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
This commit is contained in:
Adrian Roos
2018-02-21 15:17:07 +01:00
parent 78cab5a596
commit 8d13bf132c
2 changed files with 69 additions and 4 deletions

View File

@@ -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;
}
/**

View File

@@ -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();