Loading core/java/android/view/InsetsAnimationControlImpl.java +19 −18 Original line number Diff line number Diff line Loading @@ -34,11 +34,11 @@ import static android.view.InsetsController.DEBUG; import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN; import static android.view.InsetsController.LayoutInsetsDuringAnimation; import static android.view.InsetsSource.ID_IME; import static android.view.InsetsState.ISIDE_BOTTOM; import static android.view.InsetsState.ISIDE_FLOATING; import static android.view.InsetsState.ISIDE_LEFT; import static android.view.InsetsState.ISIDE_RIGHT; import static android.view.InsetsState.ISIDE_TOP; import static android.view.InsetsSource.SIDE_BOTTOM; import static android.view.InsetsSource.SIDE_NONE; import static android.view.InsetsSource.SIDE_LEFT; import static android.view.InsetsSource.SIDE_RIGHT; import static android.view.InsetsSource.SIDE_TOP; import static android.view.WindowInsets.Type.ime; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; Loading @@ -60,7 +60,7 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseSetArray; import android.util.proto.ProtoOutputStream; import android.view.InsetsState.InternalInsetsSide; import android.view.InsetsSource.InternalInsetsSide; import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsAnimation.Bounds; Loading Loading @@ -142,7 +142,7 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro if (mHasZeroInsetsIme) { // IME has shownInsets of ZERO, and can't map to a side by default. // Map zero insets IME to bottom, making it a special case of bottom insets. idSideMap.put(ID_IME, ISIDE_BOTTOM); idSideMap.put(ID_IME, SIDE_BOTTOM); } buildSideControlsMap(idSideMap, mSideControlsMap, controls); } else { Loading Loading @@ -286,10 +286,10 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro } final Insets offset = Insets.subtract(mShownInsets, mPendingInsets); final ArrayList<SurfaceParams> params = new ArrayList<>(); updateLeashesForSide(ISIDE_LEFT, offset.left, params, outState, mPendingAlpha); updateLeashesForSide(ISIDE_TOP, offset.top, params, outState, mPendingAlpha); updateLeashesForSide(ISIDE_RIGHT, offset.right, params, outState, mPendingAlpha); updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, params, outState, mPendingAlpha); updateLeashesForSide(SIDE_LEFT, offset.left, params, outState, mPendingAlpha); updateLeashesForSide(SIDE_TOP, offset.top, params, outState, mPendingAlpha); updateLeashesForSide(SIDE_RIGHT, offset.right, params, outState, mPendingAlpha); updateLeashesForSide(SIDE_BOTTOM, offset.bottom, params, outState, mPendingAlpha); mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()])); mCurrentInsets = mPendingInsets; Loading Loading @@ -499,19 +499,19 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro final float surfaceOffset = mTranslator != null ? mTranslator.translateLengthInAppWindowToScreen(offset) : offset; switch (side) { case ISIDE_LEFT: case SIDE_LEFT: m.postTranslate(-surfaceOffset, 0); frame.offset(-offset, 0); break; case ISIDE_TOP: case SIDE_TOP: m.postTranslate(0, -surfaceOffset); frame.offset(0, -offset); break; case ISIDE_RIGHT: case SIDE_RIGHT: m.postTranslate(surfaceOffset, 0); frame.offset(offset, 0); break; case ISIDE_BOTTOM: case SIDE_BOTTOM: m.postTranslate(0, surfaceOffset); frame.offset(0, offset); break; Loading Loading @@ -543,9 +543,10 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro // control may be null if it got revoked. continue; } @InternalInsetsSide int side = InsetsState.getInsetSide(control.getInsetsHint()); if (side == ISIDE_FLOATING && control.getType() == WindowInsets.Type.ime()) { side = ISIDE_BOTTOM; @InternalInsetsSide int side = InsetsSource.getInsetSide(control.getInsetsHint()); if (side == SIDE_NONE && control.getType() == WindowInsets.Type.ime()) { // IME might not provide insets when it is fullscreen or floating. side = SIDE_BOTTOM; } sideControlsMap.add(side, control); } Loading core/java/android/view/InsetsSource.java +103 −8 Original line number Diff line number Diff line Loading @@ -46,6 +46,24 @@ import java.util.StringJoiner; */ public class InsetsSource implements Parcelable { @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "SIDE_", value = { SIDE_NONE, SIDE_LEFT, SIDE_TOP, SIDE_RIGHT, SIDE_BOTTOM, SIDE_UNKNOWN }) public @interface InternalInsetsSide {} static final int SIDE_NONE = 0; static final int SIDE_LEFT = 1; static final int SIDE_TOP = 2; static final int SIDE_RIGHT = 3; static final int SIDE_BOTTOM = 4; static final int SIDE_UNKNOWN = 5; /** The insets source ID of IME */ public static final int ID_IME = createId(null, 0, ime()); Loading Loading @@ -101,6 +119,12 @@ public class InsetsSource implements Parcelable { private boolean mVisible; /** * Used to decide which side of the relative frame should receive insets when the frame fully * covers the relative frame. */ private @InternalInsetsSide int mSideHint = SIDE_NONE; private final Rect mTmpFrame = new Rect(); public InsetsSource(int id, @InsetsType int type) { Loading @@ -119,6 +143,7 @@ public class InsetsSource implements Parcelable { ? new Rect(other.mVisibleFrame) : null; mFlags = other.mFlags; mSideHint = other.mSideHint; } public void set(InsetsSource other) { Loading @@ -128,6 +153,7 @@ public class InsetsSource implements Parcelable { ? new Rect(other.mVisibleFrame) : null; mFlags = other.mFlags; mSideHint = other.mSideHint; } public InsetsSource setFrame(int left, int top, int right, int bottom) { Loading Loading @@ -160,6 +186,18 @@ public class InsetsSource implements Parcelable { return this; } /** * Updates the side hint which is used to decide which side of the relative frame should receive * insets when the frame fully covers the relative frame. * * @param bounds A rectangle which contains the frame. It will be used to calculate the hint. */ public InsetsSource updateSideHint(Rect bounds) { mSideHint = getInsetSide( calculateInsets(bounds, mFrame, true /* ignoreVisibility */)); return this; } public int getId() { return mId; } Loading Loading @@ -236,8 +274,21 @@ public class InsetsSource implements Parcelable { return Insets.of(0, 0, 0, mTmpFrame.height()); } if (mTmpFrame.equals(relativeFrame)) { // Covering all sides switch (mSideHint) { default: case SIDE_LEFT: return Insets.of(mTmpFrame.width(), 0, 0, 0); case SIDE_TOP: return Insets.of(0, mTmpFrame.height(), 0, 0); case SIDE_RIGHT: return Insets.of(0, 0, mTmpFrame.width(), 0); case SIDE_BOTTOM: return Insets.of(0, 0, 0, mTmpFrame.height()); } } else if (mTmpFrame.width() == relativeFrame.width()) { // Intersecting at top/bottom if (mTmpFrame.width() == relativeFrame.width()) { if (mTmpFrame.top == relativeFrame.top) { return Insets.of(0, mTmpFrame.height(), 0, 0); } else if (mTmpFrame.bottom == relativeFrame.bottom) { Loading @@ -249,9 +300,8 @@ public class InsetsSource implements Parcelable { if (mTmpFrame.top == 0) { return Insets.of(0, mTmpFrame.height(), 0, 0); } } } else if (mTmpFrame.height() == relativeFrame.height()) { // Intersecting at left/right else if (mTmpFrame.height() == relativeFrame.height()) { if (mTmpFrame.left == relativeFrame.left) { return Insets.of(mTmpFrame.width(), 0, 0, 0); } else if (mTmpFrame.right == relativeFrame.right) { Loading Loading @@ -282,6 +332,46 @@ public class InsetsSource implements Parcelable { return false; } /** * Retrieves the side for a certain {@code insets}. It is required that only one field l/t/r/b * is set in order that this method returns a meaningful result. */ static @InternalInsetsSide int getInsetSide(Insets insets) { if (Insets.NONE.equals(insets)) { return SIDE_NONE; } if (insets.left != 0) { return SIDE_LEFT; } if (insets.top != 0) { return SIDE_TOP; } if (insets.right != 0) { return SIDE_RIGHT; } if (insets.bottom != 0) { return SIDE_BOTTOM; } return SIDE_UNKNOWN; } static String sideToString(@InternalInsetsSide int side) { switch (side) { case SIDE_NONE: return "NONE"; case SIDE_LEFT: return "LEFT"; case SIDE_TOP: return "TOP"; case SIDE_RIGHT: return "RIGHT"; case SIDE_BOTTOM: return "BOTTOM"; default: return "UNKNOWN:" + side; } } /** * Creates an identifier of an {@link InsetsSource}. * Loading Loading @@ -331,7 +421,7 @@ public class InsetsSource implements Parcelable { } public static String flagsToString(@Flags int flags) { final StringJoiner joiner = new StringJoiner(" "); final StringJoiner joiner = new StringJoiner("|"); if ((flags & FLAG_SUPPRESS_SCRIM) != 0) { joiner.add("SUPPRESS_SCRIM"); } Loading Loading @@ -371,6 +461,7 @@ public class InsetsSource implements Parcelable { } pw.print(" visible="); pw.print(mVisible); pw.print(" flags="); pw.print(flagsToString(mFlags)); pw.print(" sideHint="); pw.print(sideToString(mSideHint)); pw.println(); } Loading @@ -393,6 +484,7 @@ public class InsetsSource implements Parcelable { if (mType != that.mType) return false; if (mVisible != that.mVisible) return false; if (mFlags != that.mFlags) return false; if (mSideHint != that.mSideHint) return false; if (excludeInvisibleImeFrames && !mVisible && mType == WindowInsets.Type.ime()) return true; if (!Objects.equals(mVisibleFrame, that.mVisibleFrame)) return false; return mFrame.equals(that.mFrame); Loading @@ -400,7 +492,7 @@ public class InsetsSource implements Parcelable { @Override public int hashCode() { return Objects.hash(mId, mType, mFrame, mVisibleFrame, mVisible, mFlags); return Objects.hash(mId, mType, mFrame, mVisibleFrame, mVisible, mFlags, mSideHint); } public InsetsSource(Parcel in) { Loading @@ -414,6 +506,7 @@ public class InsetsSource implements Parcelable { } mVisible = in.readBoolean(); mFlags = in.readInt(); mSideHint = in.readInt(); } @Override Loading @@ -434,6 +527,7 @@ public class InsetsSource implements Parcelable { } dest.writeBoolean(mVisible); dest.writeInt(mFlags); dest.writeInt(mSideHint); } @Override Loading @@ -442,7 +536,8 @@ public class InsetsSource implements Parcelable { + " mType=" + WindowInsets.Type.toString(mType) + " mFrame=" + mFrame.toShortString() + " mVisible=" + mVisible + " mFlags=[" + flagsToString(mFlags) + "]" + " mFlags=" + flagsToString(mFlags) + " mSideHint=" + sideToString(mSideHint) + "}"; } Loading core/java/android/view/InsetsState.java +3 −45 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.WindowConfiguration.ActivityType; Loading @@ -48,6 +47,7 @@ import android.os.Parcelable; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.proto.ProtoOutputStream; import android.view.InsetsSource.InternalInsetsSide; import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; Loading @@ -55,8 +55,6 @@ import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; import java.util.StringJoiner; Loading @@ -66,23 +64,6 @@ import java.util.StringJoiner; */ public class InsetsState implements Parcelable { @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "ISIDE", value = { ISIDE_LEFT, ISIDE_TOP, ISIDE_RIGHT, ISIDE_BOTTOM, ISIDE_FLOATING, ISIDE_UNKNOWN }) public @interface InternalInsetsSide {} static final int ISIDE_LEFT = 0; static final int ISIDE_TOP = 1; static final int ISIDE_RIGHT = 2; static final int ISIDE_BOTTOM = 3; static final int ISIDE_FLOATING = 4; static final int ISIDE_UNKNOWN = 5; private final SparseArray<InsetsSource> mSources; /** Loading Loading @@ -398,36 +379,13 @@ public class InsetsState implements Parcelable { } if (idSideMap != null) { @InternalInsetsSide int insetSide = getInsetSide(insets); if (insetSide != ISIDE_UNKNOWN) { @InternalInsetsSide int insetSide = InsetsSource.getInsetSide(insets); if (insetSide != InsetsSource.SIDE_UNKNOWN) { idSideMap.put(source.getId(), insetSide); } } } /** * Retrieves the side for a certain {@code insets}. It is required that only one field l/t/r/b * is set in order that this method returns a meaningful result. */ static @InternalInsetsSide int getInsetSide(Insets insets) { if (Insets.NONE.equals(insets)) { return ISIDE_FLOATING; } if (insets.left != 0) { return ISIDE_LEFT; } if (insets.top != 0) { return ISIDE_TOP; } if (insets.right != 0) { return ISIDE_RIGHT; } if (insets.bottom != 0) { return ISIDE_BOTTOM; } return ISIDE_UNKNOWN; } /** * Gets the source mapped from the ID, or creates one if no such mapping has been made. */ Loading core/tests/coretests/src/android/view/InsetsStateTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -20,8 +20,8 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.view.InsetsSource.FLAG_FORCE_CONSUMING; import static android.view.InsetsSource.ID_IME; import static android.view.InsetsState.ISIDE_BOTTOM; import static android.view.InsetsState.ISIDE_TOP; import static android.view.InsetsSource.SIDE_BOTTOM; import static android.view.InsetsSource.SIDE_TOP; import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT; import static android.view.RoundedCorner.POSITION_BOTTOM_RIGHT; import static android.view.RoundedCorner.POSITION_TOP_LEFT; Loading Loading @@ -106,8 +106,8 @@ public class InsetsStateTest { typeSideMap); assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all())); assertEquals(ISIDE_TOP, typeSideMap.get(ID_STATUS_BAR)); assertEquals(ISIDE_BOTTOM, typeSideMap.get(ID_IME)); assertEquals(SIDE_TOP, typeSideMap.get(ID_STATUS_BAR)); assertEquals(SIDE_BOTTOM, typeSideMap.get(ID_IME)); assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars())); assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(ime())); } Loading services/core/java/com/android/server/wm/DisplayFrames.java +19 −15 Original line number Diff line number Diff line Loading @@ -92,35 +92,39 @@ public class DisplayFrames { mRotation = rotation; mWidth = w; mHeight = h; final Rect unrestricted = mUnrestricted; unrestricted.set(0, 0, w, h); state.setDisplayFrame(unrestricted); final Rect u = mUnrestricted; u.set(0, 0, w, h); state.setDisplayFrame(u); state.setDisplayCutout(displayCutout); state.setRoundedCorners(roundedCorners); state.setPrivacyIndicatorBounds(indicatorBounds); state.setDisplayShape(displayShape); state.getDisplayCutoutSafe(safe); if (safe.left > unrestricted.left) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_LEFT, displayCutout()).setFrame( unrestricted.left, unrestricted.top, safe.left, unrestricted.bottom); if (safe.left > u.left) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_LEFT, displayCutout()) .setFrame(u.left, u.top, safe.left, u.bottom) .updateSideHint(u); } else { state.removeSource(ID_DISPLAY_CUTOUT_LEFT); } if (safe.top > unrestricted.top) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_TOP, displayCutout()).setFrame( unrestricted.left, unrestricted.top, unrestricted.right, safe.top); if (safe.top > u.top) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_TOP, displayCutout()) .setFrame(u.left, u.top, u.right, safe.top) .updateSideHint(u); } else { state.removeSource(ID_DISPLAY_CUTOUT_TOP); } if (safe.right < unrestricted.right) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_RIGHT, displayCutout()).setFrame( safe.right, unrestricted.top, unrestricted.right, unrestricted.bottom); if (safe.right < u.right) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_RIGHT, displayCutout()) .setFrame(safe.right, u.top, u.right, u.bottom) .updateSideHint(u); } else { state.removeSource(ID_DISPLAY_CUTOUT_RIGHT); } if (safe.bottom < unrestricted.bottom) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_BOTTOM, displayCutout()).setFrame( unrestricted.left, safe.bottom, unrestricted.right, unrestricted.bottom); if (safe.bottom < u.bottom) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_BOTTOM, displayCutout()) .setFrame(u.left, safe.bottom, u.right, u.bottom) .updateSideHint(u); } else { state.removeSource(ID_DISPLAY_CUTOUT_BOTTOM); } Loading Loading
core/java/android/view/InsetsAnimationControlImpl.java +19 −18 Original line number Diff line number Diff line Loading @@ -34,11 +34,11 @@ import static android.view.InsetsController.DEBUG; import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN; import static android.view.InsetsController.LayoutInsetsDuringAnimation; import static android.view.InsetsSource.ID_IME; import static android.view.InsetsState.ISIDE_BOTTOM; import static android.view.InsetsState.ISIDE_FLOATING; import static android.view.InsetsState.ISIDE_LEFT; import static android.view.InsetsState.ISIDE_RIGHT; import static android.view.InsetsState.ISIDE_TOP; import static android.view.InsetsSource.SIDE_BOTTOM; import static android.view.InsetsSource.SIDE_NONE; import static android.view.InsetsSource.SIDE_LEFT; import static android.view.InsetsSource.SIDE_RIGHT; import static android.view.InsetsSource.SIDE_TOP; import static android.view.WindowInsets.Type.ime; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; Loading @@ -60,7 +60,7 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseSetArray; import android.util.proto.ProtoOutputStream; import android.view.InsetsState.InternalInsetsSide; import android.view.InsetsSource.InternalInsetsSide; import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsAnimation.Bounds; Loading Loading @@ -142,7 +142,7 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro if (mHasZeroInsetsIme) { // IME has shownInsets of ZERO, and can't map to a side by default. // Map zero insets IME to bottom, making it a special case of bottom insets. idSideMap.put(ID_IME, ISIDE_BOTTOM); idSideMap.put(ID_IME, SIDE_BOTTOM); } buildSideControlsMap(idSideMap, mSideControlsMap, controls); } else { Loading Loading @@ -286,10 +286,10 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro } final Insets offset = Insets.subtract(mShownInsets, mPendingInsets); final ArrayList<SurfaceParams> params = new ArrayList<>(); updateLeashesForSide(ISIDE_LEFT, offset.left, params, outState, mPendingAlpha); updateLeashesForSide(ISIDE_TOP, offset.top, params, outState, mPendingAlpha); updateLeashesForSide(ISIDE_RIGHT, offset.right, params, outState, mPendingAlpha); updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, params, outState, mPendingAlpha); updateLeashesForSide(SIDE_LEFT, offset.left, params, outState, mPendingAlpha); updateLeashesForSide(SIDE_TOP, offset.top, params, outState, mPendingAlpha); updateLeashesForSide(SIDE_RIGHT, offset.right, params, outState, mPendingAlpha); updateLeashesForSide(SIDE_BOTTOM, offset.bottom, params, outState, mPendingAlpha); mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()])); mCurrentInsets = mPendingInsets; Loading Loading @@ -499,19 +499,19 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro final float surfaceOffset = mTranslator != null ? mTranslator.translateLengthInAppWindowToScreen(offset) : offset; switch (side) { case ISIDE_LEFT: case SIDE_LEFT: m.postTranslate(-surfaceOffset, 0); frame.offset(-offset, 0); break; case ISIDE_TOP: case SIDE_TOP: m.postTranslate(0, -surfaceOffset); frame.offset(0, -offset); break; case ISIDE_RIGHT: case SIDE_RIGHT: m.postTranslate(surfaceOffset, 0); frame.offset(offset, 0); break; case ISIDE_BOTTOM: case SIDE_BOTTOM: m.postTranslate(0, surfaceOffset); frame.offset(0, offset); break; Loading Loading @@ -543,9 +543,10 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro // control may be null if it got revoked. continue; } @InternalInsetsSide int side = InsetsState.getInsetSide(control.getInsetsHint()); if (side == ISIDE_FLOATING && control.getType() == WindowInsets.Type.ime()) { side = ISIDE_BOTTOM; @InternalInsetsSide int side = InsetsSource.getInsetSide(control.getInsetsHint()); if (side == SIDE_NONE && control.getType() == WindowInsets.Type.ime()) { // IME might not provide insets when it is fullscreen or floating. side = SIDE_BOTTOM; } sideControlsMap.add(side, control); } Loading
core/java/android/view/InsetsSource.java +103 −8 Original line number Diff line number Diff line Loading @@ -46,6 +46,24 @@ import java.util.StringJoiner; */ public class InsetsSource implements Parcelable { @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "SIDE_", value = { SIDE_NONE, SIDE_LEFT, SIDE_TOP, SIDE_RIGHT, SIDE_BOTTOM, SIDE_UNKNOWN }) public @interface InternalInsetsSide {} static final int SIDE_NONE = 0; static final int SIDE_LEFT = 1; static final int SIDE_TOP = 2; static final int SIDE_RIGHT = 3; static final int SIDE_BOTTOM = 4; static final int SIDE_UNKNOWN = 5; /** The insets source ID of IME */ public static final int ID_IME = createId(null, 0, ime()); Loading Loading @@ -101,6 +119,12 @@ public class InsetsSource implements Parcelable { private boolean mVisible; /** * Used to decide which side of the relative frame should receive insets when the frame fully * covers the relative frame. */ private @InternalInsetsSide int mSideHint = SIDE_NONE; private final Rect mTmpFrame = new Rect(); public InsetsSource(int id, @InsetsType int type) { Loading @@ -119,6 +143,7 @@ public class InsetsSource implements Parcelable { ? new Rect(other.mVisibleFrame) : null; mFlags = other.mFlags; mSideHint = other.mSideHint; } public void set(InsetsSource other) { Loading @@ -128,6 +153,7 @@ public class InsetsSource implements Parcelable { ? new Rect(other.mVisibleFrame) : null; mFlags = other.mFlags; mSideHint = other.mSideHint; } public InsetsSource setFrame(int left, int top, int right, int bottom) { Loading Loading @@ -160,6 +186,18 @@ public class InsetsSource implements Parcelable { return this; } /** * Updates the side hint which is used to decide which side of the relative frame should receive * insets when the frame fully covers the relative frame. * * @param bounds A rectangle which contains the frame. It will be used to calculate the hint. */ public InsetsSource updateSideHint(Rect bounds) { mSideHint = getInsetSide( calculateInsets(bounds, mFrame, true /* ignoreVisibility */)); return this; } public int getId() { return mId; } Loading Loading @@ -236,8 +274,21 @@ public class InsetsSource implements Parcelable { return Insets.of(0, 0, 0, mTmpFrame.height()); } if (mTmpFrame.equals(relativeFrame)) { // Covering all sides switch (mSideHint) { default: case SIDE_LEFT: return Insets.of(mTmpFrame.width(), 0, 0, 0); case SIDE_TOP: return Insets.of(0, mTmpFrame.height(), 0, 0); case SIDE_RIGHT: return Insets.of(0, 0, mTmpFrame.width(), 0); case SIDE_BOTTOM: return Insets.of(0, 0, 0, mTmpFrame.height()); } } else if (mTmpFrame.width() == relativeFrame.width()) { // Intersecting at top/bottom if (mTmpFrame.width() == relativeFrame.width()) { if (mTmpFrame.top == relativeFrame.top) { return Insets.of(0, mTmpFrame.height(), 0, 0); } else if (mTmpFrame.bottom == relativeFrame.bottom) { Loading @@ -249,9 +300,8 @@ public class InsetsSource implements Parcelable { if (mTmpFrame.top == 0) { return Insets.of(0, mTmpFrame.height(), 0, 0); } } } else if (mTmpFrame.height() == relativeFrame.height()) { // Intersecting at left/right else if (mTmpFrame.height() == relativeFrame.height()) { if (mTmpFrame.left == relativeFrame.left) { return Insets.of(mTmpFrame.width(), 0, 0, 0); } else if (mTmpFrame.right == relativeFrame.right) { Loading Loading @@ -282,6 +332,46 @@ public class InsetsSource implements Parcelable { return false; } /** * Retrieves the side for a certain {@code insets}. It is required that only one field l/t/r/b * is set in order that this method returns a meaningful result. */ static @InternalInsetsSide int getInsetSide(Insets insets) { if (Insets.NONE.equals(insets)) { return SIDE_NONE; } if (insets.left != 0) { return SIDE_LEFT; } if (insets.top != 0) { return SIDE_TOP; } if (insets.right != 0) { return SIDE_RIGHT; } if (insets.bottom != 0) { return SIDE_BOTTOM; } return SIDE_UNKNOWN; } static String sideToString(@InternalInsetsSide int side) { switch (side) { case SIDE_NONE: return "NONE"; case SIDE_LEFT: return "LEFT"; case SIDE_TOP: return "TOP"; case SIDE_RIGHT: return "RIGHT"; case SIDE_BOTTOM: return "BOTTOM"; default: return "UNKNOWN:" + side; } } /** * Creates an identifier of an {@link InsetsSource}. * Loading Loading @@ -331,7 +421,7 @@ public class InsetsSource implements Parcelable { } public static String flagsToString(@Flags int flags) { final StringJoiner joiner = new StringJoiner(" "); final StringJoiner joiner = new StringJoiner("|"); if ((flags & FLAG_SUPPRESS_SCRIM) != 0) { joiner.add("SUPPRESS_SCRIM"); } Loading Loading @@ -371,6 +461,7 @@ public class InsetsSource implements Parcelable { } pw.print(" visible="); pw.print(mVisible); pw.print(" flags="); pw.print(flagsToString(mFlags)); pw.print(" sideHint="); pw.print(sideToString(mSideHint)); pw.println(); } Loading @@ -393,6 +484,7 @@ public class InsetsSource implements Parcelable { if (mType != that.mType) return false; if (mVisible != that.mVisible) return false; if (mFlags != that.mFlags) return false; if (mSideHint != that.mSideHint) return false; if (excludeInvisibleImeFrames && !mVisible && mType == WindowInsets.Type.ime()) return true; if (!Objects.equals(mVisibleFrame, that.mVisibleFrame)) return false; return mFrame.equals(that.mFrame); Loading @@ -400,7 +492,7 @@ public class InsetsSource implements Parcelable { @Override public int hashCode() { return Objects.hash(mId, mType, mFrame, mVisibleFrame, mVisible, mFlags); return Objects.hash(mId, mType, mFrame, mVisibleFrame, mVisible, mFlags, mSideHint); } public InsetsSource(Parcel in) { Loading @@ -414,6 +506,7 @@ public class InsetsSource implements Parcelable { } mVisible = in.readBoolean(); mFlags = in.readInt(); mSideHint = in.readInt(); } @Override Loading @@ -434,6 +527,7 @@ public class InsetsSource implements Parcelable { } dest.writeBoolean(mVisible); dest.writeInt(mFlags); dest.writeInt(mSideHint); } @Override Loading @@ -442,7 +536,8 @@ public class InsetsSource implements Parcelable { + " mType=" + WindowInsets.Type.toString(mType) + " mFrame=" + mFrame.toShortString() + " mVisible=" + mVisible + " mFlags=[" + flagsToString(mFlags) + "]" + " mFlags=" + flagsToString(mFlags) + " mSideHint=" + sideToString(mSideHint) + "}"; } Loading
core/java/android/view/InsetsState.java +3 −45 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.WindowConfiguration.ActivityType; Loading @@ -48,6 +47,7 @@ import android.os.Parcelable; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.proto.ProtoOutputStream; import android.view.InsetsSource.InternalInsetsSide; import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; Loading @@ -55,8 +55,6 @@ import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import com.android.internal.annotations.VisibleForTesting; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; import java.util.StringJoiner; Loading @@ -66,23 +64,6 @@ import java.util.StringJoiner; */ public class InsetsState implements Parcelable { @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "ISIDE", value = { ISIDE_LEFT, ISIDE_TOP, ISIDE_RIGHT, ISIDE_BOTTOM, ISIDE_FLOATING, ISIDE_UNKNOWN }) public @interface InternalInsetsSide {} static final int ISIDE_LEFT = 0; static final int ISIDE_TOP = 1; static final int ISIDE_RIGHT = 2; static final int ISIDE_BOTTOM = 3; static final int ISIDE_FLOATING = 4; static final int ISIDE_UNKNOWN = 5; private final SparseArray<InsetsSource> mSources; /** Loading Loading @@ -398,36 +379,13 @@ public class InsetsState implements Parcelable { } if (idSideMap != null) { @InternalInsetsSide int insetSide = getInsetSide(insets); if (insetSide != ISIDE_UNKNOWN) { @InternalInsetsSide int insetSide = InsetsSource.getInsetSide(insets); if (insetSide != InsetsSource.SIDE_UNKNOWN) { idSideMap.put(source.getId(), insetSide); } } } /** * Retrieves the side for a certain {@code insets}. It is required that only one field l/t/r/b * is set in order that this method returns a meaningful result. */ static @InternalInsetsSide int getInsetSide(Insets insets) { if (Insets.NONE.equals(insets)) { return ISIDE_FLOATING; } if (insets.left != 0) { return ISIDE_LEFT; } if (insets.top != 0) { return ISIDE_TOP; } if (insets.right != 0) { return ISIDE_RIGHT; } if (insets.bottom != 0) { return ISIDE_BOTTOM; } return ISIDE_UNKNOWN; } /** * Gets the source mapped from the ID, or creates one if no such mapping has been made. */ Loading
core/tests/coretests/src/android/view/InsetsStateTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -20,8 +20,8 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.view.InsetsSource.FLAG_FORCE_CONSUMING; import static android.view.InsetsSource.ID_IME; import static android.view.InsetsState.ISIDE_BOTTOM; import static android.view.InsetsState.ISIDE_TOP; import static android.view.InsetsSource.SIDE_BOTTOM; import static android.view.InsetsSource.SIDE_TOP; import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT; import static android.view.RoundedCorner.POSITION_BOTTOM_RIGHT; import static android.view.RoundedCorner.POSITION_TOP_LEFT; Loading Loading @@ -106,8 +106,8 @@ public class InsetsStateTest { typeSideMap); assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all())); assertEquals(ISIDE_TOP, typeSideMap.get(ID_STATUS_BAR)); assertEquals(ISIDE_BOTTOM, typeSideMap.get(ID_IME)); assertEquals(SIDE_TOP, typeSideMap.get(ID_STATUS_BAR)); assertEquals(SIDE_BOTTOM, typeSideMap.get(ID_IME)); assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(statusBars())); assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(ime())); } Loading
services/core/java/com/android/server/wm/DisplayFrames.java +19 −15 Original line number Diff line number Diff line Loading @@ -92,35 +92,39 @@ public class DisplayFrames { mRotation = rotation; mWidth = w; mHeight = h; final Rect unrestricted = mUnrestricted; unrestricted.set(0, 0, w, h); state.setDisplayFrame(unrestricted); final Rect u = mUnrestricted; u.set(0, 0, w, h); state.setDisplayFrame(u); state.setDisplayCutout(displayCutout); state.setRoundedCorners(roundedCorners); state.setPrivacyIndicatorBounds(indicatorBounds); state.setDisplayShape(displayShape); state.getDisplayCutoutSafe(safe); if (safe.left > unrestricted.left) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_LEFT, displayCutout()).setFrame( unrestricted.left, unrestricted.top, safe.left, unrestricted.bottom); if (safe.left > u.left) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_LEFT, displayCutout()) .setFrame(u.left, u.top, safe.left, u.bottom) .updateSideHint(u); } else { state.removeSource(ID_DISPLAY_CUTOUT_LEFT); } if (safe.top > unrestricted.top) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_TOP, displayCutout()).setFrame( unrestricted.left, unrestricted.top, unrestricted.right, safe.top); if (safe.top > u.top) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_TOP, displayCutout()) .setFrame(u.left, u.top, u.right, safe.top) .updateSideHint(u); } else { state.removeSource(ID_DISPLAY_CUTOUT_TOP); } if (safe.right < unrestricted.right) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_RIGHT, displayCutout()).setFrame( safe.right, unrestricted.top, unrestricted.right, unrestricted.bottom); if (safe.right < u.right) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_RIGHT, displayCutout()) .setFrame(safe.right, u.top, u.right, u.bottom) .updateSideHint(u); } else { state.removeSource(ID_DISPLAY_CUTOUT_RIGHT); } if (safe.bottom < unrestricted.bottom) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_BOTTOM, displayCutout()).setFrame( unrestricted.left, safe.bottom, unrestricted.right, unrestricted.bottom); if (safe.bottom < u.bottom) { state.getOrCreateSource(ID_DISPLAY_CUTOUT_BOTTOM, displayCutout()) .setFrame(u.left, safe.bottom, u.right, u.bottom) .updateSideHint(u); } else { state.removeSource(ID_DISPLAY_CUTOUT_BOTTOM); } Loading