Loading core/java/android/view/DisplayCutout.java +28 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.util.PathParser; import android.util.proto.ProtoOutputStream; Loading Loading @@ -75,15 +76,19 @@ public final class DisplayCutout { false /* copyArguments */); private static final Pair<Path, DisplayCutout> NULL_PAIR = new Pair<>(null, null); 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 int sCachedDisplayHeight; @GuardedBy("CACHE_LOCK") private static float sCachedDensity; @GuardedBy("CACHE_LOCK") private static DisplayCutout sCachedCutout; private static Pair<Path, DisplayCutout> sCachedCutout = NULL_PAIR; private final Rect mSafeInsets; private final Region mBounds; Loading Loading @@ -347,7 +352,7 @@ public final class DisplayCutout { } /** * Creates an instance according to @android:string/config_mainBuiltInDisplayCutout. * Creates the bounding path according to @android:string/config_mainBuiltInDisplayCutout. * * @hide */ Loading @@ -356,6 +361,16 @@ public final class DisplayCutout { displayWidth, displayHeight, res.getDisplayMetrics().density); } /** * Creates an instance according to @android:string/config_mainBuiltInDisplayCutout. * * @hide */ public static Path pathFromResources(Resources res, int displayWidth, int displayHeight) { return pathAndDisplayCutoutFromSpec(res.getString(R.string.config_mainBuiltInDisplayCutout), displayWidth, displayHeight, res.getDisplayMetrics().density).first; } /** * Creates an instance according to the supplied {@link android.util.PathParser.PathData} spec. * Loading @@ -364,11 +379,17 @@ public final class DisplayCutout { @VisibleForTesting(visibility = PRIVATE) public static DisplayCutout fromSpec(String spec, int displayWidth, int displayHeight, float density) { return pathAndDisplayCutoutFromSpec(spec, displayWidth, displayHeight, density).second; } private static Pair<Path, DisplayCutout> pathAndDisplayCutoutFromSpec(String spec, int displayWidth, int displayHeight, float density) { if (TextUtils.isEmpty(spec)) { return null; return NULL_PAIR; } synchronized (CACHE_LOCK) { if (spec.equals(sCachedSpec) && sCachedDisplayWidth == displayWidth && sCachedDisplayHeight == displayHeight && sCachedDensity == density) { return sCachedCutout; } Loading Loading @@ -398,7 +419,7 @@ public final class DisplayCutout { p = PathParser.createPathFromPathData(spec); } catch (Throwable e) { Log.wtf(TAG, "Could not inflate cutout: ", e); return null; return NULL_PAIR; } final Matrix m = new Matrix(); Loading @@ -414,7 +435,7 @@ public final class DisplayCutout { bottomPath = PathParser.createPathFromPathData(bottomSpec); } catch (Throwable e) { Log.wtf(TAG, "Could not inflate bottom cutout: ", e); return null; return NULL_PAIR; } // Keep top transform m.postTranslate(0, displayHeight); Loading @@ -422,10 +443,11 @@ public final class DisplayCutout { p.addPath(bottomPath); } final DisplayCutout result = fromBounds(p); final Pair<Path, DisplayCutout> result = new Pair<>(p, fromBounds(p)); synchronized (CACHE_LOCK) { sCachedSpec = spec; sCachedDisplayWidth = displayWidth; sCachedDisplayHeight = displayHeight; sCachedDensity = density; sCachedCutout = result; } Loading core/tests/coretests/src/android/view/DisplayCutoutTest.java +6 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,12 @@ public class DisplayCutoutTest { assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached))); } @Test public void fromSpec_wontCacheIfScreenHeightChanges() { DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 4000, 1f); assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached))); } @Test public void fromSpec_wontCacheIfDensityChanges() { DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f); Loading packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +47 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,10 @@ package com.android.systemui; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; Loading @@ -21,12 +25,14 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M import static com.android.systemui.tuner.TunablePadding.FLAG_START; import static com.android.systemui.tuner.TunablePadding.FLAG_END; import android.annotation.Dimension; import android.app.Fragment; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; Loading @@ -41,6 +47,7 @@ import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Surface; import android.view.View; import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; Loading Loading @@ -359,6 +366,7 @@ public class ScreenDecorations extends SystemUI implements Tunable { if (!mBoundingPath.isEmpty()) { mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); canvas.drawPath(mBoundingPath, mPaint); } } Loading Loading @@ -388,7 +396,7 @@ public class ScreenDecorations extends SystemUI implements Tunable { if (hasCutout()) { mBounds.set(mInfo.displayCutout.getBounds()); localBounds(mBoundingRect); mInfo.displayCutout.getBounds().getBoundaryPath(mBoundingPath); updateBoundingPath(); invalidate(); newVisible = VISIBLE; } else { Loading @@ -400,6 +408,44 @@ public class ScreenDecorations extends SystemUI implements Tunable { } } private void updateBoundingPath() { int lw = mInfo.logicalWidth; int lh = mInfo.logicalHeight; boolean flipped = mInfo.rotation == ROTATION_90 || mInfo.rotation == ROTATION_270; int dw = flipped ? lh : lw; int dh = flipped ? lw : lh; mBoundingPath.set(DisplayCutout.pathFromResources(getResources(), lw, lh)); Matrix m = new Matrix(); transformPhysicalToLogicalCoordinates(mInfo.rotation, dw, dh, m); mBoundingPath.transform(m); } private static void transformPhysicalToLogicalCoordinates(@Surface.Rotation int rotation, @Dimension int physicalWidth, @Dimension int physicalHeight, Matrix out) { switch (rotation) { case ROTATION_0: out.reset(); break; case ROTATION_90: out.setRotate(270); out.postTranslate(0, physicalWidth); break; case ROTATION_180: out.setRotate(180); out.postTranslate(physicalWidth, physicalHeight); break; case ROTATION_270: out.setRotate(90); out.postTranslate(physicalHeight, 0); break; default: throw new IllegalArgumentException("Unknown rotation: " + rotation); } } private boolean hasCutout() { final DisplayCutout displayCutout = mInfo.displayCutout; if (displayCutout == null) { Loading Loading
core/java/android/view/DisplayCutout.java +28 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.util.PathParser; import android.util.proto.ProtoOutputStream; Loading Loading @@ -75,15 +76,19 @@ public final class DisplayCutout { false /* copyArguments */); private static final Pair<Path, DisplayCutout> NULL_PAIR = new Pair<>(null, null); 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 int sCachedDisplayHeight; @GuardedBy("CACHE_LOCK") private static float sCachedDensity; @GuardedBy("CACHE_LOCK") private static DisplayCutout sCachedCutout; private static Pair<Path, DisplayCutout> sCachedCutout = NULL_PAIR; private final Rect mSafeInsets; private final Region mBounds; Loading Loading @@ -347,7 +352,7 @@ public final class DisplayCutout { } /** * Creates an instance according to @android:string/config_mainBuiltInDisplayCutout. * Creates the bounding path according to @android:string/config_mainBuiltInDisplayCutout. * * @hide */ Loading @@ -356,6 +361,16 @@ public final class DisplayCutout { displayWidth, displayHeight, res.getDisplayMetrics().density); } /** * Creates an instance according to @android:string/config_mainBuiltInDisplayCutout. * * @hide */ public static Path pathFromResources(Resources res, int displayWidth, int displayHeight) { return pathAndDisplayCutoutFromSpec(res.getString(R.string.config_mainBuiltInDisplayCutout), displayWidth, displayHeight, res.getDisplayMetrics().density).first; } /** * Creates an instance according to the supplied {@link android.util.PathParser.PathData} spec. * Loading @@ -364,11 +379,17 @@ public final class DisplayCutout { @VisibleForTesting(visibility = PRIVATE) public static DisplayCutout fromSpec(String spec, int displayWidth, int displayHeight, float density) { return pathAndDisplayCutoutFromSpec(spec, displayWidth, displayHeight, density).second; } private static Pair<Path, DisplayCutout> pathAndDisplayCutoutFromSpec(String spec, int displayWidth, int displayHeight, float density) { if (TextUtils.isEmpty(spec)) { return null; return NULL_PAIR; } synchronized (CACHE_LOCK) { if (spec.equals(sCachedSpec) && sCachedDisplayWidth == displayWidth && sCachedDisplayHeight == displayHeight && sCachedDensity == density) { return sCachedCutout; } Loading Loading @@ -398,7 +419,7 @@ public final class DisplayCutout { p = PathParser.createPathFromPathData(spec); } catch (Throwable e) { Log.wtf(TAG, "Could not inflate cutout: ", e); return null; return NULL_PAIR; } final Matrix m = new Matrix(); Loading @@ -414,7 +435,7 @@ public final class DisplayCutout { bottomPath = PathParser.createPathFromPathData(bottomSpec); } catch (Throwable e) { Log.wtf(TAG, "Could not inflate bottom cutout: ", e); return null; return NULL_PAIR; } // Keep top transform m.postTranslate(0, displayHeight); Loading @@ -422,10 +443,11 @@ public final class DisplayCutout { p.addPath(bottomPath); } final DisplayCutout result = fromBounds(p); final Pair<Path, DisplayCutout> result = new Pair<>(p, fromBounds(p)); synchronized (CACHE_LOCK) { sCachedSpec = spec; sCachedDisplayWidth = displayWidth; sCachedDisplayHeight = displayHeight; sCachedDensity = density; sCachedCutout = result; } Loading
core/tests/coretests/src/android/view/DisplayCutoutTest.java +6 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,12 @@ public class DisplayCutoutTest { assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached))); } @Test public void fromSpec_wontCacheIfScreenHeightChanges() { DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 4000, 1f); assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached))); } @Test public void fromSpec_wontCacheIfDensityChanges() { DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f); Loading
packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +47 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,10 @@ package com.android.systemui; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; Loading @@ -21,12 +25,14 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M import static com.android.systemui.tuner.TunablePadding.FLAG_START; import static com.android.systemui.tuner.TunablePadding.FLAG_END; import android.annotation.Dimension; import android.app.Fragment; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; Loading @@ -41,6 +47,7 @@ import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Surface; import android.view.View; import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; Loading Loading @@ -359,6 +366,7 @@ public class ScreenDecorations extends SystemUI implements Tunable { if (!mBoundingPath.isEmpty()) { mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); canvas.drawPath(mBoundingPath, mPaint); } } Loading Loading @@ -388,7 +396,7 @@ public class ScreenDecorations extends SystemUI implements Tunable { if (hasCutout()) { mBounds.set(mInfo.displayCutout.getBounds()); localBounds(mBoundingRect); mInfo.displayCutout.getBounds().getBoundaryPath(mBoundingPath); updateBoundingPath(); invalidate(); newVisible = VISIBLE; } else { Loading @@ -400,6 +408,44 @@ public class ScreenDecorations extends SystemUI implements Tunable { } } private void updateBoundingPath() { int lw = mInfo.logicalWidth; int lh = mInfo.logicalHeight; boolean flipped = mInfo.rotation == ROTATION_90 || mInfo.rotation == ROTATION_270; int dw = flipped ? lh : lw; int dh = flipped ? lw : lh; mBoundingPath.set(DisplayCutout.pathFromResources(getResources(), lw, lh)); Matrix m = new Matrix(); transformPhysicalToLogicalCoordinates(mInfo.rotation, dw, dh, m); mBoundingPath.transform(m); } private static void transformPhysicalToLogicalCoordinates(@Surface.Rotation int rotation, @Dimension int physicalWidth, @Dimension int physicalHeight, Matrix out) { switch (rotation) { case ROTATION_0: out.reset(); break; case ROTATION_90: out.setRotate(270); out.postTranslate(0, physicalWidth); break; case ROTATION_180: out.setRotate(180); out.postTranslate(physicalWidth, physicalHeight); break; case ROTATION_270: out.setRotate(90); out.postTranslate(physicalHeight, 0); break; default: throw new IllegalArgumentException("Unknown rotation: " + rotation); } } private boolean hasCutout() { final DisplayCutout displayCutout = mInfo.displayCutout; if (displayCutout == null) { Loading