diff options
3 files changed, 81 insertions, 7 deletions
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 66a9c6c01ca4..f59c0b5036bd 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -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; @@ -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; @@ -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 */ @@ -357,6 +362,16 @@ public final class DisplayCutout { } /** + * 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. * * @hide @@ -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; } @@ -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(); @@ -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); @@ -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; } diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java index 6e9401d7c7a0..6ee74cb9a742 100644 --- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java +++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java @@ -208,6 +208,12 @@ public class DisplayCutoutTest { } @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); assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached))); diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index a0fa69e61f20..e54b083ecdf4 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -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; @@ -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; @@ -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; @@ -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); } } @@ -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 { @@ -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) { |