Loading core/java/android/view/InsetsSource.java +14 −0 Original line number Diff line number Diff line Loading @@ -104,12 +104,23 @@ public class InsetsSource implements Parcelable { */ public static final int FLAG_ANIMATE_RESIZING = 1 << 3; /** * Controls whether the {@link WindowInsets.Type#captionBar()} insets provided by this source * should always be forcibly consumed. Unlike with {@link #FLAG_FORCE_CONSUMING}, when this * flag is used the caption bar will be consumed even when the bar is requested to be visible. * * Note: this flag does not take effect when the window applies * {@link WindowInsetsController.Appearance#APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND}. */ public static final int FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR = 1 << 4; @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, prefix = "FLAG_", value = { FLAG_SUPPRESS_SCRIM, FLAG_INSETS_ROUNDED_CORNER, FLAG_FORCE_CONSUMING, FLAG_ANIMATE_RESIZING, FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR }) public @interface Flags {} Loading Loading @@ -555,6 +566,9 @@ public class InsetsSource implements Parcelable { if ((flags & FLAG_ANIMATE_RESIZING) != 0) { joiner.add("ANIMATE_RESIZING"); } if ((flags & FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR) != 0) { joiner.add("FORCE_CONSUMING_OPAQUE_CAPTION_BAR"); } return joiner.toString(); } Loading core/java/android/view/InsetsState.java +13 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.view; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.util.SequenceUtils.getInitSeq; import static android.view.InsetsSource.FLAG_FORCE_CONSUMING; import static android.view.InsetsSource.FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR; import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER; import static android.view.InsetsStateProto.DISPLAY_CUTOUT; import static android.view.InsetsStateProto.DISPLAY_FRAME; Loading Loading @@ -54,6 +55,7 @@ import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import com.android.internal.annotations.VisibleForTesting; import com.android.window.flags.Flags; import java.io.PrintWriter; import java.util.Objects; Loading Loading @@ -131,18 +133,25 @@ public class InsetsState implements Parcelable { final Rect relativeFrame = new Rect(frame); final Rect relativeFrameMax = new Rect(frame); @InsetsType int forceConsumingTypes = 0; boolean forceConsumingOpaqueCaptionBar = false; @InsetsType int suppressScrimTypes = 0; final Rect[][] typeBoundingRectsMap = new Rect[Type.SIZE][]; final Rect[][] typeMaxBoundingRectsMap = new Rect[Type.SIZE][]; for (int i = mSources.size() - 1; i >= 0; i--) { final InsetsSource source = mSources.valueAt(i); final @InsetsType int type = source.getType(); final @InsetsSource.Flags int flags = source.getFlags(); if ((source.getFlags() & InsetsSource.FLAG_FORCE_CONSUMING) != 0) { if ((flags & InsetsSource.FLAG_FORCE_CONSUMING) != 0) { forceConsumingTypes |= type; } if ((source.getFlags() & InsetsSource.FLAG_SUPPRESS_SCRIM) != 0) { if (Flags.enableCaptionCompatInsetForceConsumptionAlways() && (flags & FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR) != 0) { forceConsumingOpaqueCaptionBar = true; } if ((flags & InsetsSource.FLAG_SUPPRESS_SCRIM) != 0) { suppressScrimTypes |= type; } Loading Loading @@ -177,7 +186,8 @@ public class InsetsState implements Parcelable { } return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound, forceConsumingTypes, suppressScrimTypes, calculateRelativeCutout(frame), forceConsumingTypes, forceConsumingOpaqueCaptionBar, suppressScrimTypes, calculateRelativeCutout(frame), calculateRelativeRoundedCorners(frame), calculateRelativePrivacyIndicatorBounds(frame), calculateRelativeDisplayShape(frame), Loading core/java/android/view/WindowInsets.java +41 −15 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ public final class WindowInsets { private final int mFrameHeight; private final @InsetsType int mForceConsumingTypes; private final boolean mForceConsumingOpaqueCaptionBar; private final @InsetsType int mSuppressScrimTypes; private final boolean mSystemWindowInsetsConsumed; private final boolean mStableInsetsConsumed; Loading @@ -123,7 +124,7 @@ public final class WindowInsets { static { CONSUMED = new WindowInsets(createCompatTypeMap(null), createCompatTypeMap(null), createCompatVisibilityMap(createCompatTypeMap(null)), false, 0, 0, null, createCompatVisibilityMap(createCompatTypeMap(null)), false, 0, false, 0, null, null, null, null, systemBars(), false, null, null, 0, 0); } Loading @@ -144,6 +145,7 @@ public final class WindowInsets { boolean[] typeVisibilityMap, boolean isRound, @InsetsType int forceConsumingTypes, boolean forceConsumingOpaqueCaptionBar, @InsetsType int suppressScrimTypes, DisplayCutout displayCutout, RoundedCorners roundedCorners, Loading @@ -166,6 +168,7 @@ public final class WindowInsets { mTypeVisibilityMap = typeVisibilityMap; mIsRound = isRound; mForceConsumingTypes = forceConsumingTypes; mForceConsumingOpaqueCaptionBar = forceConsumingOpaqueCaptionBar; mSuppressScrimTypes = suppressScrimTypes; mCompatInsetsTypes = compatInsetsTypes; mCompatIgnoreVisibility = compatIgnoreVisibility; Loading Loading @@ -196,7 +199,9 @@ public final class WindowInsets { this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap, src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap, src.mTypeVisibilityMap, src.mIsRound, src.mForceConsumingTypes, src.mSuppressScrimTypes, src.mForceConsumingTypes, src.mForceConsumingOpaqueCaptionBar, src.mSuppressScrimTypes, displayCutoutCopyConstructorArgument(src), src.mRoundedCorners, src.mPrivacyIndicatorBounds, Loading Loading @@ -257,7 +262,7 @@ public final class WindowInsets { /** @hide */ @UnsupportedAppUsage public WindowInsets(Rect systemWindowInsets) { this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, 0, 0, this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, 0, false, 0, null, null, null, null, systemBars(), false /* compatIgnoreVisibility */, new Rect[SIZE][], null, 0, 0); } Loading Loading @@ -675,10 +680,10 @@ public final class WindowInsets { return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, mIsRound, mForceConsumingTypes, mSuppressScrimTypes, null /* displayCutout */, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, mCompatInsetsTypes, mCompatIgnoreVisibility, mSystemWindowInsetsConsumed ? null : mTypeBoundingRectsMap, mIsRound, mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, null /* displayCutout */, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, mCompatInsetsTypes, mCompatIgnoreVisibility, mSystemWindowInsetsConsumed ? null : mTypeBoundingRectsMap, mStableInsetsConsumed ? null : mTypeMaxBoundingRectsMap, mFrameWidth, mFrameHeight); } Loading Loading @@ -729,7 +734,8 @@ public final class WindowInsets { public WindowInsets consumeSystemWindowInsets() { return new WindowInsets(null, null, mTypeVisibilityMap, mIsRound, mForceConsumingTypes, mSuppressScrimTypes, mIsRound, mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, // If the system window insets types contain displayCutout, we should also consume // it. (mCompatInsetsTypes & displayCutout()) != 0 Loading Loading @@ -1021,6 +1027,13 @@ public final class WindowInsets { return mForceConsumingTypes; } /** * @hide */ public boolean isForceConsumingOpaqueCaptionBar() { return mForceConsumingOpaqueCaptionBar; } /** * @hide */ Loading Loading @@ -1058,6 +1071,8 @@ public final class WindowInsets { result.append("\n "); result.append("forceConsumingTypes=" + Type.toString(mForceConsumingTypes)); result.append("\n "); result.append("forceConsumingOpaqueCaptionBar=" + mForceConsumingOpaqueCaptionBar); result.append("\n "); result.append("suppressScrimTypes=" + Type.toString(mSuppressScrimTypes)); result.append("\n "); result.append("compatInsetsTypes=" + Type.toString(mCompatInsetsTypes)); Loading Loading @@ -1180,7 +1195,8 @@ public final class WindowInsets { ? null : insetInsets(mTypeMaxInsetsMap, left, top, right, bottom), mTypeVisibilityMap, mIsRound, mForceConsumingTypes, mSuppressScrimTypes, mIsRound, mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, mDisplayCutoutConsumed ? null : mDisplayCutout == null Loading Loading @@ -1214,6 +1230,7 @@ public final class WindowInsets { return mIsRound == that.mIsRound && mForceConsumingTypes == that.mForceConsumingTypes && mForceConsumingOpaqueCaptionBar == that.mForceConsumingOpaqueCaptionBar && mSuppressScrimTypes == that.mSuppressScrimTypes && mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed && mStableInsetsConsumed == that.mStableInsetsConsumed Loading @@ -1235,9 +1252,9 @@ public final class WindowInsets { public int hashCode() { return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap), Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout, mRoundedCorners, mForceConsumingTypes, mSuppressScrimTypes, mSystemWindowInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed, mPrivacyIndicatorBounds, mDisplayShape, Arrays.deepHashCode(mTypeBoundingRectsMap), mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, mSystemWindowInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed, mPrivacyIndicatorBounds, mDisplayShape, Arrays.deepHashCode(mTypeBoundingRectsMap), Arrays.deepHashCode(mTypeMaxBoundingRectsMap), mFrameWidth, mFrameHeight); } Loading Loading @@ -1367,6 +1384,7 @@ public final class WindowInsets { private boolean mIsRound; private @InsetsType int mForceConsumingTypes; private boolean mForceConsumingOpaqueCaptionBar; private @InsetsType int mSuppressScrimTypes; private PrivacyIndicatorBounds mPrivacyIndicatorBounds = new PrivacyIndicatorBounds(); Loading Loading @@ -1399,6 +1417,7 @@ public final class WindowInsets { mRoundedCorners = insets.mRoundedCorners; mIsRound = insets.mIsRound; mForceConsumingTypes = insets.mForceConsumingTypes; mForceConsumingOpaqueCaptionBar = insets.mForceConsumingOpaqueCaptionBar; mSuppressScrimTypes = insets.mSuppressScrimTypes; mPrivacyIndicatorBounds = insets.mPrivacyIndicatorBounds; mDisplayShape = insets.mDisplayShape; Loading Loading @@ -1685,6 +1704,13 @@ public final class WindowInsets { return this; } /** @hide */ @NonNull public Builder setForceConsumingOpaqueCaptionBar(boolean forceConsumingOpaqueCaptionBar) { mForceConsumingOpaqueCaptionBar = forceConsumingOpaqueCaptionBar; return this; } /** @hide */ @NonNull public Builder setSuppressScrimTypes(@InsetsType int suppressScrimTypes) { Loading Loading @@ -1765,9 +1791,9 @@ public final class WindowInsets { public WindowInsets build() { return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, mIsRound, mForceConsumingTypes, mSuppressScrimTypes, mDisplayCutout, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, systemBars(), false /* compatIgnoreVisibility */, mIsRound, mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, mDisplayCutout, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, systemBars(), false /* compatIgnoreVisibility */, mSystemInsetsConsumed ? null : mTypeBoundingRectsMap, mStableInsetsConsumed ? null : mTypeMaxBoundingRectsMap, mFrameWidth, mFrameHeight); Loading core/java/com/android/internal/policy/DecorView.java +20 −13 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowInsetsController.APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; Loading @@ -36,6 +37,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.flags.Flags.customizableWindowHeaders; import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL; Loading Loading @@ -226,6 +228,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private boolean mLastHasLeftStableInset = false; private int mLastWindowFlags = 0; private @InsetsType int mLastForceConsumingTypes = 0; private boolean mLastForceConsumingOpaqueCaptionBar = false; private @InsetsType int mLastSuppressScrimTypes = 0; private int mRootScrollY = 0; Loading Loading @@ -1068,8 +1071,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind WindowManager.LayoutParams attrs = mWindow.getAttributes(); int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility(); final ViewRootImpl viewRoot = getViewRootImpl(); final WindowInsetsController controller = getWindowInsetsController(); final @InsetsType int requestedVisibleTypes = controller.getRequestedVisibleTypes(); final @Appearance int appearance = viewRoot != null ? viewRoot.mWindowAttributes.insetsFlags.appearance : controller.getSystemBarsAppearance(); // IME is an exceptional floating window that requires color view. final boolean isImeWindow = Loading @@ -1080,13 +1087,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; mLastWindowFlags = attrs.flags; final ViewRootImpl viewRoot = getViewRootImpl(); final @Appearance int appearance = viewRoot != null ? viewRoot.mWindowAttributes.insetsFlags.appearance : controller.getSystemBarsAppearance(); if (insets != null) { mLastForceConsumingTypes = insets.getForceConsumingTypes(); mLastForceConsumingOpaqueCaptionBar = insets.isForceConsumingOpaqueCaptionBar(); final boolean clearsCompatInsets = clearsCompatInsets(attrs.type, attrs.flags, getResources().getConfiguration().windowConfiguration.getActivityType(), Loading Loading @@ -1209,16 +1212,20 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final boolean hideCaptionBar = fullscreen || (requestedVisibleTypes & WindowInsets.Type.captionBar()) == 0; final boolean consumingCaptionBar = ((mLastForceConsumingTypes & WindowInsets.Type.captionBar()) != 0 final boolean consumingCaptionBar = Flags.enableCaptionCompatInsetForceConsumption() && ((mLastForceConsumingTypes & WindowInsets.Type.captionBar()) != 0 && hideCaptionBar); final int consumedTop; if (Flags.enableCaptionCompatInsetForceConsumption()) { consumedTop = (consumingStatusBar || consumingCaptionBar) ? mLastTopInset : 0; } else { consumedTop = consumingStatusBar ? mLastTopInset : 0; } final boolean isOpaqueCaptionBar = customizableWindowHeaders() && (appearance & APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND) == 0; final boolean consumingOpaqueCaptionBar = Flags.enableCaptionCompatInsetForceConsumptionAlways() && mLastForceConsumingOpaqueCaptionBar && isOpaqueCaptionBar; final int consumedTop = (consumingStatusBar || consumingCaptionBar || consumingOpaqueCaptionBar) ? mLastTopInset : 0; int consumedRight = consumingNavBar ? mLastRightInset : 0; int consumedBottom = consumingNavBar ? mLastBottomInset : 0; int consumedLeft = consumingNavBar ? mLastLeftInset : 0; Loading core/tests/coretests/src/android/view/InsetsStateTest.java +24 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.view; 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.FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR; import static android.view.InsetsSource.ID_IME; import static android.view.InsetsSource.SIDE_BOTTOM; import static android.view.InsetsSource.SIDE_TOP; Loading Loading @@ -54,12 +55,17 @@ import static org.junit.Assert.assertTrue; import android.graphics.Insets; import android.graphics.Rect; import android.os.Parcel; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.util.SparseIntArray; import android.view.WindowInsets.Type; import androidx.test.runner.AndroidJUnit4; import com.android.window.flags.Flags; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -78,6 +84,9 @@ import java.util.List; @RunWith(AndroidJUnit4.class) public class InsetsStateTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private static final int ID_STATUS_BAR = InsetsSource.createId( null /* owner */, 0 /* index */, statusBars()); private static final int ID_NAVIGATION_BAR = InsetsSource.createId( Loading Loading @@ -854,4 +863,19 @@ public class InsetsStateTest { ); } @Test @EnableFlags(Flags.FLAG_ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS) public void testCalculateInsets_forceConsumingCaptionBar() { mState.getOrCreateSource(ID_CAPTION_BAR, captionBar()) .setFrame(new Rect(0, 0, 100, 100)) .setVisible(true) .setFlags(FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR); final WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 1000, 1000), null, false, SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, new SparseIntArray()); assertTrue(insets.isForceConsumingOpaqueCaptionBar()); } } Loading
core/java/android/view/InsetsSource.java +14 −0 Original line number Diff line number Diff line Loading @@ -104,12 +104,23 @@ public class InsetsSource implements Parcelable { */ public static final int FLAG_ANIMATE_RESIZING = 1 << 3; /** * Controls whether the {@link WindowInsets.Type#captionBar()} insets provided by this source * should always be forcibly consumed. Unlike with {@link #FLAG_FORCE_CONSUMING}, when this * flag is used the caption bar will be consumed even when the bar is requested to be visible. * * Note: this flag does not take effect when the window applies * {@link WindowInsetsController.Appearance#APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND}. */ public static final int FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR = 1 << 4; @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, prefix = "FLAG_", value = { FLAG_SUPPRESS_SCRIM, FLAG_INSETS_ROUNDED_CORNER, FLAG_FORCE_CONSUMING, FLAG_ANIMATE_RESIZING, FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR }) public @interface Flags {} Loading Loading @@ -555,6 +566,9 @@ public class InsetsSource implements Parcelable { if ((flags & FLAG_ANIMATE_RESIZING) != 0) { joiner.add("ANIMATE_RESIZING"); } if ((flags & FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR) != 0) { joiner.add("FORCE_CONSUMING_OPAQUE_CAPTION_BAR"); } return joiner.toString(); } Loading
core/java/android/view/InsetsState.java +13 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.view; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.util.SequenceUtils.getInitSeq; import static android.view.InsetsSource.FLAG_FORCE_CONSUMING; import static android.view.InsetsSource.FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR; import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER; import static android.view.InsetsStateProto.DISPLAY_CUTOUT; import static android.view.InsetsStateProto.DISPLAY_FRAME; Loading Loading @@ -54,6 +55,7 @@ import android.view.WindowInsets.Type.InsetsType; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import com.android.internal.annotations.VisibleForTesting; import com.android.window.flags.Flags; import java.io.PrintWriter; import java.util.Objects; Loading Loading @@ -131,18 +133,25 @@ public class InsetsState implements Parcelable { final Rect relativeFrame = new Rect(frame); final Rect relativeFrameMax = new Rect(frame); @InsetsType int forceConsumingTypes = 0; boolean forceConsumingOpaqueCaptionBar = false; @InsetsType int suppressScrimTypes = 0; final Rect[][] typeBoundingRectsMap = new Rect[Type.SIZE][]; final Rect[][] typeMaxBoundingRectsMap = new Rect[Type.SIZE][]; for (int i = mSources.size() - 1; i >= 0; i--) { final InsetsSource source = mSources.valueAt(i); final @InsetsType int type = source.getType(); final @InsetsSource.Flags int flags = source.getFlags(); if ((source.getFlags() & InsetsSource.FLAG_FORCE_CONSUMING) != 0) { if ((flags & InsetsSource.FLAG_FORCE_CONSUMING) != 0) { forceConsumingTypes |= type; } if ((source.getFlags() & InsetsSource.FLAG_SUPPRESS_SCRIM) != 0) { if (Flags.enableCaptionCompatInsetForceConsumptionAlways() && (flags & FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR) != 0) { forceConsumingOpaqueCaptionBar = true; } if ((flags & InsetsSource.FLAG_SUPPRESS_SCRIM) != 0) { suppressScrimTypes |= type; } Loading Loading @@ -177,7 +186,8 @@ public class InsetsState implements Parcelable { } return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound, forceConsumingTypes, suppressScrimTypes, calculateRelativeCutout(frame), forceConsumingTypes, forceConsumingOpaqueCaptionBar, suppressScrimTypes, calculateRelativeCutout(frame), calculateRelativeRoundedCorners(frame), calculateRelativePrivacyIndicatorBounds(frame), calculateRelativeDisplayShape(frame), Loading
core/java/android/view/WindowInsets.java +41 −15 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ public final class WindowInsets { private final int mFrameHeight; private final @InsetsType int mForceConsumingTypes; private final boolean mForceConsumingOpaqueCaptionBar; private final @InsetsType int mSuppressScrimTypes; private final boolean mSystemWindowInsetsConsumed; private final boolean mStableInsetsConsumed; Loading @@ -123,7 +124,7 @@ public final class WindowInsets { static { CONSUMED = new WindowInsets(createCompatTypeMap(null), createCompatTypeMap(null), createCompatVisibilityMap(createCompatTypeMap(null)), false, 0, 0, null, createCompatVisibilityMap(createCompatTypeMap(null)), false, 0, false, 0, null, null, null, null, systemBars(), false, null, null, 0, 0); } Loading @@ -144,6 +145,7 @@ public final class WindowInsets { boolean[] typeVisibilityMap, boolean isRound, @InsetsType int forceConsumingTypes, boolean forceConsumingOpaqueCaptionBar, @InsetsType int suppressScrimTypes, DisplayCutout displayCutout, RoundedCorners roundedCorners, Loading @@ -166,6 +168,7 @@ public final class WindowInsets { mTypeVisibilityMap = typeVisibilityMap; mIsRound = isRound; mForceConsumingTypes = forceConsumingTypes; mForceConsumingOpaqueCaptionBar = forceConsumingOpaqueCaptionBar; mSuppressScrimTypes = suppressScrimTypes; mCompatInsetsTypes = compatInsetsTypes; mCompatIgnoreVisibility = compatIgnoreVisibility; Loading Loading @@ -196,7 +199,9 @@ public final class WindowInsets { this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap, src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap, src.mTypeVisibilityMap, src.mIsRound, src.mForceConsumingTypes, src.mSuppressScrimTypes, src.mForceConsumingTypes, src.mForceConsumingOpaqueCaptionBar, src.mSuppressScrimTypes, displayCutoutCopyConstructorArgument(src), src.mRoundedCorners, src.mPrivacyIndicatorBounds, Loading Loading @@ -257,7 +262,7 @@ public final class WindowInsets { /** @hide */ @UnsupportedAppUsage public WindowInsets(Rect systemWindowInsets) { this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, 0, 0, this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, 0, false, 0, null, null, null, null, systemBars(), false /* compatIgnoreVisibility */, new Rect[SIZE][], null, 0, 0); } Loading Loading @@ -675,10 +680,10 @@ public final class WindowInsets { return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, mIsRound, mForceConsumingTypes, mSuppressScrimTypes, null /* displayCutout */, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, mCompatInsetsTypes, mCompatIgnoreVisibility, mSystemWindowInsetsConsumed ? null : mTypeBoundingRectsMap, mIsRound, mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, null /* displayCutout */, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, mCompatInsetsTypes, mCompatIgnoreVisibility, mSystemWindowInsetsConsumed ? null : mTypeBoundingRectsMap, mStableInsetsConsumed ? null : mTypeMaxBoundingRectsMap, mFrameWidth, mFrameHeight); } Loading Loading @@ -729,7 +734,8 @@ public final class WindowInsets { public WindowInsets consumeSystemWindowInsets() { return new WindowInsets(null, null, mTypeVisibilityMap, mIsRound, mForceConsumingTypes, mSuppressScrimTypes, mIsRound, mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, // If the system window insets types contain displayCutout, we should also consume // it. (mCompatInsetsTypes & displayCutout()) != 0 Loading Loading @@ -1021,6 +1027,13 @@ public final class WindowInsets { return mForceConsumingTypes; } /** * @hide */ public boolean isForceConsumingOpaqueCaptionBar() { return mForceConsumingOpaqueCaptionBar; } /** * @hide */ Loading Loading @@ -1058,6 +1071,8 @@ public final class WindowInsets { result.append("\n "); result.append("forceConsumingTypes=" + Type.toString(mForceConsumingTypes)); result.append("\n "); result.append("forceConsumingOpaqueCaptionBar=" + mForceConsumingOpaqueCaptionBar); result.append("\n "); result.append("suppressScrimTypes=" + Type.toString(mSuppressScrimTypes)); result.append("\n "); result.append("compatInsetsTypes=" + Type.toString(mCompatInsetsTypes)); Loading Loading @@ -1180,7 +1195,8 @@ public final class WindowInsets { ? null : insetInsets(mTypeMaxInsetsMap, left, top, right, bottom), mTypeVisibilityMap, mIsRound, mForceConsumingTypes, mSuppressScrimTypes, mIsRound, mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, mDisplayCutoutConsumed ? null : mDisplayCutout == null Loading Loading @@ -1214,6 +1230,7 @@ public final class WindowInsets { return mIsRound == that.mIsRound && mForceConsumingTypes == that.mForceConsumingTypes && mForceConsumingOpaqueCaptionBar == that.mForceConsumingOpaqueCaptionBar && mSuppressScrimTypes == that.mSuppressScrimTypes && mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed && mStableInsetsConsumed == that.mStableInsetsConsumed Loading @@ -1235,9 +1252,9 @@ public final class WindowInsets { public int hashCode() { return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap), Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout, mRoundedCorners, mForceConsumingTypes, mSuppressScrimTypes, mSystemWindowInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed, mPrivacyIndicatorBounds, mDisplayShape, Arrays.deepHashCode(mTypeBoundingRectsMap), mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, mSystemWindowInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed, mPrivacyIndicatorBounds, mDisplayShape, Arrays.deepHashCode(mTypeBoundingRectsMap), Arrays.deepHashCode(mTypeMaxBoundingRectsMap), mFrameWidth, mFrameHeight); } Loading Loading @@ -1367,6 +1384,7 @@ public final class WindowInsets { private boolean mIsRound; private @InsetsType int mForceConsumingTypes; private boolean mForceConsumingOpaqueCaptionBar; private @InsetsType int mSuppressScrimTypes; private PrivacyIndicatorBounds mPrivacyIndicatorBounds = new PrivacyIndicatorBounds(); Loading Loading @@ -1399,6 +1417,7 @@ public final class WindowInsets { mRoundedCorners = insets.mRoundedCorners; mIsRound = insets.mIsRound; mForceConsumingTypes = insets.mForceConsumingTypes; mForceConsumingOpaqueCaptionBar = insets.mForceConsumingOpaqueCaptionBar; mSuppressScrimTypes = insets.mSuppressScrimTypes; mPrivacyIndicatorBounds = insets.mPrivacyIndicatorBounds; mDisplayShape = insets.mDisplayShape; Loading Loading @@ -1685,6 +1704,13 @@ public final class WindowInsets { return this; } /** @hide */ @NonNull public Builder setForceConsumingOpaqueCaptionBar(boolean forceConsumingOpaqueCaptionBar) { mForceConsumingOpaqueCaptionBar = forceConsumingOpaqueCaptionBar; return this; } /** @hide */ @NonNull public Builder setSuppressScrimTypes(@InsetsType int suppressScrimTypes) { Loading Loading @@ -1765,9 +1791,9 @@ public final class WindowInsets { public WindowInsets build() { return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, mIsRound, mForceConsumingTypes, mSuppressScrimTypes, mDisplayCutout, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, systemBars(), false /* compatIgnoreVisibility */, mIsRound, mForceConsumingTypes, mForceConsumingOpaqueCaptionBar, mSuppressScrimTypes, mDisplayCutout, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, systemBars(), false /* compatIgnoreVisibility */, mSystemInsetsConsumed ? null : mTypeBoundingRectsMap, mStableInsetsConsumed ? null : mTypeMaxBoundingRectsMap, mFrameWidth, mFrameHeight); Loading
core/java/com/android/internal/policy/DecorView.java +20 −13 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowInsetsController.APPEARANCE_FORCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; Loading @@ -36,6 +37,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.flags.Flags.customizableWindowHeaders; import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL; Loading Loading @@ -226,6 +228,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private boolean mLastHasLeftStableInset = false; private int mLastWindowFlags = 0; private @InsetsType int mLastForceConsumingTypes = 0; private boolean mLastForceConsumingOpaqueCaptionBar = false; private @InsetsType int mLastSuppressScrimTypes = 0; private int mRootScrollY = 0; Loading Loading @@ -1068,8 +1071,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind WindowManager.LayoutParams attrs = mWindow.getAttributes(); int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility(); final ViewRootImpl viewRoot = getViewRootImpl(); final WindowInsetsController controller = getWindowInsetsController(); final @InsetsType int requestedVisibleTypes = controller.getRequestedVisibleTypes(); final @Appearance int appearance = viewRoot != null ? viewRoot.mWindowAttributes.insetsFlags.appearance : controller.getSystemBarsAppearance(); // IME is an exceptional floating window that requires color view. final boolean isImeWindow = Loading @@ -1080,13 +1087,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; mLastWindowFlags = attrs.flags; final ViewRootImpl viewRoot = getViewRootImpl(); final @Appearance int appearance = viewRoot != null ? viewRoot.mWindowAttributes.insetsFlags.appearance : controller.getSystemBarsAppearance(); if (insets != null) { mLastForceConsumingTypes = insets.getForceConsumingTypes(); mLastForceConsumingOpaqueCaptionBar = insets.isForceConsumingOpaqueCaptionBar(); final boolean clearsCompatInsets = clearsCompatInsets(attrs.type, attrs.flags, getResources().getConfiguration().windowConfiguration.getActivityType(), Loading Loading @@ -1209,16 +1212,20 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final boolean hideCaptionBar = fullscreen || (requestedVisibleTypes & WindowInsets.Type.captionBar()) == 0; final boolean consumingCaptionBar = ((mLastForceConsumingTypes & WindowInsets.Type.captionBar()) != 0 final boolean consumingCaptionBar = Flags.enableCaptionCompatInsetForceConsumption() && ((mLastForceConsumingTypes & WindowInsets.Type.captionBar()) != 0 && hideCaptionBar); final int consumedTop; if (Flags.enableCaptionCompatInsetForceConsumption()) { consumedTop = (consumingStatusBar || consumingCaptionBar) ? mLastTopInset : 0; } else { consumedTop = consumingStatusBar ? mLastTopInset : 0; } final boolean isOpaqueCaptionBar = customizableWindowHeaders() && (appearance & APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND) == 0; final boolean consumingOpaqueCaptionBar = Flags.enableCaptionCompatInsetForceConsumptionAlways() && mLastForceConsumingOpaqueCaptionBar && isOpaqueCaptionBar; final int consumedTop = (consumingStatusBar || consumingCaptionBar || consumingOpaqueCaptionBar) ? mLastTopInset : 0; int consumedRight = consumingNavBar ? mLastRightInset : 0; int consumedBottom = consumingNavBar ? mLastBottomInset : 0; int consumedLeft = consumingNavBar ? mLastLeftInset : 0; Loading
core/tests/coretests/src/android/view/InsetsStateTest.java +24 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.view; 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.FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR; import static android.view.InsetsSource.ID_IME; import static android.view.InsetsSource.SIDE_BOTTOM; import static android.view.InsetsSource.SIDE_TOP; Loading Loading @@ -54,12 +55,17 @@ import static org.junit.Assert.assertTrue; import android.graphics.Insets; import android.graphics.Rect; import android.os.Parcel; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.util.SparseIntArray; import android.view.WindowInsets.Type; import androidx.test.runner.AndroidJUnit4; import com.android.window.flags.Flags; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -78,6 +84,9 @@ import java.util.List; @RunWith(AndroidJUnit4.class) public class InsetsStateTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private static final int ID_STATUS_BAR = InsetsSource.createId( null /* owner */, 0 /* index */, statusBars()); private static final int ID_NAVIGATION_BAR = InsetsSource.createId( Loading Loading @@ -854,4 +863,19 @@ public class InsetsStateTest { ); } @Test @EnableFlags(Flags.FLAG_ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS) public void testCalculateInsets_forceConsumingCaptionBar() { mState.getOrCreateSource(ID_CAPTION_BAR, captionBar()) .setFrame(new Rect(0, 0, 100, 100)) .setVisible(true) .setFlags(FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR); final WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 1000, 1000), null, false, SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, ACTIVITY_TYPE_UNDEFINED, new SparseIntArray()); assertTrue(insets.isForceConsumingOpaqueCaptionBar()); } }