Loading api/current.txt +12 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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; core/java/android/view/DisplayCutout.java +63 −82 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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. */ Loading @@ -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; } Loading @@ -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; } Loading @@ -161,7 +150,7 @@ public final class DisplayCutout { @Override public String toString() { return "DisplayCutout{insets=" + mSafeInsets + " bounding=" + mBoundingRect + " bounds=" + mBounds + "}"; } Loading @@ -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. Loading @@ -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); } /** Loading @@ -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++) { Loading @@ -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, Loading @@ -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. Loading @@ -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); } /** Loading Loading @@ -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); } } Loading Loading @@ -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() { Loading core/java/android/view/ViewRootImpl.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading core/java/android/view/WindowInsets.java +16 −15 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ package android.view; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Rect; /** Loading Loading @@ -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); Loading Loading @@ -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; } /** Loading @@ -99,7 +100,7 @@ public final class WindowInsets { mIsRound = src.mIsRound; mAlwaysConsumeNavBar = src.mAlwaysConsumeNavBar; mDisplayCutout = src.mDisplayCutout; mCutoutConsumed = src.mCutoutConsumed; mDisplayCutoutConsumed = src.mDisplayCutoutConsumed; } /** @hide */ Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -311,7 +312,7 @@ public final class WindowInsets { */ public boolean isConsumed() { return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed && mCutoutConsumed; && mDisplayCutoutConsumed; } /** Loading Loading @@ -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" : "") + "}"; } Loading core/java/android/view/WindowManager.java +11 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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( Loading Loading
api/current.txt +12 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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;
core/java/android/view/DisplayCutout.java +63 −82 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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. */ Loading @@ -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; } Loading @@ -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; } Loading @@ -161,7 +150,7 @@ public final class DisplayCutout { @Override public String toString() { return "DisplayCutout{insets=" + mSafeInsets + " bounding=" + mBoundingRect + " bounds=" + mBounds + "}"; } Loading @@ -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. Loading @@ -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); } /** Loading @@ -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++) { Loading @@ -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, Loading @@ -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. Loading @@ -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); } /** Loading Loading @@ -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); } } Loading Loading @@ -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() { Loading
core/java/android/view/ViewRootImpl.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading
core/java/android/view/WindowInsets.java +16 −15 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ package android.view; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Rect; /** Loading Loading @@ -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); Loading Loading @@ -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; } /** Loading @@ -99,7 +100,7 @@ public final class WindowInsets { mIsRound = src.mIsRound; mAlwaysConsumeNavBar = src.mAlwaysConsumeNavBar; mDisplayCutout = src.mDisplayCutout; mCutoutConsumed = src.mCutoutConsumed; mDisplayCutoutConsumed = src.mDisplayCutoutConsumed; } /** @hide */ Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -311,7 +312,7 @@ public final class WindowInsets { */ public boolean isConsumed() { return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed && mCutoutConsumed; && mDisplayCutoutConsumed; } /** Loading Loading @@ -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" : "") + "}"; } Loading
core/java/android/view/WindowManager.java +11 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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( Loading