diff options
| -rw-r--r-- | api/current.txt | 12 | ||||
| -rw-r--r-- | core/java/android/view/DisplayCutout.java | 145 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/WindowInsets.java | 31 | ||||
| -rw-r--r-- | core/java/android/view/WindowManager.java | 13 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/DisplayCutoutTest.java | 112 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java | 32 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java | 6 |
8 files changed, 137 insertions, 216 deletions
diff --git a/api/current.txt b/api/current.txt index c8a85d4bf009..b719bd20775f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -44718,6 +44718,14 @@ package android.view { field public static final android.os.Parcelable.Creator<android.view.Display.Mode> CREATOR; } + public final class DisplayCutout { + method public android.graphics.Region getBounds(); + method public int getSafeInsetBottom(); + method public int getSafeInsetLeft(); + method public int getSafeInsetRight(); + method public int getSafeInsetTop(); + } + public final class DragAndDropPermissions implements android.os.Parcelable { method public int describeContents(); method public void release(); @@ -47671,8 +47679,10 @@ package android.view { public final class WindowInsets { ctor public WindowInsets(android.view.WindowInsets); + method public android.view.WindowInsets consumeDisplayCutout(); method public android.view.WindowInsets consumeStableInsets(); method public android.view.WindowInsets consumeSystemWindowInsets(); + method public android.view.DisplayCutout getDisplayCutout(); method public int getStableInsetBottom(); method public int getStableInsetLeft(); method public int getStableInsetRight(); @@ -47732,6 +47742,7 @@ package android.view { field public static final int FIRST_APPLICATION_WINDOW = 1; // 0x1 field public static final int FIRST_SUB_WINDOW = 1000; // 0x3e8 field public static final int FIRST_SYSTEM_WINDOW = 2000; // 0x7d0 + field public static final long FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA = 1L; // 0x1L field public static final int FLAGS_CHANGED = 4; // 0x4 field public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 1; // 0x1 field public static final int FLAG_ALT_FOCUSABLE_IM = 131072; // 0x20000 @@ -47826,6 +47837,7 @@ package android.view { field public float buttonBrightness; field public float dimAmount; field public int flags; + field public long flags2; field public int format; field public int gravity; field public float horizontalMargin; diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 19cd42e1fa18..e448f14ca97d 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -21,40 +21,37 @@ import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; -import android.annotation.NonNull; +import android.graphics.Path; import android.graphics.Point; import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; -import java.util.ArrayList; import java.util.List; /** * Represents a part of the display that is not functional for displaying content. * * <p>{@code DisplayCutout} is immutable. - * - * @hide will become API */ public final class DisplayCutout { - private static final Rect ZERO_RECT = new Rect(0, 0, 0, 0); - private static final ArrayList<Point> EMPTY_LIST = new ArrayList<>(); + private static final Rect ZERO_RECT = new Rect(); + private static final Region EMPTY_REGION = new Region(); /** - * An instance where {@link #hasCutout()} returns {@code false}. + * An instance where {@link #isEmpty()} returns {@code true}. * * @hide */ - public static final DisplayCutout NO_CUTOUT = - new DisplayCutout(ZERO_RECT, ZERO_RECT, EMPTY_LIST); + public static final DisplayCutout NO_CUTOUT = new DisplayCutout(ZERO_RECT, EMPTY_REGION); private final Rect mSafeInsets; - private final Rect mBoundingRect; - private final List<Point> mBoundingPolygon; + private final Region mBounds; /** * Creates a DisplayCutout instance. @@ -64,22 +61,18 @@ public final class DisplayCutout { * @hide */ @VisibleForTesting - public DisplayCutout(Rect safeInsets, Rect boundingRect, List<Point> boundingPolygon) { + public DisplayCutout(Rect safeInsets, Region bounds) { mSafeInsets = safeInsets != null ? safeInsets : ZERO_RECT; - mBoundingRect = boundingRect != null ? boundingRect : ZERO_RECT; - mBoundingPolygon = boundingPolygon != null ? boundingPolygon : EMPTY_LIST; + mBounds = bounds != null ? bounds : Region.obtain(); } /** - * Returns whether there is a cutout. - * - * If false, the safe insets will all return zero, and the bounding box or polygon will be - * empty or outside the content view. + * Returns true if there is no cutout or it is outside of the content view. * - * @return {@code true} if there is a cutout, {@code false} otherwise + * @hide */ - public boolean hasCutout() { - return !mSafeInsets.equals(ZERO_RECT); + public boolean isEmpty() { + return mSafeInsets.equals(ZERO_RECT); } /** Returns the inset from the top which avoids the display cutout. */ @@ -103,44 +96,41 @@ public final class DisplayCutout { } /** - * Obtains the safe insets in a rect. + * Returns the safe insets in a rect. * - * @param out a rect which is set to the safe insets. + * @return a rect which is set to the safe insets. * @hide */ - public void getSafeInsets(@NonNull Rect out) { - out.set(mSafeInsets); + public Rect getSafeInsets() { + return new Rect(mSafeInsets); } /** - * Obtains the bounding rect of the cutout. + * Returns the bounding region of the cutout. * - * @param outRect is filled with the bounding rect of the cutout. Coordinates are relative + * @return the bounding region of the cutout. Coordinates are relative * to the top-left corner of the content view. */ - public void getBoundingRect(@NonNull Rect outRect) { - outRect.set(mBoundingRect); + public Region getBounds() { + return Region.obtain(mBounds); } /** - * Obtains the bounding polygon of the cutout. + * Returns the bounding rect of the cutout. * - * @param outPolygon is filled with a list of points representing the corners of a convex - * polygon which covers the cutout. Coordinates are relative to the - * top-left corner of the content view. + * @return the bounding rect of the cutout. Coordinates are relative + * to the top-left corner of the content view. + * @hide */ - public void getBoundingPolygon(List<Point> outPolygon) { - outPolygon.clear(); - for (int i = 0; i < mBoundingPolygon.size(); i++) { - outPolygon.add(new Point(mBoundingPolygon.get(i))); - } + public Rect getBoundingRect() { + // TODO(roosa): Inline. + return mBounds.getBounds(); } @Override public int hashCode() { int result = mSafeInsets.hashCode(); - result = result * 31 + mBoundingRect.hashCode(); - result = result * 31 + mBoundingPolygon.hashCode(); + result = result * 31 + mBounds.getBounds().hashCode(); return result; } @@ -152,8 +142,7 @@ public final class DisplayCutout { if (o instanceof DisplayCutout) { DisplayCutout c = (DisplayCutout) o; return mSafeInsets.equals(c.mSafeInsets) - && mBoundingRect.equals(c.mBoundingRect) - && mBoundingPolygon.equals(c.mBoundingPolygon); + && mBounds.equals(c.mBounds); } return false; } @@ -161,7 +150,7 @@ public final class DisplayCutout { @Override public String toString() { return "DisplayCutout{insets=" + mSafeInsets - + " bounding=" + mBoundingRect + + " bounds=" + mBounds + "}"; } @@ -172,15 +161,13 @@ public final class DisplayCutout { * @hide */ public DisplayCutout inset(int insetLeft, int insetTop, int insetRight, int insetBottom) { - if (mBoundingRect.isEmpty() + if (mBounds.isEmpty() || insetLeft == 0 && insetTop == 0 && insetRight == 0 && insetBottom == 0) { return this; } Rect safeInsets = new Rect(mSafeInsets); - Rect boundingRect = new Rect(mBoundingRect); - ArrayList<Point> boundingPolygon = new ArrayList<>(); - getBoundingPolygon(boundingPolygon); + Region bounds = Region.obtain(mBounds); // Note: it's not really well defined what happens when the inset is negative, because we // don't know if the safe inset needs to expand in general. @@ -197,10 +184,9 @@ public final class DisplayCutout { safeInsets.right = atLeastZero(safeInsets.right - insetRight); } - boundingRect.offset(-insetLeft, -insetTop); - offset(boundingPolygon, -insetLeft, -insetTop); + bounds.translate(-insetLeft, -insetTop); - return new DisplayCutout(safeInsets, boundingRect, boundingPolygon); + return new DisplayCutout(safeInsets, bounds); } /** @@ -210,20 +196,17 @@ public final class DisplayCutout { * @hide */ public DisplayCutout calculateRelativeTo(Rect frame) { - if (mBoundingRect.isEmpty() || !Rect.intersects(frame, mBoundingRect)) { + if (mBounds.isEmpty() || !Rect.intersects(frame, mBounds.getBounds())) { return NO_CUTOUT; } - Rect boundingRect = new Rect(mBoundingRect); - ArrayList<Point> boundingPolygon = new ArrayList<>(); - getBoundingPolygon(boundingPolygon); - - return DisplayCutout.calculateRelativeTo(frame, boundingRect, boundingPolygon); + return DisplayCutout.calculateRelativeTo(frame, Region.obtain(mBounds)); } - private static DisplayCutout calculateRelativeTo(Rect frame, Rect boundingRect, - ArrayList<Point> boundingPolygon) { + private static DisplayCutout calculateRelativeTo(Rect frame, Region bounds) { + Rect boundingRect = bounds.getBounds(); Rect safeRect = new Rect(); + int bestArea = 0; int bestVariant = 0; for (int variant = ROTATION_0; variant <= ROTATION_270; variant++) { @@ -247,10 +230,9 @@ public final class DisplayCutout { Math.max(0, frame.bottom - safeRect.bottom)); } - boundingRect.offset(-frame.left, -frame.top); - offset(boundingPolygon, -frame.left, -frame.top); + bounds.translate(-frame.left, -frame.top); - return new DisplayCutout(safeRect, boundingRect, boundingPolygon); + return new DisplayCutout(safeRect, bounds); } private static int calculateInsetVariantArea(Rect frame, Rect boundingRect, int variant, @@ -277,11 +259,6 @@ public final class DisplayCutout { return value < 0 ? 0 : value; } - private static void offset(ArrayList<Point> points, int dx, int dy) { - for (int i = 0; i < points.size(); i++) { - points.get(i).offset(dx, dy); - } - } /** * Creates an instance from a bounding polygon. @@ -289,20 +266,28 @@ public final class DisplayCutout { * @hide */ public static DisplayCutout fromBoundingPolygon(List<Point> points) { - Rect boundingRect = new Rect(Integer.MAX_VALUE, Integer.MAX_VALUE, - Integer.MIN_VALUE, Integer.MIN_VALUE); - ArrayList<Point> boundingPolygon = new ArrayList<>(); + Region bounds = Region.obtain(); + Path path = new Path(); + path.reset(); for (int i = 0; i < points.size(); i++) { Point point = points.get(i); - boundingRect.left = Math.min(boundingRect.left, point.x); - boundingRect.right = Math.max(boundingRect.right, point.x); - boundingRect.top = Math.min(boundingRect.top, point.y); - boundingRect.bottom = Math.max(boundingRect.bottom, point.y); - boundingPolygon.add(new Point(point)); + if (i == 0) { + path.moveTo(point.x, point.y); + } else { + path.lineTo(point.x, point.y); + } } + path.close(); + + RectF clipRect = new RectF(); + path.computeBounds(clipRect, false /* unused */); + Region clipRegion = Region.obtain(); + clipRegion.set((int) clipRect.left, (int) clipRect.top, + (int) clipRect.right, (int) clipRect.bottom); - return new DisplayCutout(ZERO_RECT, boundingRect, boundingPolygon); + bounds.setPath(path, clipRegion); + return new DisplayCutout(ZERO_RECT, bounds); } /** @@ -336,8 +321,7 @@ public final class DisplayCutout { } else { out.writeInt(1); out.writeTypedObject(mInner.mSafeInsets, flags); - out.writeTypedObject(mInner.mBoundingRect, flags); - out.writeTypedList(mInner.mBoundingPolygon, flags); + out.writeTypedObject(mInner.mBounds, flags); } } @@ -368,13 +352,10 @@ public final class DisplayCutout { return NO_CUTOUT; } - ArrayList<Point> boundingPolygon = new ArrayList<>(); - Rect safeInsets = in.readTypedObject(Rect.CREATOR); - Rect boundingRect = in.readTypedObject(Rect.CREATOR); - in.readTypedList(boundingPolygon, Point.CREATOR); + Region bounds = in.readTypedObject(Region.CREATOR); - return new DisplayCutout(safeInsets, boundingRect, boundingPolygon); + return new DisplayCutout(safeInsets, bounds); } public DisplayCutout get() { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 2c82ac49c84e..6c5091c28708 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1602,7 +1602,7 @@ public final class ViewRootImpl implements ViewParent, if (!layoutInCutout) { // Window is either not laid out in cutout or the status bar inset takes care of // clearing the cutout, so we don't need to dispatch the cutout to the hierarchy. - insets = insets.consumeCutout(); + insets = insets.consumeDisplayCutout(); } host.dispatchApplyWindowInsets(insets); } diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index df124ac5be28..e5cbe96b9173 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -17,7 +17,7 @@ package android.view; -import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Rect; /** @@ -49,7 +49,7 @@ public final class WindowInsets { private boolean mSystemWindowInsetsConsumed = false; private boolean mWindowDecorInsetsConsumed = false; private boolean mStableInsetsConsumed = false; - private boolean mCutoutConsumed = false; + private boolean mDisplayCutoutConsumed = false; private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0); @@ -80,8 +80,9 @@ public final class WindowInsets { mIsRound = isRound; mAlwaysConsumeNavBar = alwaysConsumeNavBar; - mCutoutConsumed = displayCutout == null; - mDisplayCutout = mCutoutConsumed ? DisplayCutout.NO_CUTOUT : displayCutout; + mDisplayCutoutConsumed = displayCutout == null; + mDisplayCutout = (mDisplayCutoutConsumed || displayCutout.isEmpty()) + ? null : displayCutout; } /** @@ -99,7 +100,7 @@ public final class WindowInsets { mIsRound = src.mIsRound; mAlwaysConsumeNavBar = src.mAlwaysConsumeNavBar; mDisplayCutout = src.mDisplayCutout; - mCutoutConsumed = src.mCutoutConsumed; + mDisplayCutoutConsumed = src.mDisplayCutoutConsumed; } /** @hide */ @@ -269,15 +270,16 @@ public final class WindowInsets { */ public boolean hasInsets() { return hasSystemWindowInsets() || hasWindowDecorInsets() || hasStableInsets() - || mDisplayCutout.hasCutout(); + || mDisplayCutout != null; } /** - * @return the display cutout + * Returns the display cutout if there is one. + * + * @return the display cutout or null if there is none * @see DisplayCutout - * @hide pending API */ - @NonNull + @Nullable public DisplayCutout getDisplayCutout() { return mDisplayCutout; } @@ -286,12 +288,11 @@ public final class WindowInsets { * Returns a copy of this WindowInsets with the cutout fully consumed. * * @return A modified copy of this WindowInsets - * @hide pending API */ - public WindowInsets consumeCutout() { + public WindowInsets consumeDisplayCutout() { final WindowInsets result = new WindowInsets(this); - result.mDisplayCutout = DisplayCutout.NO_CUTOUT; - result.mCutoutConsumed = true; + result.mDisplayCutout = null; + result.mDisplayCutoutConsumed = true; return result; } @@ -311,7 +312,7 @@ public final class WindowInsets { */ public boolean isConsumed() { return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed - && mCutoutConsumed; + && mDisplayCutoutConsumed; } /** @@ -530,7 +531,7 @@ public final class WindowInsets { return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets + " windowDecorInsets=" + mWindowDecorInsets + " stableInsets=" + mStableInsets - + (mDisplayCutout.hasCutout() ? " cutout=" + mDisplayCutout : "") + + (mDisplayCutout != null ? " cutout=" + mDisplayCutout : "") + (isRound() ? " round" : "") + "}"; } diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 012e86406579..cbe012af0b21 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1286,7 +1286,6 @@ public interface WindowManager extends ViewManager { * The window must correctly position its contents to take the display cutout into account. * * @see DisplayCutout - * @hide for now */ public static final long FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA = 0x00000001; @@ -1294,7 +1293,6 @@ public interface WindowManager extends ViewManager { * Various behavioral options/flags. Default is none. * * @see #FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA - * @hide for now */ @Flags2 public long flags2; @@ -2249,6 +2247,7 @@ public interface WindowManager extends ViewManager { out.writeInt(y); out.writeInt(type); out.writeInt(flags); + out.writeLong(flags2); out.writeInt(privateFlags); out.writeInt(softInputMode); out.writeInt(gravity); @@ -2304,6 +2303,7 @@ public interface WindowManager extends ViewManager { y = in.readInt(); type = in.readInt(); flags = in.readInt(); + flags2 = in.readLong(); privateFlags = in.readInt(); softInputMode = in.readInt(); gravity = in.readInt(); @@ -2436,6 +2436,10 @@ public interface WindowManager extends ViewManager { flags = o.flags; changes |= FLAGS_CHANGED; } + if (flags2 != o.flags2) { + flags2 = o.flags2; + changes |= FLAGS_CHANGED; + } if (privateFlags != o.privateFlags) { privateFlags = o.privateFlags; changes |= PRIVATE_FLAGS_CHANGED; @@ -2689,6 +2693,11 @@ public interface WindowManager extends ViewManager { sb.append(System.lineSeparator()); sb.append(prefix).append(" fl=").append( ViewDebug.flagsToString(LayoutParams.class, "flags", flags)); + if (flags2 != 0) { + sb.append(System.lineSeparator()); + // TODO(roosa): add a long overload for ViewDebug.flagsToString. + sb.append(prefix).append(" fl2=0x").append(Long.toHexString(flags2)); + } if (privateFlags != 0) { sb.append(System.lineSeparator()); sb.append(prefix).append(" pfl=").append(ViewDebug.flagsToString( diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java index 6dd787d2e038..0d8c679a312f 100644 --- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java +++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java @@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue; import android.graphics.Point; import android.graphics.Rect; +import android.graphics.Region; import android.os.Parcel; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; @@ -34,7 +35,6 @@ import android.view.DisplayCutout.ParcelableWrapper; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.ArrayList; import java.util.Arrays; @RunWith(AndroidJUnit4.class) @@ -45,19 +45,14 @@ public class DisplayCutoutTest { /** This is not a consistent cutout. Useful for verifying insets in one go though. */ final DisplayCutout mCutoutNumbers = new DisplayCutout( new Rect(1, 2, 3, 4), - new Rect(5, 6, 7, 8), - Arrays.asList( - new Point(9, 10), - new Point(11, 12), - new Point(13, 14), - new Point(15, 16))); + new Region(5, 6, 7, 8)); final DisplayCutout mCutoutTop = createCutoutTop(); @Test public void hasCutout() throws Exception { - assertFalse(NO_CUTOUT.hasCutout()); - assertTrue(mCutoutTop.hasCutout()); + assertTrue(NO_CUTOUT.isEmpty()); + assertFalse(mCutoutTop.isEmpty()); } @Test @@ -67,30 +62,12 @@ public class DisplayCutoutTest { assertEquals(3, mCutoutNumbers.getSafeInsetRight()); assertEquals(4, mCutoutNumbers.getSafeInsetBottom()); - Rect safeInsets = new Rect(); - mCutoutNumbers.getSafeInsets(safeInsets); - - assertEquals(new Rect(1, 2, 3, 4), safeInsets); + assertEquals(new Rect(1, 2, 3, 4), mCutoutNumbers.getSafeInsets()); } @Test public void getBoundingRect() throws Exception { - Rect boundingRect = new Rect(); - mCutoutTop.getBoundingRect(boundingRect); - - assertEquals(new Rect(50, 0, 75, 100), boundingRect); - } - - @Test - public void getBoundingPolygon() throws Exception { - ArrayList<Point> boundingPolygon = new ArrayList<>(); - mCutoutTop.getBoundingPolygon(boundingPolygon); - - assertEquals(Arrays.asList( - new Point(75, 0), - new Point(50, 0), - new Point(75, 100), - new Point(50, 100)), boundingPolygon); + assertEquals(new Rect(50, 0, 75, 100), mCutoutTop.getBoundingRect()); } @Test @@ -167,104 +144,61 @@ public class DisplayCutoutTest { assertEquals(cutout.getSafeInsetRight(), 0); assertEquals(cutout.getSafeInsetBottom(), 0); - assertFalse(cutout.hasCutout()); + assertTrue(cutout.isEmpty()); } @Test public void inset_bounds() throws Exception { DisplayCutout cutout = mCutoutTop.inset(1, 2, 3, 4); - Rect boundingRect = new Rect(); - cutout.getBoundingRect(boundingRect); - - assertEquals(new Rect(49, -2, 74, 98), boundingRect); - - ArrayList<Point> boundingPolygon = new ArrayList<>(); - cutout.getBoundingPolygon(boundingPolygon); - - assertEquals(Arrays.asList( - new Point(74, -2), - new Point(49, -2), - new Point(74, 98), - new Point(49, 98)), boundingPolygon); + assertEquals(new Rect(49, -2, 74, 98), cutout.getBoundingRect()); } @Test public void calculateRelativeTo_top() throws Exception { DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(0, 0, 200, 400)); - Rect insets = new Rect(); - cutout.getSafeInsets(insets); - - assertEquals(new Rect(0, 100, 0, 0), insets); + assertEquals(new Rect(0, 100, 0, 0), cutout.getSafeInsets()); } @Test public void calculateRelativeTo_left() throws Exception { DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(0, 0, 400, 200)); - Rect insets = new Rect(); - cutout.getSafeInsets(insets); - - assertEquals(new Rect(75, 0, 0, 0), insets); + assertEquals(new Rect(75, 0, 0, 0), cutout.getSafeInsets()); } @Test public void calculateRelativeTo_bottom() throws Exception { DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(0, -300, 200, 100)); - Rect insets = new Rect(); - cutout.getSafeInsets(insets); - - assertEquals(new Rect(0, 0, 0, 100), insets); + assertEquals(new Rect(0, 0, 0, 100), cutout.getSafeInsets()); } @Test public void calculateRelativeTo_right() throws Exception { DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(-400, -200, 100, 100)); - Rect insets = new Rect(); - cutout.getSafeInsets(insets); - - assertEquals(new Rect(0, 0, 50, 0), insets); + assertEquals(new Rect(0, 0, 50, 0), cutout.getSafeInsets()); } @Test public void calculateRelativeTo_bounds() throws Exception { DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(-1000, -2000, 100, 200)); - - Rect boundingRect = new Rect(); - cutout.getBoundingRect(boundingRect); - assertEquals(new Rect(1050, 2000, 1075, 2100), boundingRect); - - ArrayList<Point> boundingPolygon = new ArrayList<>(); - cutout.getBoundingPolygon(boundingPolygon); - - assertEquals(Arrays.asList( - new Point(1075, 2000), - new Point(1050, 2000), - new Point(1075, 2100), - new Point(1050, 2100)), boundingPolygon); + assertEquals(new Rect(1050, 2000, 1075, 2100), cutout.getBoundingRect()); } @Test public void fromBoundingPolygon() throws Exception { assertEquals( - new DisplayCutout( - new Rect(0, 0, 0, 0), // fromBoundingPolygon won't calculate safe insets. - new Rect(50, 0, 75, 100), - Arrays.asList( - new Point(75, 0), - new Point(50, 0), - new Point(75, 100), - new Point(50, 100))), + new Rect(50, 0, 75, 100), DisplayCutout.fromBoundingPolygon( Arrays.asList( new Point(75, 0), new Point(50, 0), new Point(75, 100), - new Point(50, 100)))); + new Point(50, 100))).getBounds().getBounds()); } @Test @@ -324,24 +258,12 @@ public class DisplayCutoutTest { } private static DisplayCutout createCutoutTop() { - return new DisplayCutout( - new Rect(0, 100, 0, 0), - new Rect(50, 0, 75, 100), - Arrays.asList( - new Point(75, 0), - new Point(50, 0), - new Point(75, 100), - new Point(50, 100))); + return createCutoutWithInsets(0, 100, 0, 0); } private static DisplayCutout createCutoutWithInsets(int left, int top, int right, int bottom) { return new DisplayCutout( new Rect(left, top, right, bottom), - new Rect(50, 0, 75, 100), - Arrays.asList( - new Point(75, 0), - new Point(50, 0), - new Point(75, 100), - new Point(50, 100))); + new Region(50, 0, 75, 100)); } } diff --git a/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java b/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java index edd1748c7380..6aa465ce9f8c 100644 --- a/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java +++ b/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java @@ -24,6 +24,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.Point; +import android.graphics.Region; import android.os.Handler; import android.os.Looper; import android.os.UserHandle; @@ -36,7 +37,8 @@ import android.view.ViewGroup.LayoutParams; import android.view.WindowInsets; import android.view.WindowManager; -import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * Emulates a display cutout by drawing its shape in an overlay as supplied by @@ -85,6 +87,7 @@ public class EmulatedDisplayCutout extends SystemUI { PixelFormat.TRANSLUCENT); lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS | WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; + lp.flags2 |= WindowManager.LayoutParams.FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA; lp.setTitle("EmulatedDisplayCutout"); lp.gravity = Gravity.TOP; return lp; @@ -102,9 +105,8 @@ public class EmulatedDisplayCutout extends SystemUI { }; private static class CutoutView extends View { - private Paint mPaint = new Paint(); - private Path mPath = new Path(); - private ArrayList<Point> mBoundingPolygon = new ArrayList<>(); + private final Paint mPaint = new Paint(); + private final Path mBounds = new Path(); CutoutView(Context context) { super(context); @@ -112,28 +114,22 @@ public class EmulatedDisplayCutout extends SystemUI { @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { - insets.getDisplayCutout().getBoundingPolygon(mBoundingPolygon); + if (insets.getDisplayCutout() != null) { + insets.getDisplayCutout().getBounds().getBoundaryPath(mBounds); + } else { + mBounds.reset(); + } invalidate(); - return insets.consumeCutout(); + return insets.consumeDisplayCutout(); } @Override protected void onDraw(Canvas canvas) { - if (!mBoundingPolygon.isEmpty()) { + if (!mBounds.isEmpty()) { mPaint.setColor(Color.DKGRAY); mPaint.setStyle(Paint.Style.FILL); - mPath.reset(); - for (int i = 0; i < mBoundingPolygon.size(); i++) { - Point point = mBoundingPolygon.get(i); - if (i == 0) { - mPath.moveTo(point.x, point.y); - } else { - mPath.lineTo(point.x, point.y); - } - } - mPath.close(); - canvas.drawPath(mPath, mPaint); + canvas.drawPath(mBounds, mPaint); } } } diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java index 337fd50a88d4..0959df2b78bd 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java @@ -451,9 +451,9 @@ public class WindowFrameTests extends WindowTestsBase { private DisplayCutout createDisplayCutoutFromRect(int left, int top, int right, int bottom) { return DisplayCutout.fromBoundingPolygon(Arrays.asList( new Point(left, top), - new Point (left, bottom), - new Point (right, bottom), - new Point (left, bottom) + new Point(left, bottom), + new Point(right, bottom), + new Point(right, top) )); } } |