diff --git a/core/java/android/view/InsetsFrameProvider.java b/core/java/android/view/InsetsFrameProvider.java index 72757807169ee..da54da16585d6 100644 --- a/core/java/android/view/InsetsFrameProvider.java +++ b/core/java/android/view/InsetsFrameProvider.java @@ -273,6 +273,9 @@ public class InsetsFrameProvider implements Parcelable { /** * Class to describe the insets size to be provided to window with specific window type. If not * used, same insets size will be sent as instructed in the insetsSize and source. + * + * If the insetsSize of given type is set to {@code null}, the insets source frame will be used + * directly for that window type. */ public static class InsetsSizeOverride implements Parcelable { public final int windowType; @@ -280,7 +283,7 @@ public class InsetsFrameProvider implements Parcelable { protected InsetsSizeOverride(Parcel in) { windowType = in.readInt(); - insetsSize = in.readParcelable(null, android.graphics.Insets.class); + insetsSize = in.readParcelable(null, Insets.class); } public InsetsSizeOverride(int type, Insets size) { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index c089511a7ce91..50cf63d529095 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -25,11 +25,16 @@ import static android.app.StatusBarManager.WindowVisibleState; import static android.app.StatusBarManager.windowStateToString; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES; +import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; +import static android.view.InsetsState.ITYPE_LEFT_GESTURES; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; +import static android.view.InsetsState.ITYPE_RIGHT_GESTURES; import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; @@ -77,6 +82,7 @@ import android.telecom.TelecomManager; import android.text.TextUtils; import android.util.Log; import android.view.Display; +import android.view.DisplayCutout; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.InsetsFrameProvider; @@ -240,6 +246,12 @@ public class NavigationBar extends ViewController implements private boolean mTransientShown; private boolean mTransientShownFromGestureOnSystemBar; + /** + * This is to indicate whether the navigation bar button is forced visible. This is true + * when the setup wizard is on display. When that happens, the window frame should be provided + * as insets size directly. + */ + private boolean mIsButtonForceVisible; private int mNavBarMode = NAV_BAR_MODE_3BUTTON; private LightBarController mLightBarController; private final LightBarController mMainLightBarController; @@ -623,6 +635,10 @@ public class NavigationBar extends ViewController implements mView.setTouchHandler(mTouchHandler); setNavBarMode(mNavBarMode); mEdgeBackGestureHandler.setStateChangeCallback(mView::updateStates); + mEdgeBackGestureHandler.setButtonForceVisibleChangeCallback((forceVisible) -> { + mIsButtonForceVisible = forceVisible; + repositionNavigationBar(mCurrentRotation); + }); mNavigationBarTransitions.addListener(this::onBarTransition); mView.updateRotationButton(); @@ -810,7 +826,6 @@ public class NavigationBar extends ViewController implements mLayoutDirection = ld; refreshLayout(ld); } - repositionNavigationBar(rotation); if (canShowSecondaryHandle()) { if (rotation != mCurrentRotation) { @@ -1599,23 +1614,15 @@ public class NavigationBar extends ViewController implements width, height, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR, - WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH | WindowManager.LayoutParams.FLAG_SLIPPERY, PixelFormat.TRANSLUCENT); lp.gravity = gravity; - if (insetsHeight != -1) { - lp.providedInsets = new InsetsFrameProvider[] { - new InsetsFrameProvider(ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, insetsHeight)) - }; - } else { - lp.providedInsets = new InsetsFrameProvider[] { - new InsetsFrameProvider(ITYPE_NAVIGATION_BAR) - }; - } + lp.providedInsets = getInsetsFrameProvider(insetsHeight, userContext); + lp.token = new Binder(); lp.accessibilityTitle = userContext.getString(R.string.nav_bar); lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC @@ -1628,6 +1635,68 @@ public class NavigationBar extends ViewController implements return lp; } + private InsetsFrameProvider[] getInsetsFrameProvider(int insetsHeight, Context userContext) { + final InsetsFrameProvider navBarProvider; + if (insetsHeight != -1 && !mIsButtonForceVisible) { + navBarProvider = new InsetsFrameProvider( + ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, insetsHeight)); + // Use window frame for IME. + navBarProvider.insetsSizeOverrides = new InsetsFrameProvider.InsetsSizeOverride[] { + new InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, null) + }; + } else { + navBarProvider = new InsetsFrameProvider(ITYPE_NAVIGATION_BAR); + navBarProvider.insetsSizeOverrides = new InsetsFrameProvider.InsetsSizeOverride[]{ + new InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, null) + }; + } + final boolean navBarTapThrough = userContext.getResources().getBoolean( + com.android.internal.R.bool.config_navBarTapThrough); + final InsetsFrameProvider bottomTappableProvider; + if (navBarTapThrough) { + bottomTappableProvider = new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT, + Insets.of(0, 0, 0, 0)); + } else { + bottomTappableProvider = new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT); + } + + if (!mEdgeBackGestureHandler.isHandlingGestures()) { + // 2/3 button navigation is on. Do not provide any gesture insets here. But need to keep + // the provider to support runtime update. + return new InsetsFrameProvider[] { + navBarProvider, + new InsetsFrameProvider( + ITYPE_BOTTOM_MANDATORY_GESTURES, Insets.NONE), + new InsetsFrameProvider(ITYPE_LEFT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY, + Insets.NONE, null), + new InsetsFrameProvider(ITYPE_RIGHT_GESTURES, + InsetsFrameProvider.SOURCE_DISPLAY, + Insets.NONE, null), + bottomTappableProvider + }; + } else { + // Gesture navigation + final int gestureHeight = userContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.navigation_bar_gesture_height); + final DisplayCutout cutout = userContext.getDisplay().getCutout(); + final int safeInsetsLeft = cutout != null ? cutout.getSafeInsetLeft() : 0; + final int safeInsetsRight = cutout != null ? cutout.getSafeInsetRight() : 0; + return new InsetsFrameProvider[] { + navBarProvider, + new InsetsFrameProvider( + ITYPE_BOTTOM_MANDATORY_GESTURES, Insets.of(0, 0, 0, gestureHeight)), + new InsetsFrameProvider(ITYPE_LEFT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY, + Insets.of(safeInsetsLeft + + mEdgeBackGestureHandler.getEdgeWidthLeft(), 0, 0, 0), null), + new InsetsFrameProvider(ITYPE_RIGHT_GESTURES, + InsetsFrameProvider.SOURCE_DISPLAY, + Insets.of(0, 0, safeInsetsRight + + mEdgeBackGestureHandler.getEdgeWidthRight(), 0), null), + bottomTappableProvider + }; + } + } + private boolean canShowSecondaryHandle() { return mNavBarMode == NAV_BAR_MODE_GESTURAL && mOrientationHandle != null; } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index 709467ffd3b50..10ff48babe162 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -175,6 +175,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker private final OverviewProxyService mOverviewProxyService; private final SysUiState mSysUiState; private Runnable mStateChangeCallback; + private Consumer mButtonForceVisibleCallback; private final PluginManager mPluginManager; private final ProtoTracer mProtoTracer; @@ -240,6 +241,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker private boolean mIsBackGestureAllowed; private boolean mGestureBlockingActivityRunning; private boolean mIsNewBackAffordanceEnabled; + private boolean mIsButtonForceVisible; private InputMonitor mInputMonitor; private InputChannelCompat.InputEventReceiver mInputEventReceiver; @@ -402,12 +404,29 @@ public class EdgeBackGestureHandler extends CurrentUserTracker mStateChangeCallback = callback; } + public void setButtonForceVisibleChangeCallback(Consumer callback) { + mButtonForceVisibleCallback = callback; + } + + public int getEdgeWidthLeft() { + return mEdgeWidthLeft; + } + + public int getEdgeWidthRight() { + return mEdgeWidthRight; + } + public void updateCurrentUserResources() { Resources res = mNavigationModeController.getCurrentUserContext().getResources(); mEdgeWidthLeft = mGestureNavigationSettingsObserver.getLeftSensitivity(res); mEdgeWidthRight = mGestureNavigationSettingsObserver.getRightSensitivity(res); - mIsBackGestureAllowed = - !mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible(); + final boolean previousForceVisible = mIsButtonForceVisible; + mIsButtonForceVisible = + mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible(); + if (previousForceVisible != mIsButtonForceVisible && mButtonForceVisibleCallback != null) { + mButtonForceVisibleCallback.accept(mIsButtonForceVisible); + } + mIsBackGestureAllowed = !mIsButtonForceVisible; final DisplayMetrics dm = res.getDisplayMetrics(); final float defaultGestureHeight = res.getDimension( diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 442777a202818..a40713a60e274 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -19,14 +19,11 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.view.Display.TYPE_INTERNAL; -import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES; -import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; +import static android.view.InsetsFrameProvider.SOURCE_FRAME; import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_CLIMATE_BAR; import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_LEFT_GESTURES; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_RIGHT_GESTURES; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; @@ -47,7 +44,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLO import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_UNRESTRICTED_GESTURE_EXCLUSION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; -import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; @@ -208,15 +204,12 @@ public class DisplayPolicy { private final Object mServiceAcquireLock = new Object(); private StatusBarManagerInternal mStatusBarManagerInternal; - @Px - private int mBottomGestureAdditionalInset; @Px private int mLeftGestureInset; @Px private int mRightGestureInset; private boolean mCanSystemBarsBeShownByUser; - private boolean mNavButtonForcedVisible; StatusBarManagerInternal getStatusBarManagerInternal() { synchronized (mServiceAcquireLock) { @@ -240,7 +233,6 @@ public class DisplayPolicy { private volatile boolean mHasNavigationBar; // Can the navigation bar ever move to the side? private volatile boolean mNavigationBarCanMove; - private volatile boolean mNavigationBarLetsThroughTaps; private volatile boolean mNavigationBarAlwaysShowOnSideGesture; // Written by vr manager thread, only read in this class. @@ -360,8 +352,6 @@ public class DisplayPolicy { private PointerLocationView mPointerLocationView; - private int mDisplayCutoutTouchableRegionSize; - private RefreshRatePolicy mRefreshRatePolicy; /** @@ -1150,71 +1140,9 @@ public class DisplayPolicy { break; case TYPE_NAVIGATION_BAR: mNavigationBar = win; - final TriConsumer navFrameProvider = - (displayFrames, windowContainer, inOutFrame) -> { - if (!mNavButtonForcedVisible) { - final LayoutParams lp = - win.mAttrs.forRotation(displayFrames.mRotation); - if (lp.providedInsets != null) { - for (InsetsFrameProvider provider : lp.providedInsets) { - if (provider.type != ITYPE_NAVIGATION_BAR) { - continue; - } - InsetsFrameProvider.calculateInsetsFrame( - displayFrames.mUnrestricted, - win.getBounds(), displayFrames.mDisplayCutoutSafe, - inOutFrame, provider.source, - provider.insetsSize, lp.privateFlags, - provider.minimalInsetsSizeInDisplayCutoutSafe); - } - } - inOutFrame.inset(win.mGivenContentInsets); - } - }; - final SparseArray> imeOverride = - new SparseArray<>(); - // For IME, we don't modify the frame. - imeOverride.put(TYPE_INPUT_METHOD, null); - mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win, - navFrameProvider, imeOverride); - - mDisplayContent.setInsetProvider(ITYPE_BOTTOM_MANDATORY_GESTURES, win, - (displayFrames, windowContainer, inOutFrame) -> { - inOutFrame.top -= mBottomGestureAdditionalInset; - }); - mDisplayContent.setInsetProvider(ITYPE_LEFT_GESTURES, win, - (displayFrames, windowContainer, inOutFrame) -> { - final int leftSafeInset = - Math.max(displayFrames.mDisplayCutoutSafe.left, 0); - inOutFrame.left = 0; - inOutFrame.top = 0; - inOutFrame.bottom = displayFrames.mHeight; - inOutFrame.right = leftSafeInset + mLeftGestureInset; - }); - mDisplayContent.setInsetProvider(ITYPE_RIGHT_GESTURES, win, - (displayFrames, windowContainer, inOutFrame) -> { - final int rightSafeInset = - Math.min(displayFrames.mDisplayCutoutSafe.right, - displayFrames.mUnrestricted.right); - inOutFrame.left = rightSafeInset - mRightGestureInset; - inOutFrame.top = 0; - inOutFrame.bottom = displayFrames.mHeight; - inOutFrame.right = displayFrames.mWidth; - }); - mDisplayContent.setInsetProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT, win, - (displayFrames, windowContainer, inOutFrame) -> { - if ((win.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0 - || mNavigationBarLetsThroughTaps) { - inOutFrame.setEmpty(); - } - }); - mInsetsSourceWindowsExceptIme.add(win); - if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar); break; } - // TODO(b/239145252): Temporarily skip the navigation bar as it is still with the hard-coded - // logic. - if (attrs.providedInsets != null && attrs.type != TYPE_NAVIGATION_BAR) { + if (attrs.providedInsets != null) { for (int i = attrs.providedInsets.length - 1; i >= 0; i--) { final InsetsFrameProvider provider = attrs.providedInsets[i]; switch (provider.type) { @@ -1242,24 +1170,8 @@ public class DisplayPolicy { // The index of the provider and corresponding insets types cannot change at // runtime as ensured in WMS. Make use of the index in the provider directly // to access the latest provided size at runtime. - final int index = i; final TriConsumer frameProvider = - provider.insetsSize != null - ? (displayFrames, windowContainer, inOutFrame) -> { - inOutFrame.inset(win.mGivenContentInsets); - final LayoutParams lp = - win.mAttrs.forRotation(displayFrames.mRotation); - final InsetsFrameProvider ifp = - win.mAttrs.forRotation(displayFrames.mRotation) - .providedInsets[index]; - InsetsFrameProvider.calculateInsetsFrame( - displayFrames.mUnrestricted, - windowContainer.getBounds(), - displayFrames.mDisplayCutoutSafe, - inOutFrame, ifp.source, - ifp.insetsSize, lp.privateFlags, - ifp.minimalInsetsSizeInDisplayCutoutSafe); - } : null; + getFrameProvider(win, provider, i); final InsetsFrameProvider.InsetsSizeOverride[] overrides = provider.insetsSizeOverrides; final SparseArray> @@ -1267,27 +1179,10 @@ public class DisplayPolicy { if (overrides != null) { overrideProviders = new SparseArray<>(); for (int j = overrides.length - 1; j >= 0; j--) { - final int overrideIndex = j; final TriConsumer overrideFrameProvider = - (displayFrames, windowContainer, inOutFrame) -> { - final LayoutParams lp = - win.mAttrs.forRotation( - displayFrames.mRotation); - final InsetsFrameProvider ifp = - win.mAttrs.providedInsets[index]; - InsetsFrameProvider.calculateInsetsFrame( - displayFrames.mUnrestricted, - windowContainer.getBounds(), - displayFrames.mDisplayCutoutSafe, - inOutFrame, ifp.source, - ifp.insetsSizeOverrides[ - overrideIndex].insetsSize, - lp.privateFlags, - null); - }; - overrideProviders.put(overrides[j].windowType, - overrideFrameProvider); + getOverrideFrameProvider(win, i, j); + overrideProviders.put(overrides[j].windowType, overrideFrameProvider); } } else { overrideProviders = null; @@ -1299,6 +1194,36 @@ public class DisplayPolicy { } } + @Nullable + private TriConsumer getFrameProvider(WindowState win, + InsetsFrameProvider provider, int index) { + if (provider.insetsSize == null && provider.source == SOURCE_FRAME) { + return null; + } + return (displayFrames, windowContainer, inOutFrame) -> { + inOutFrame.inset(win.mGivenContentInsets); + final LayoutParams lp = win.mAttrs.forRotation(displayFrames.mRotation); + final InsetsFrameProvider ifp = lp.providedInsets[index]; + InsetsFrameProvider.calculateInsetsFrame(displayFrames.mUnrestricted, + windowContainer.getBounds(), displayFrames.mDisplayCutoutSafe, inOutFrame, + ifp.source, ifp.insetsSize, lp.privateFlags, + ifp.minimalInsetsSizeInDisplayCutoutSafe); + }; + } + + @NonNull + private TriConsumer getOverrideFrameProvider( + WindowState win, int index, int overrideIndex) { + return (displayFrames, windowContainer, inOutFrame) -> { + final LayoutParams lp = win.mAttrs.forRotation(displayFrames.mRotation); + final InsetsFrameProvider ifp = lp.providedInsets[index]; + InsetsFrameProvider.calculateInsetsFrame(displayFrames.mUnrestricted, + windowContainer.getBounds(), displayFrames.mDisplayCutoutSafe, inOutFrame, + ifp.source, ifp.insetsSizeOverrides[overrideIndex].insetsSize, lp.privateFlags, + null); + }; + } + @WindowManagerPolicy.AltBarPosition private int getAltBarPosition(WindowManager.LayoutParams params) { switch (params.gravity) { @@ -1386,16 +1311,6 @@ public class DisplayPolicy { mInsetsSourceWindowsExceptIme.remove(win); } - private int getStatusBarHeight(DisplayFrames displayFrames) { - int statusBarHeight; - if (mStatusBar != null) { - statusBarHeight = mStatusBar.mAttrs.forRotation(displayFrames.mRotation).height; - } else { - statusBarHeight = 0; - } - return Math.max(statusBarHeight, displayFrames.mDisplayCutoutSafe.top); - } - WindowState getStatusBar() { return mStatusBar != null ? mStatusBar : mStatusBarAlt; } @@ -1892,27 +1807,12 @@ public class DisplayPolicy { final Resources res = getCurrentUserResources(); final int portraitRotation = displayRotation.getPortraitRotation(); - if (hasStatusBar()) { - mDisplayCutoutTouchableRegionSize = res.getDimensionPixelSize( - R.dimen.display_cutout_touchable_region_size); - } else { - mDisplayCutoutTouchableRegionSize = 0; - } - mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode); mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res); mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res); - mNavButtonForcedVisible = - mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible(); - mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough); mNavigationBarAlwaysShowOnSideGesture = res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture); - // This should calculate how much above the frame we accept gestures. - mBottomGestureAdditionalInset = - res.getDimensionPixelSize(R.dimen.navigation_bar_gesture_height) - - getNavigationBarFrameHeight(portraitRotation); - updateConfigurationAndScreenSizeDependentBehaviors(); final boolean shouldAttach = diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c9d3dac104de8..80644206ec4a7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -266,6 +266,7 @@ import android.view.InputApplicationHandle; import android.view.InputChannel; import android.view.InputDevice; import android.view.InputWindowHandle; +import android.view.InsetsFrameProvider; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.InsetsVisibilities; @@ -2277,6 +2278,27 @@ public class WindowManagerService extends IWindowManager.Stub "Insets types can not be changed after the window is " + "added."); } + final InsetsFrameProvider.InsetsSizeOverride[] overrides = + win.mAttrs.providedInsets[i].insetsSizeOverrides; + final InsetsFrameProvider.InsetsSizeOverride[] newOverrides = + attrs.providedInsets[i].insetsSizeOverrides; + if (!(overrides == null && newOverrides == null)) { + if (overrides == null || newOverrides == null + || (overrides.length != newOverrides.length)) { + throw new IllegalArgumentException( + "Insets override types can not be changed after the " + + "window is added."); + } else { + final int overrideTypes = overrides.length; + for (int j = 0; j < overrideTypes; j++) { + if (overrides[j].windowType != newOverrides[j].windowType) { + throw new IllegalArgumentException( + "Insets override types can not be changed after" + + " the window is added."); + } + } + } + } } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index f2bc47dfd6e90..1a006f342b88e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -19,6 +19,8 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; +import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES; +import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES; @@ -74,7 +76,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_regular() { addStatusBar(); - addWindow(TYPE_NAVIGATION_BAR, "navBar"); + addNavigationBar(); final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); @@ -86,7 +88,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_multiWindowTaskVisible() { addStatusBar(); - addWindow(TYPE_NAVIGATION_BAR, "navBar"); + addNavigationBar(); final WindowState win = createWindow(null, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app"); @@ -99,7 +101,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_freeformTaskVisible() { addStatusBar(); - addWindow(TYPE_NAVIGATION_BAR, "navBar"); + addNavigationBar(); final WindowState win = createWindow(null, WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app"); @@ -112,7 +114,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_forceStatusBarVisible() { addStatusBar().mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; - addWindow(TYPE_NAVIGATION_BAR, "navBar"); + addNavigationBar(); final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); @@ -126,7 +128,7 @@ public class InsetsPolicyTest extends WindowTestsBase { addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.privateFlags |= PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; addStatusBar(); - addWindow(TYPE_NAVIGATION_BAR, "navBar"); + addNavigationBar(); final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); @@ -139,7 +141,7 @@ public class InsetsPolicyTest extends WindowTestsBase { public void testControlsForDispatch_statusBarForceShowNavigation_butFocusedAnyways() { WindowState notifShade = addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade"); notifShade.mAttrs.privateFlags |= PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; - addWindow(TYPE_NAVIGATION_BAR, "navBar"); + addNavigationBar(); mDisplayContent.getInsetsPolicy().updateBarControlTarget(notifShade); InsetsSourceControl[] controls @@ -155,7 +157,7 @@ public class InsetsPolicyTest extends WindowTestsBase { mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController()); mDisplayContent.getInsetsPolicy().setRemoteInsetsControllerControlsSystemBars(true); addStatusBar(); - addWindow(TYPE_NAVIGATION_BAR, "navBar"); + addNavigationBar(); final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); @@ -166,7 +168,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_topAppHidesStatusBar() { addStatusBar(); - addWindow(TYPE_NAVIGATION_BAR, "navBar"); + addNavigationBar(); // Add a fullscreen (MATCH_PARENT x MATCH_PARENT) app window which hides status bar. final WindowState fullscreenApp = addWindow(TYPE_APPLICATION, "fullscreenApp"); @@ -261,7 +263,7 @@ public class InsetsPolicyTest extends WindowTestsBase { final WindowState statusBar = addStatusBar(); statusBar.setHasSurface(true); statusBar.getControllableInsetProvider().setServerVisible(true); - final WindowState navBar = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar"); + final WindowState navBar = addNavigationBar(); navBar.setHasSurface(true); navBar.getControllableInsetProvider().setServerVisible(true); final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy()); @@ -301,8 +303,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testShowTransientBars_statusBarCanBeTransient_appGetsStatusBarFakeControl() { addStatusBar().getControllableInsetProvider().getSource().setVisible(false); - addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar") - .getControllableInsetProvider().setServerVisible(true); + addNavigationBar().getControllableInsetProvider().setServerVisible(true); final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy()); doNothing().when(policy).startAnimation(anyBoolean(), any()); @@ -331,8 +332,8 @@ public class InsetsPolicyTest extends WindowTestsBase { public void testAbortTransientBars_bothCanBeAborted_appGetsBothRealControls() { final InsetsSource statusBarSource = addStatusBar().getControllableInsetProvider().getSource(); - final InsetsSource navBarSource = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar") - .getControllableInsetProvider().getSource(); + final InsetsSource navBarSource = + addNavigationBar().getControllableInsetProvider().getSource(); statusBarSource.setVisible(false); navBarSource.setVisible(false); mAppWindow.mAboveInsetsState.addSource(navBarSource); @@ -383,8 +384,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testShowTransientBars_abortsWhenControlTargetChanges() { addStatusBar().getControllableInsetProvider().getSource().setVisible(false); - addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar") - .getControllableInsetProvider().getSource().setVisible(false); + addNavigationBar().getControllableInsetProvider().getSource().setVisible(false); final WindowState app = addWindow(TYPE_APPLICATION, "app"); final WindowState app2 = addWindow(TYPE_APPLICATION, "app"); @@ -400,9 +400,15 @@ public class InsetsPolicyTest extends WindowTestsBase { assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR)); } - private WindowState addNonFocusableWindow(int type, String name) { - WindowState win = addWindow(type, name); + private WindowState addNavigationBar() { + final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "navBar"); win.mAttrs.flags |= FLAG_NOT_FOCUSABLE; + win.mAttrs.providedInsets = new InsetsFrameProvider[] { + new InsetsFrameProvider(ITYPE_NAVIGATION_BAR), + new InsetsFrameProvider(ITYPE_BOTTOM_MANDATORY_GESTURES), + new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT) + }; + mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs); return win; } @@ -429,6 +435,10 @@ public class InsetsPolicyTest extends WindowTestsBase { } private InsetsSourceControl[] addWindowAndGetControlsForDispatch(WindowState win) { + mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs); + // Force update the focus in DisplayPolicy here. Otherwise, without server side focus + // update, the policy relying on windowing type will never get updated. + mDisplayContent.getDisplayPolicy().focusChangedLw(null, win); mDisplayContent.getInsetsPolicy().updateBarControlTarget(win); return mDisplayContent.getInsetsStateController().getControlsForDispatch(win); } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 40326e9ad7f6d..b259cdaff8396 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -26,6 +26,8 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.os.Process.SYSTEM_UID; +import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES; +import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES; @@ -347,6 +349,11 @@ class WindowTestsBase extends SystemServiceTestsBase { LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; mNavBarWindow.mAttrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT; + mNavBarWindow.mAttrs.providedInsets = new InsetsFrameProvider[] { + new InsetsFrameProvider(ITYPE_NAVIGATION_BAR), + new InsetsFrameProvider(ITYPE_BOTTOM_MANDATORY_GESTURES), + new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT) + }; for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) { mNavBarWindow.mAttrs.paramsForRotation[rot] = getNavBarLayoutParamsForRotation(rot); @@ -400,6 +407,11 @@ class WindowTestsBase extends SystemServiceTestsBase { lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT; lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + lp.providedInsets = new InsetsFrameProvider[] { + new InsetsFrameProvider(ITYPE_NAVIGATION_BAR), + new InsetsFrameProvider(ITYPE_BOTTOM_MANDATORY_GESTURES), + new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT) + }; return lp; }