From 8d13bf132ce2ce5533da752d56e9f578c65ebbb3 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Wed, 21 Feb 2018 15:17:07 +0100 Subject: DisplayCutout: Cache inflations from resources Caches inflations from resources if the parameters did not change. This increases the hitrate of the rotation variants cache in window manager, and avoids unnecessairy reinflations whenever the display changes. Change-Id: I2ed9a2c259158bf1a6b551b3422534efbfec99c9 Bug: 72444324 Test: atest DisplayCutoutTest --- core/java/android/view/DisplayCutout.java | 45 ++++++++++++++++++++-- .../src/android/view/DisplayCutoutTest.java | 28 ++++++++++++++ 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 272303099193..f5b7068998d6 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -23,6 +23,8 @@ import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; + import android.content.res.Resources; import android.graphics.Matrix; import android.graphics.Path; @@ -38,6 +40,7 @@ import android.util.Size; import android.util.proto.ProtoOutputStream; import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.Objects; @@ -73,6 +76,17 @@ public final class DisplayCutout { public static final DisplayCutout NO_CUTOUT = new DisplayCutout(ZERO_RECT, EMPTY_REGION, new Size(0, 0)); + + private static final Object CACHE_LOCK = new Object(); + @GuardedBy("CACHE_LOCK") + private static String sCachedSpec; + @GuardedBy("CACHE_LOCK") + private static int sCachedDisplayWidth; + @GuardedBy("CACHE_LOCK") + private static float sCachedDensity; + @GuardedBy("CACHE_LOCK") + private static DisplayCutout sCachedCutout; + private final Rect mSafeInsets; private final Region mBounds; private final Size mFrameSize; @@ -350,10 +364,26 @@ public final class DisplayCutout { * @hide */ public static DisplayCutout fromResources(Resources res, int displayWidth) { - String spec = res.getString(R.string.config_mainBuiltInDisplayCutout); + return fromSpec(res.getString(R.string.config_mainBuiltInDisplayCutout), + displayWidth, res.getDisplayMetrics().density); + } + + /** + * Creates an instance according to the supplied {@link android.util.PathParser.PathData} spec. + * + * @hide + */ + @VisibleForTesting(visibility = PRIVATE) + public static DisplayCutout fromSpec(String spec, int displayWidth, float density) { if (TextUtils.isEmpty(spec)) { return null; } + synchronized (CACHE_LOCK) { + if (spec.equals(sCachedSpec) && sCachedDisplayWidth == displayWidth + && sCachedDensity == density) { + return sCachedCutout; + } + } spec = spec.trim(); final boolean inDp = spec.endsWith(DP_MARKER); if (inDp) { @@ -370,12 +400,19 @@ public final class DisplayCutout { final Matrix m = new Matrix(); if (inDp) { - final float dpToPx = res.getDisplayMetrics().density; - m.postScale(dpToPx, dpToPx); + m.postScale(density, density); } m.postTranslate(displayWidth / 2f, 0); p.transform(m); - return fromBounds(p); + + final DisplayCutout result = fromBounds(p); + synchronized (CACHE_LOCK) { + sCachedSpec = spec; + sCachedDisplayWidth = displayWidth; + sCachedDensity = density; + sCachedCutout = result; + } + return result; } /** diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java index ee4bc34d0876..d80735326568 100644 --- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java +++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java @@ -18,10 +18,14 @@ package android.view; import static android.view.DisplayCutout.NO_CUTOUT; import static android.view.DisplayCutout.fromBoundingRect; +import static android.view.DisplayCutout.fromSpec; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import android.graphics.Rect; @@ -270,6 +274,30 @@ public class DisplayCutoutTest { assertEquals(posAfterWrite, p.dataPosition()); } + @Test + public void fromSpec_caches() { + DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 1f); + assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 1f), sameInstance(cached)); + } + + @Test + public void fromSpec_wontCacheIfSpecChanges() { + DisplayCutout cached = fromSpec("L1,0 L1000,1000 L0,1 z", 200, 1f); + assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 1f), not(sameInstance(cached))); + } + + @Test + public void fromSpec_wontCacheIfScreenWidthChanges() { + DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 2000, 1f); + assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 1f), not(sameInstance(cached))); + } + + @Test + public void fromSpec_wontCacheIfDensityChanges() { + DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 2f); + assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 1f), not(sameInstance(cached))); + } + @Test public void parcel_unparcel_nocutout() { Parcel p = Parcel.obtain(); -- cgit v1.2.3-59-g8ed1b