diff options
12 files changed, 181 insertions, 92 deletions
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 5019b85ca503..0abad6c76c2e 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -797,7 +797,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/, - mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(), + mLastInsets.isRound(), false /* alwaysConsumeSystemBars */, mLastLegacySoftInputMode, mLastLegacyWindowFlags, mLastLegacySystemUiFlags, mWindowType, mLastWindowingMode, null /* idSideMap */); mHost.dispatchWindowInsetsAnimationProgress(insets, diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java index e10184976abe..64411866f020 100644 --- a/core/java/android/view/InsetsSource.java +++ b/core/java/android/view/InsetsSource.java @@ -68,10 +68,16 @@ public class InsetsSource implements Parcelable { */ public static final int FLAG_INSETS_ROUNDED_CORNER = 1 << 1; + /** + * Controls whether the insets provided by this source should be forcibly consumed. + */ + public static final int FLAG_FORCE_CONSUMING = 1 << 2; + @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, prefix = "FLAG_", value = { FLAG_SUPPRESS_SCRIM, FLAG_INSETS_ROUNDED_CORNER, + FLAG_FORCE_CONSUMING, }) public @interface Flags {} @@ -328,6 +334,9 @@ public class InsetsSource implements Parcelable { if ((flags & FLAG_INSETS_ROUNDED_CORNER) != 0) { joiner.add("INSETS_ROUNDED_CORNER"); } + if ((flags & FLAG_FORCE_CONSUMING) != 0) { + joiner.add("FORCE_CONSUMING"); + } return joiner.toString(); } diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index dceae90822b8..c13b9ab0abd1 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -16,6 +16,7 @@ package android.view; +import static android.view.InsetsSource.FLAG_FORCE_CONSUMING; import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER; import static android.view.InsetsStateProto.DISPLAY_CUTOUT; import static android.view.InsetsStateProto.DISPLAY_FRAME; @@ -144,12 +145,18 @@ public class InsetsState implements Parcelable { boolean[] typeVisibilityMap = new boolean[Type.SIZE]; final Rect relativeFrame = new Rect(frame); final Rect relativeFrameMax = new Rect(frame); + @InsetsType int forceConsumingTypes = 0; @InsetsType int suppressScrimTypes = 0; for (int i = mSources.size() - 1; i >= 0; i--) { final InsetsSource source = mSources.valueAt(i); + final @InsetsType int type = source.getType(); + + if ((source.getFlags() & InsetsSource.FLAG_FORCE_CONSUMING) != 0) { + forceConsumingTypes |= type; + } if ((source.getFlags() & InsetsSource.FLAG_SUPPRESS_SCRIM) != 0) { - suppressScrimTypes |= source.getType(); + suppressScrimTypes |= type; } processSource(source, relativeFrame, false /* ignoreVisibility */, typeInsetsMap, @@ -157,7 +164,7 @@ public class InsetsState implements Parcelable { // IME won't be reported in max insets as the size depends on the EditorInfo of the IME // target. - if (source.getType() != WindowInsets.Type.ime()) { + if (type != WindowInsets.Type.ime()) { InsetsSource ignoringVisibilitySource = ignoringVisibilityState != null ? ignoringVisibilityState.peekSource(source.getId()) : source; @@ -178,13 +185,13 @@ public class InsetsState implements Parcelable { if ((legacyWindowFlags & FLAG_FULLSCREEN) != 0) { compatInsetsTypes &= ~statusBars(); } - if (clearsCompatInsets(windowType, legacyWindowFlags, windowingMode) - && !alwaysConsumeSystemBars) { - compatInsetsTypes = 0; + if (clearsCompatInsets(windowType, legacyWindowFlags, windowingMode)) { + // Clear all types but forceConsumingTypes. + compatInsetsTypes &= forceConsumingTypes; } return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound, - alwaysConsumeSystemBars, suppressScrimTypes, calculateRelativeCutout(frame), + forceConsumingTypes, suppressScrimTypes, calculateRelativeCutout(frame), calculateRelativeRoundedCorners(frame), calculateRelativePrivacyIndicatorBounds(frame), calculateRelativeDisplayShape(frame), @@ -290,9 +297,8 @@ public class InsetsState implements Parcelable { public Insets calculateVisibleInsets(Rect frame, int windowType, int windowingMode, @SoftInputModeFlags int softInputMode, int windowFlags) { - if (clearsCompatInsets(windowType, windowFlags, windowingMode)) { - return Insets.NONE; - } + final boolean clearsCompatInsets = clearsCompatInsets( + windowType, windowFlags, windowingMode); final int softInputAdjustMode = softInputMode & SOFT_INPUT_MASK_ADJUST; final int visibleInsetsTypes = softInputAdjustMode != SOFT_INPUT_ADJUST_NOTHING ? systemBars() | ime() @@ -303,6 +309,9 @@ public class InsetsState implements Parcelable { if ((source.getType() & visibleInsetsTypes) == 0) { continue; } + if (clearsCompatInsets && !source.hasFlags(FLAG_FORCE_CONSUMING)) { + continue; + } insets = Insets.max(source.calculateVisibleInsets(frame), insets); } return insets; diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 4acaea849586..57a41619ff8d 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -84,13 +84,7 @@ public final class WindowInsets { @Nullable private final PrivacyIndicatorBounds mPrivacyIndicatorBounds; @Nullable private final DisplayShape mDisplayShape; - /** - * In multi-window we force show the navigation bar. Because we don't want that the surface size - * changes in this mode, we instead have a flag whether the navigation bar size should always - * be consumed, so the app is treated like there is no virtual navigation bar at all. - */ - private final boolean mAlwaysConsumeSystemBars; - + private final @InsetsType int mForceConsumingTypes; private final @InsetsType int mSuppressScrimTypes; private final boolean mSystemWindowInsetsConsumed; private final boolean mStableInsetsConsumed; @@ -117,7 +111,7 @@ public final class WindowInsets { static { CONSUMED = new WindowInsets(createCompatTypeMap(null), createCompatTypeMap(null), - createCompatVisibilityMap(createCompatTypeMap(null)), false, false, 0, null, + createCompatVisibilityMap(createCompatTypeMap(null)), false, 0, 0, null, null, null, null, systemBars(), false); } @@ -137,7 +131,8 @@ public final class WindowInsets { @Nullable Insets[] typeMaxInsetsMap, boolean[] typeVisibilityMap, boolean isRound, - boolean alwaysConsumeSystemBars, @InsetsType int suppressScrimTypes, + @InsetsType int forceConsumingTypes, + @InsetsType int suppressScrimTypes, DisplayCutout displayCutout, RoundedCorners roundedCorners, PrivacyIndicatorBounds privacyIndicatorBounds, @@ -155,7 +150,7 @@ public final class WindowInsets { mTypeVisibilityMap = typeVisibilityMap; mIsRound = isRound; - mAlwaysConsumeSystemBars = alwaysConsumeSystemBars; + mForceConsumingTypes = forceConsumingTypes; mSuppressScrimTypes = suppressScrimTypes; mCompatInsetsTypes = compatInsetsTypes; mCompatIgnoreVisibility = compatIgnoreVisibility; @@ -178,7 +173,7 @@ public final class WindowInsets { this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap, src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap, src.mTypeVisibilityMap, src.mIsRound, - src.mAlwaysConsumeSystemBars, src.mSuppressScrimTypes, + src.mForceConsumingTypes, src.mSuppressScrimTypes, displayCutoutCopyConstructorArgument(src), src.mRoundedCorners, src.mPrivacyIndicatorBounds, @@ -235,7 +230,7 @@ public final class WindowInsets { /** @hide */ @UnsupportedAppUsage public WindowInsets(Rect systemWindowInsets) { - this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, false, 0, + this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, 0, 0, null, null, null, null, systemBars(), false /* compatIgnoreVisibility */); } @@ -556,7 +551,7 @@ public final class WindowInsets { return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, - mIsRound, mAlwaysConsumeSystemBars, mSuppressScrimTypes, + mIsRound, mForceConsumingTypes, mSuppressScrimTypes, null /* displayCutout */, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, mCompatInsetsTypes, mCompatIgnoreVisibility); } @@ -607,7 +602,7 @@ public final class WindowInsets { public WindowInsets consumeSystemWindowInsets() { return new WindowInsets(null, null, mTypeVisibilityMap, - mIsRound, mAlwaysConsumeSystemBars, mSuppressScrimTypes, + mIsRound, mForceConsumingTypes, mSuppressScrimTypes, // If the system window insets types contain displayCutout, we should also consume // it. (mCompatInsetsTypes & displayCutout()) != 0 @@ -895,8 +890,8 @@ public final class WindowInsets { /** * @hide */ - public boolean shouldAlwaysConsumeSystemBars() { - return mAlwaysConsumeSystemBars; + public @InsetsType int getForceConsumingTypes() { + return mForceConsumingTypes; } /** @@ -930,6 +925,8 @@ public final class WindowInsets { result.append("\n "); result.append(mDisplayShape != null ? "displayShape=" + mDisplayShape : ""); result.append("\n "); + result.append("forceConsumingTypes=" + Type.toString(mForceConsumingTypes)); + result.append("\n "); result.append("suppressScrimTypes=" + Type.toString(mSuppressScrimTypes)); result.append("\n "); result.append("compatInsetsTypes=" + Type.toString(mCompatInsetsTypes)); @@ -1027,7 +1024,7 @@ public final class WindowInsets { ? null : insetInsets(mTypeMaxInsetsMap, left, top, right, bottom), mTypeVisibilityMap, - mIsRound, mAlwaysConsumeSystemBars, mSuppressScrimTypes, + mIsRound, mForceConsumingTypes, mSuppressScrimTypes, mDisplayCutoutConsumed ? null : mDisplayCutout == null @@ -1050,7 +1047,7 @@ public final class WindowInsets { WindowInsets that = (WindowInsets) o; return mIsRound == that.mIsRound - && mAlwaysConsumeSystemBars == that.mAlwaysConsumeSystemBars + && mForceConsumingTypes == that.mForceConsumingTypes && mSuppressScrimTypes == that.mSuppressScrimTypes && mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed && mStableInsetsConsumed == that.mStableInsetsConsumed @@ -1068,7 +1065,7 @@ public final class WindowInsets { public int hashCode() { return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap), Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout, mRoundedCorners, - mAlwaysConsumeSystemBars, mSuppressScrimTypes, mSystemWindowInsetsConsumed, + mForceConsumingTypes, mSuppressScrimTypes, mSystemWindowInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed, mPrivacyIndicatorBounds, mDisplayShape); } @@ -1134,7 +1131,7 @@ public final class WindowInsets { private DisplayShape mDisplayShape = DisplayShape.NONE; private boolean mIsRound; - private boolean mAlwaysConsumeSystemBars; + private @InsetsType int mForceConsumingTypes; private @InsetsType int mSuppressScrimTypes; private PrivacyIndicatorBounds mPrivacyIndicatorBounds = new PrivacyIndicatorBounds(); @@ -1162,7 +1159,7 @@ public final class WindowInsets { mDisplayCutout = displayCutoutCopyConstructorArgument(insets); mRoundedCorners = insets.mRoundedCorners; mIsRound = insets.mIsRound; - mAlwaysConsumeSystemBars = insets.mAlwaysConsumeSystemBars; + mForceConsumingTypes = insets.mForceConsumingTypes; mSuppressScrimTypes = insets.mSuppressScrimTypes; mPrivacyIndicatorBounds = insets.mPrivacyIndicatorBounds; mDisplayShape = insets.mDisplayShape; @@ -1433,7 +1430,15 @@ public final class WindowInsets { /** @hide */ @NonNull public Builder setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars) { - mAlwaysConsumeSystemBars = alwaysConsumeSystemBars; + // TODO (b/277891341): Remove this and related usages. This has been replaced by + // #setForceConsumingTypes. + return this; + } + + /** @hide */ + @NonNull + public Builder setForceConsumingTypes(@InsetsType int forceConsumingTypes) { + mForceConsumingTypes = forceConsumingTypes; return this; } @@ -1453,7 +1458,7 @@ public final class WindowInsets { public WindowInsets build() { return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap, mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap, - mIsRound, mAlwaysConsumeSystemBars, mSuppressScrimTypes, mDisplayCutout, + mIsRound, mForceConsumingTypes, mSuppressScrimTypes, mDisplayCutout, mRoundedCorners, mPrivacyIndicatorBounds, mDisplayShape, systemBars(), false /* compatIgnoreVisibility */); } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index af1fdd79169a..bb868018bc95 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -232,7 +232,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private boolean mLastHasRightStableInset = false; private boolean mLastHasLeftStableInset = false; private int mLastWindowFlags = 0; - private boolean mLastShouldAlwaysConsumeSystemBars = false; + private @InsetsType int mLastForceConsumingTypes = 0; private @InsetsType int mLastSuppressScrimTypes = 0; private int mRootScrollY = 0; @@ -1111,19 +1111,19 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind : controller.getSystemBarsAppearance(); if (insets != null) { - mLastShouldAlwaysConsumeSystemBars = insets.shouldAlwaysConsumeSystemBars(); + mLastForceConsumingTypes = insets.getForceConsumingTypes(); - final boolean clearsCompatInsets = - clearsCompatInsets(attrs.type, attrs.flags, - getResources().getConfiguration().windowConfiguration - .getWindowingMode()) - && !mLastShouldAlwaysConsumeSystemBars; + @InsetsType int compatInsetsTypes = + WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout(); + if (clearsCompatInsets(attrs.type, attrs.flags, + getResources().getConfiguration().windowConfiguration.getWindowingMode())) { + compatInsetsTypes &= mLastForceConsumingTypes; + } final Insets stableBarInsets = insets.getInsetsIgnoringVisibility( WindowInsets.Type.systemBars()); - final Insets systemInsets = clearsCompatInsets + final Insets systemInsets = compatInsetsTypes == 0 ? Insets.NONE - : Insets.min(insets.getInsets(WindowInsets.Type.systemBars() - | WindowInsets.Type.displayCutout()), stableBarInsets); + : Insets.min(insets.getInsets(compatInsetsTypes), stableBarInsets); mLastTopInset = systemInsets.top; mLastBottomInset = systemInsets.bottom; mLastRightInset = systemInsets.right; @@ -1208,7 +1208,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0 && decorFitsSystemWindows && !hideNavigation) - || (mLastShouldAlwaysConsumeSystemBars && hideNavigation); + || ((mLastForceConsumingTypes & WindowInsets.Type.navigationBars()) != 0 + && hideNavigation); boolean consumingNavBar = ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 @@ -1224,13 +1225,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind boolean fullscreen = (sysUiVisibility & SYSTEM_UI_FLAG_FULLSCREEN) != 0 || (attrs.flags & FLAG_FULLSCREEN) != 0 || (requestedVisibleTypes & WindowInsets.Type.statusBars()) == 0; - boolean consumingStatusBar = (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0 - && decorFitsSystemWindows - && (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0 - && (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0 - && mForceWindowDrawsBarBackgrounds - && mLastTopInset != 0 - || (mLastShouldAlwaysConsumeSystemBars && fullscreen); + boolean consumingStatusBar = + ((sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0 + && decorFitsSystemWindows + && (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0 + && (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0 + && mForceWindowDrawsBarBackgrounds + && mLastTopInset != 0) + || ((mLastForceConsumingTypes & WindowInsets.Type.statusBars()) != 0 + && fullscreen); int consumedTop = consumingStatusBar ? mLastTopInset : 0; int consumedRight = consumingNavBar ? mLastRightInset : 0; @@ -1434,9 +1437,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private void updateColorViewInt(final ColorViewState state, int color, int dividerColor, int size, boolean verticalBar, boolean seascape, int sideMargin, boolean animate, boolean force, @InsetsType int requestedVisibleTypes) { + final @InsetsType int type = state.attributes.insetsType; state.present = state.attributes.isPresent( - (requestedVisibleTypes & state.attributes.insetsType) != 0 - || mLastShouldAlwaysConsumeSystemBars, + (requestedVisibleTypes & type) != 0 || (mLastForceConsumingTypes & type) != 0, mWindow.getAttributes().flags, force); boolean show = state.attributes.isVisible(state.present, color, mWindow.getAttributes().flags, force); diff --git a/core/tests/coretests/src/android/view/WindowInsetsTest.java b/core/tests/coretests/src/android/view/WindowInsetsTest.java index b4ba23c92a22..69abf5f3204f 100644 --- a/core/tests/coretests/src/android/view/WindowInsetsTest.java +++ b/core/tests/coretests/src/android/view/WindowInsetsTest.java @@ -40,14 +40,14 @@ public class WindowInsetsTest { @Test public void systemWindowInsets_afterConsuming_isConsumed() { assertTrue(new WindowInsets(WindowInsets.createCompatTypeMap(new Rect(1, 2, 3, 4)), null, - null, false, false, 0, null, null, null, null, + null, false, 0, 0, null, null, null, null, WindowInsets.Type.systemBars(), false) .consumeSystemWindowInsets().isConsumed()); } @Test public void multiNullConstructor_isConsumed() { - assertTrue(new WindowInsets(null, null, null, false, false, 0, null, null, null, null, + assertTrue(new WindowInsets(null, null, null, false, 0, 0, null, null, null, null, WindowInsets.Type.systemBars(), false).isConsumed()); } @@ -63,7 +63,7 @@ public class WindowInsetsTest { boolean[] visible = new boolean[SIZE]; WindowInsets.assignCompatInsets(maxInsets, new Rect(0, 10, 0, 0)); WindowInsets.assignCompatInsets(insets, new Rect(0, 0, 0, 0)); - WindowInsets windowInsets = new WindowInsets(insets, maxInsets, visible, false, false, + WindowInsets windowInsets = new WindowInsets(insets, maxInsets, visible, false, 0, 0, null, null, null, DisplayShape.NONE, systemBars(), true /* compatIgnoreVisibility */); assertEquals(Insets.of(0, 10, 0, 0), windowInsets.getSystemWindowInsets()); diff --git a/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java index a1a4265cd0a5..84dd2740e8b7 100644 --- a/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java +++ b/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java @@ -169,7 +169,7 @@ public class ActionBarOverlayLayoutTest { private WindowInsets insetsWith(Insets content, DisplayCutout cutout) { return new WindowInsets(WindowInsets.createCompatTypeMap(content.toRect()), null, null, - false, false, 0, cutout, null, null, null, WindowInsets.Type.systemBars(), false); + false, 0, 0, cutout, null, null, null, WindowInsets.Type.systemBars(), false); } private ViewGroup createViewGroupWithId(int id) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 12b5f5f774de..bfd2a10a8882 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3701,6 +3701,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mInputMonitor.dump(pw, " "); pw.println(); mInsetsStateController.dump(prefix, pw); + mInsetsPolicy.dump(prefix, pw); mDwpcHelper.dump(prefix, pw); pw.println(); } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index a02fd11ba832..2717a6a8ab04 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -327,8 +327,6 @@ public class DisplayPolicy { private WindowState mTopFullscreenOpaqueWindowState; private boolean mTopIsFullscreen; private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED; - private boolean mForceConsumeSystemBars; - private boolean mForceShowSystemBars; /** * Windows that provides gesture insets. If multiple windows provide gesture insets at the same @@ -1286,18 +1284,10 @@ public class DisplayPolicy { return ANIMATION_STYLEABLE; } - /** - * @return true if the system bars are forced to be consumed - */ + // TODO (b/277891341): Remove this and related usages. This has been replaced by + // InsetsSource#FLAG_FORCE_CONSUMING. public boolean areSystemBarsForcedConsumedLw() { - return mForceConsumeSystemBars; - } - - /** - * @return true if the system bars are forced to stay visible - */ - public boolean areSystemBarsForcedShownLw() { - return mForceShowSystemBars; + return false; } /** @@ -1694,7 +1684,8 @@ public class DisplayPolicy { * @return Whether the top fullscreen app hides the given type of system bar. */ boolean topAppHidesSystemBar(@InsetsType int type) { - if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) { + if (mTopFullscreenOpaqueWindowState == null + || getInsetsPolicy().areTypesForciblyShowing(type)) { return false; } return !mTopFullscreenOpaqueWindowState.isRequestedVisible(type); @@ -2371,14 +2362,7 @@ public class DisplayPolicy { final boolean freeformRootTaskVisible = defaultTaskDisplayArea.isRootTaskVisible(WINDOWING_MODE_FREEFORM); - // We need to force showing system bars when adjacent tasks or freeform roots visible. - mForceShowSystemBars = adjacentTasksVisible || freeformRootTaskVisible; - // We need to force the consumption of the system bars if they are force shown or if they - // are controlled by a remote insets controller. - mForceConsumeSystemBars = mForceShowSystemBars - || getInsetsPolicy().remoteInsetsControllerControlsSystemBars(win) - || getInsetsPolicy().forcesShowingNavigationBars(win); - mDisplayContent.getInsetsPolicy().updateBarControlTarget(win); + getInsetsPolicy().updateSystemBars(win, adjacentTasksVisible, freeformRootTaskVisible); final boolean topAppHidesStatusBar = topAppHidesSystemBar(Type.statusBars()); if (getStatusBar() != null) { diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 798dc85ec11b..4620266c981e 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -64,6 +64,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.DisplayThread; import com.android.server.statusbar.StatusBarManagerInternal; +import java.io.PrintWriter; + /** * Policy that implements who gets control over the windows generating insets. */ @@ -114,6 +116,7 @@ class InsetsPolicy { private final BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); private final BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); private @InsetsType int mShowingTransientTypes; + private @InsetsType int mForcedShowingTypes; private boolean mAnimatingShown; private final boolean mHideNavBarForKeyboard; @@ -127,7 +130,6 @@ class InsetsPolicy { mHideNavBarForKeyboard = r.getBoolean(R.bool.config_hideNavBarForKeyboard); } - /** Updates the target which can control system bars. */ void updateBarControlTarget(@Nullable WindowState focusedWin) { if (mFocusedWin != focusedWin) { @@ -514,7 +516,7 @@ class InsetsPolicy { component, focusedWin.getRequestedVisibleTypes()); return mDisplayContent.mRemoteInsetsControlTarget; } - if (mPolicy.areSystemBarsForcedShownLw()) { + if (areTypesForciblyShowing(Type.statusBars())) { // Status bar is forcibly shown. We don't want the client to control the status bar, and // we will dispatch the real visibility of status bar to the client. return null; @@ -567,13 +569,6 @@ class InsetsPolicy { return focusedWin; } } - if (forcesShowingNavigationBars(focusedWin)) { - // When "force show navigation bar" is enabled, it means both force visible is true, and - // we are in 3-button navigation. In this mode, the navigation bar is forcibly shown - // when activity type is ACTIVITY_TYPE_STANDARD which means Launcher or Recent could - // still control the navigation bar in this mode. - return null; - } if (remoteInsetsControllerControlsSystemBars(focusedWin)) { ComponentName component = focusedWin.mActivityRecord != null ? focusedWin.mActivityRecord.mActivityComponent : null; @@ -581,7 +576,7 @@ class InsetsPolicy { component, focusedWin.getRequestedVisibleTypes()); return mDisplayContent.mRemoteInsetsControlTarget; } - if (mPolicy.areSystemBarsForcedShownLw()) { + if (areTypesForciblyShowing(Type.navigationBars())) { // Navigation bar is forcibly shown. We don't want the client to control the navigation // bar, and we will dispatch the real visibility of navigation bar to the client. return null; @@ -603,7 +598,32 @@ class InsetsPolicy { return focusedWin; } - boolean forcesShowingNavigationBars(WindowState win) { + boolean areTypesForciblyShowing(@InsetsType int types) { + return (mForcedShowingTypes & types) == types; + } + + void updateSystemBars(WindowState win, boolean inSplitScreenMode, boolean inFreeformMode) { + mForcedShowingTypes = (inSplitScreenMode || inFreeformMode) + ? (Type.statusBars() | Type.navigationBars()) + : forceShowingNavigationBars(win) + ? Type.navigationBars() + : 0; + + // The client app won't be able to control these types of system bars. Here makes the client + // forcibly consume these types to prevent the app content from getting obscured. + mStateController.setForcedConsumingTypes( + mForcedShowingTypes | (remoteInsetsControllerControlsSystemBars(win) + ? (Type.statusBars() | Type.navigationBars()) + : 0)); + + updateBarControlTarget(win); + } + + private boolean forceShowingNavigationBars(WindowState win) { + // When "force show navigation bar" is enabled, it means both force visible is true, and + // we are in 3-button navigation. In this mode, the navigation bar is forcibly shown + // when activity type is ACTIVITY_TYPE_STANDARD which means Launcher or Recent could + // still control the navigation bar in this mode. return mPolicy.isForceShowNavigationBarEnabled() && win != null && win.getActivityType() == ACTIVITY_TYPE_STANDARD; } @@ -696,6 +716,21 @@ class InsetsPolicy { wereRevealedFromSwipeOnSystemBar); } + void dump(String prefix, PrintWriter pw) { + pw.println(prefix + "InsetsPolicy"); + prefix = prefix + " "; + pw.println(prefix + "status: " + StatusBarManager.windowStateToString(mStatusBar.mState)); + pw.println(prefix + "nav: " + StatusBarManager.windowStateToString(mNavBar.mState)); + if (mShowingTransientTypes != 0) { + pw.println(prefix + "mShowingTransientTypes=" + + WindowInsets.Type.toString(mShowingTransientTypes)); + } + if (mForcedShowingTypes != 0) { + pw.println(prefix + "mForcedShowingTypes=" + + WindowInsets.Type.toString(mForcedShowingTypes)); + } + } + private class BarWindow { private final int mId; diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index e1c865bb85be..2b8312c3ea60 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -40,6 +40,7 @@ import android.graphics.Rect; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import android.view.InsetsSource; +import android.view.InsetsSource.Flags; import android.view.InsetsSourceControl; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; @@ -81,6 +82,8 @@ class InsetsSourceProvider { private final Rect mSourceFrame = new Rect(); private final Rect mLastSourceFrame = new Rect(); private @NonNull Insets mInsetsHint = Insets.NONE; + private @Flags int mFlagsFromFrameProvider; + private @Flags int mFlagsFromServer; private final Consumer<Transaction> mSetLeashPositionConsumer = t -> { if (mControl != null) { @@ -189,6 +192,16 @@ class InsetsSourceProvider { } } + boolean setFlags(@Flags int flags, @Flags int mask) { + mFlagsFromServer = (mFlagsFromServer & ~mask) | (flags & mask); + final @Flags int mergedFlags = mFlagsFromFrameProvider | mFlagsFromServer; + if (mSource.getFlags() != mergedFlags) { + mSource.setFlags(mergedFlags); + return true; + } + return false; + } + /** * The source frame can affect the layout of other windows, so this should be called once the * window container gets laid out. @@ -217,11 +230,11 @@ class InsetsSourceProvider { mSourceFrame.set(frame); if (mFrameProvider != null) { - final int flags = mFrameProvider.apply( + mFlagsFromFrameProvider = mFrameProvider.apply( mWindowContainer.getDisplayContent().mDisplayFrames, mWindowContainer, mSourceFrame); - mSource.setFlags(flags); + mSource.setFlags(mFlagsFromFrameProvider | mFlagsFromServer); } updateSourceFrameForServerVisibility(); diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index addb5219c663..081ebe0e7cbd 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; +import static android.view.InsetsSource.FLAG_FORCE_CONSUMING; import static android.view.InsetsSource.ID_IME; import static android.view.WindowInsets.Type.displayCutout; import static android.view.WindowInsets.Type.ime; @@ -85,6 +86,8 @@ class InsetsStateController { } }; + private @InsetsType int mForcedConsumingTypes; + InsetsStateController(DisplayContent displayContent) { mDisplayContent = displayContent; } @@ -122,6 +125,11 @@ class InsetsStateController { provider = id == ID_IME ? new ImeInsetsSourceProvider(source, this, mDisplayContent) : new InsetsSourceProvider(source, this, mDisplayContent); + provider.setFlags( + (mForcedConsumingTypes & type) != 0 + ? FLAG_FORCE_CONSUMING + : 0, + FLAG_FORCE_CONSUMING); mProviders.put(id, provider); return provider; } @@ -137,6 +145,24 @@ class InsetsStateController { } } + void setForcedConsumingTypes(@InsetsType int types) { + if (mForcedConsumingTypes != types) { + mForcedConsumingTypes = types; + boolean changed = false; + for (int i = mProviders.size() - 1; i >= 0; i--) { + final InsetsSourceProvider provider = mProviders.valueAt(i); + changed |= provider.setFlags( + (types & provider.getSource().getType()) != 0 + ? FLAG_FORCE_CONSUMING + : 0, + FLAG_FORCE_CONSUMING); + } + if (changed) { + notifyInsetsChanged(); + } + } + } + /** * Called when a layout pass has occurred. */ @@ -391,6 +417,10 @@ class InsetsStateController { for (int i = mProviders.size() - 1; i >= 0; i--) { mProviders.valueAt(i).dump(pw, prefix + " "); } + if (mForcedConsumingTypes != 0) { + pw.println(prefix + "mForcedConsumingTypes=" + + WindowInsets.Type.toString(mForcedConsumingTypes)); + } } void dumpDebug(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) { |