From 070ae52e711296ad2b429c9a532a7fe3edffa997 Mon Sep 17 00:00:00 2001 From: Yunfan Chen Date: Wed, 28 Sep 2022 18:53:38 +0900 Subject: [PATCH] Migrate Navigation Bar to InsetsFrameProvider This patch is moving the navigation bar related insets logic from DisplayPolicy to com.android.systemui.navigationbar package. To fully match the feature, callbacks between NavigationBar and EdgeBackGestureHandler is added to handle the nav bar button force visible case. Bug: 239145252 Test: DisplayPolicyInsetsTests Test: InsetsPolicyTest DisplayPolicyTests Test: InsetsControllerTest Change-Id: I628a9e24df14268f2c7e92ab8ecd8d5d0d611847 --- .../android/view/InsetsFrameProvider.java | 5 +- .../systemui/navigationbar/NavigationBar.java | 93 ++++++++-- .../gestural/EdgeBackGestureHandler.java | 23 ++- .../com/android/server/wm/DisplayPolicy.java | 170 ++++-------------- .../server/wm/WindowManagerService.java | 22 +++ .../android/server/wm/InsetsPolicyTest.java | 44 +++-- .../android/server/wm/WindowTestsBase.java | 12 ++ 7 files changed, 202 insertions(+), 167 deletions(-) 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 50a10bc0b15ac..fb5da05c91f5a 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; @@ -238,6 +244,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; @@ -597,6 +609,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(); @@ -782,7 +798,6 @@ public class NavigationBar extends ViewController implements mLayoutDirection = ld; refreshLayout(ld); } - repositionNavigationBar(rotation); if (canShowSecondaryHandle()) { if (rotation != mCurrentRotation) { @@ -1571,23 +1586,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 @@ -1600,6 +1607,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 a8799c744656b..ec8d84f48d284 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 5ac034b8954f4..b18937bc9e8b4 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; @@ -2276,6 +2277,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; }