Loading services/core/java/com/android/server/wm/DisplayPolicy.java +39 −20 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; Loading Loading @@ -156,6 +157,7 @@ import android.view.InputDevice; import android.view.InputEvent; import android.view.InputEventReceiver; import android.view.InsetsFlags; import android.view.InsetsSource; import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; import android.view.MotionEvent; Loading Loading @@ -391,7 +393,8 @@ public class DisplayPolicy { private boolean mDreamingLockscreen; private boolean mAllowLockscreenWhenOn; private InputConsumer mInputConsumer = null; @VisibleForTesting InputConsumer mInputConsumer = null; private PointerLocationView mPointerLocationView; Loading Loading @@ -1372,13 +1375,6 @@ public class DisplayPolicy { synchronized (mLock) { mForceClearedSystemUiFlags &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; mDisplayContent.reevaluateStatusBarVisibility(); if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL && mNavigationBar != null) { final InsetsControlTarget target = mNavigationBar.getControllableInsetProvider().getControlTarget(); if (target != null) { target.showInsets(Type.navigationBars(), false /* fromIme */); } } } } }; Loading Loading @@ -1406,6 +1402,7 @@ public class DisplayPolicy { if (mInputConsumer == null) { return; } showNavigationBar(); // Any user activity always causes us to show the // navigation controls, if they had been hidden. // We also clear the low profile and only content Loading Loading @@ -1439,6 +1436,16 @@ public class DisplayPolicy { finishInputEvent(event, false /* handled */); } } private void showNavigationBar() { final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController() .peekSourceProvider(ITYPE_NAVIGATION_BAR); final InsetsControlTarget target = provider != null ? provider.getControlTarget() : null; if (target != null) { target.showInsets(Type.navigationBars(), false /* fromIme */); } } } private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames, Loading Loading @@ -1500,9 +1507,13 @@ public class DisplayPolicy { // drive nav being hidden only by whether it is requested. final int sysui = mLastSystemUiFlags; final int behavior = mLastBehavior; final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_NAVIGATION_BAR); boolean navVisible = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL ? (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 : isNavigationBarRequestedVisible(); : provider != null ? provider.isClientVisible() : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR); boolean navTranslucent = (sysui & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0; boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0 Loading @@ -1517,7 +1528,7 @@ public class DisplayPolicy { && (mNotificationShade.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0; updateHideNavInputEventReceiver(navVisible, navAllowedHidden); updateHideNavInputEventReceiver(); // For purposes of positioning and showing the nav bar, if we have decided that it can't // be hidden (because of the screen aspect ratio), then take that into account. Loading @@ -1539,30 +1550,38 @@ public class DisplayPolicy { mLastNotificationShadeForcesShowingNavigation = notificationShadeForcesShowingNavigation; } boolean isNavigationBarRequestedVisible() { final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_NAVIGATION_BAR); return provider == null ? InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR) : provider.isClientVisible(); } void updateHideNavInputEventReceiver(boolean navVisible, boolean navAllowedHidden) { void updateHideNavInputEventReceiver() { final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController() .peekSourceProvider(ITYPE_NAVIGATION_BAR); final InsetsControlTarget navControlTarget = provider != null ? provider.getControlTarget() : null; final WindowState navControllingWin = navControlTarget instanceof WindowState ? (WindowState) navControlTarget : null; final InsetsState requestedState = navControllingWin != null ? navControllingWin.getRequestedInsetsState() : null; final InsetsSource navSource = requestedState != null ? requestedState.peekSource(ITYPE_NAVIGATION_BAR) : null; final boolean navVisible = navSource != null ? navSource.isVisible() : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR); final boolean showBarsByTouch = navControllingWin != null && navControllingWin.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_BARS_BY_TOUCH; // When the navigation bar isn't visible, we put up a fake input window to catch all // touch events. This way we can detect when the user presses anywhere to bring back the // nav bar and ensure the application doesn't see the event. if (navVisible || navAllowedHidden) { if (navVisible || !showBarsByTouch) { if (mInputConsumer != null) { mInputConsumer.dismiss(); mHandler.sendMessage( mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer)); mInputConsumer = null; Slog.v(TAG, INPUT_CONSUMER_NAVIGATION + " dismissed."); } } else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) { mInputConsumer = mDisplayContent.getInputMonitor().createInputConsumer( mHandler.getLooper(), INPUT_CONSUMER_NAVIGATION, HideNavInputEventReceiver::new); Slog.v(TAG, INPUT_CONSUMER_NAVIGATION + " created."); // As long as mInputConsumer is active, hover events are not dispatched to the app // and the pointer icon is likely to become stale. Hide it to avoid confusion. InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL); Loading services/core/java/com/android/server/wm/InsetsPolicy.java +2 −9 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static android.view.InsetsController.ANIMATION_TYPE_SHOW; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.SyncRtSurfaceTransactionApplier.applyParams; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; Loading Loading @@ -95,13 +94,7 @@ class InsetsPolicy { || focusedWin != getNavControlTarget(focusedWin) || focusedWin.getRequestedInsetsState().getSource(ITYPE_NAVIGATION_BAR) .isVisible()); updateHideNavInputEventReceiver(); } private void updateHideNavInputEventReceiver() { mPolicy.updateHideNavInputEventReceiver(mPolicy.isNavigationBarRequestedVisible(), mFocusedWin != null && mFocusedWin.mAttrs.insetsFlags.behavior != BEHAVIOR_SHOW_BARS_BY_TOUCH); mPolicy.updateHideNavInputEventReceiver(); } boolean isHidden(@InternalInsetsType int type) { Loading Loading @@ -201,7 +194,7 @@ class InsetsPolicy { if (windowState == getNavControlTarget(mFocusedWin)) { mNavBar.setVisible(state.getSource(ITYPE_NAVIGATION_BAR).isVisible()); } updateHideNavInputEventReceiver(); mPolicy.updateHideNavInputEventReceiver(); } /** Loading services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +46 −1 Original line number Diff line number Diff line Loading @@ -16,9 +16,12 @@ package com.android.server.wm; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; Loading @@ -29,29 +32,33 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 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_TOAST; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.graphics.PixelFormat; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.InsetsState; import android.view.WindowManager; import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import org.junit.Test; Loading Loading @@ -307,4 +314,42 @@ public class DisplayPolicyTests extends WindowTestsBase { win.mHasSurface = true; return win; } @Test public void testUpdateHideNavInputEventReceiver() { final InsetsPolicy insetsPolicy = mDisplayContent.getInsetsPolicy(); final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); displayPolicy.addWindowLw(mStatusBarWindow, mStatusBarWindow.mAttrs); displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs); displayPolicy.addWindowLw(mNotificationShadeWindow, mNotificationShadeWindow.mAttrs); spyOn(displayPolicy); doReturn(true).when(displayPolicy).hasNavigationBar(); // App doesn't request to hide navigation bar. insetsPolicy.updateBarControlTarget(mAppWindow); assertNull(displayPolicy.mInputConsumer); // App requests to hide navigation bar. final InsetsState requestedState = new InsetsState(); requestedState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false); mAppWindow.updateRequestedInsetsState(requestedState); insetsPolicy.onInsetsModified(mAppWindow, requestedState); assertNotNull(displayPolicy.mInputConsumer); // App still requests to hide navigation bar, but without BEHAVIOR_SHOW_BARS_BY_TOUCH. mAppWindow.mAttrs.insetsFlags.behavior = BEHAVIOR_SHOW_BARS_BY_SWIPE; insetsPolicy.updateBarControlTarget(mAppWindow); assertNull(displayPolicy.mInputConsumer); // App still requests to hide navigation bar, but with BEHAVIOR_SHOW_BARS_BY_TOUCH. mAppWindow.mAttrs.insetsFlags.behavior = BEHAVIOR_SHOW_BARS_BY_TOUCH; insetsPolicy.updateBarControlTarget(mAppWindow); assertNotNull(displayPolicy.mInputConsumer); // App still requests to hide navigation bar with BEHAVIOR_SHOW_BARS_BY_TOUCH, // but notification shade forcibly shows navigation bar mNotificationShadeWindow.mAttrs.privateFlags |= PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; insetsPolicy.updateBarControlTarget(mAppWindow); assertNull(displayPolicy.mInputConsumer); } } Loading
services/core/java/com/android/server/wm/DisplayPolicy.java +39 −20 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; Loading Loading @@ -156,6 +157,7 @@ import android.view.InputDevice; import android.view.InputEvent; import android.view.InputEventReceiver; import android.view.InsetsFlags; import android.view.InsetsSource; import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; import android.view.MotionEvent; Loading Loading @@ -391,7 +393,8 @@ public class DisplayPolicy { private boolean mDreamingLockscreen; private boolean mAllowLockscreenWhenOn; private InputConsumer mInputConsumer = null; @VisibleForTesting InputConsumer mInputConsumer = null; private PointerLocationView mPointerLocationView; Loading Loading @@ -1372,13 +1375,6 @@ public class DisplayPolicy { synchronized (mLock) { mForceClearedSystemUiFlags &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; mDisplayContent.reevaluateStatusBarVisibility(); if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL && mNavigationBar != null) { final InsetsControlTarget target = mNavigationBar.getControllableInsetProvider().getControlTarget(); if (target != null) { target.showInsets(Type.navigationBars(), false /* fromIme */); } } } } }; Loading Loading @@ -1406,6 +1402,7 @@ public class DisplayPolicy { if (mInputConsumer == null) { return; } showNavigationBar(); // Any user activity always causes us to show the // navigation controls, if they had been hidden. // We also clear the low profile and only content Loading Loading @@ -1439,6 +1436,16 @@ public class DisplayPolicy { finishInputEvent(event, false /* handled */); } } private void showNavigationBar() { final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController() .peekSourceProvider(ITYPE_NAVIGATION_BAR); final InsetsControlTarget target = provider != null ? provider.getControlTarget() : null; if (target != null) { target.showInsets(Type.navigationBars(), false /* fromIme */); } } } private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames, Loading Loading @@ -1500,9 +1507,13 @@ public class DisplayPolicy { // drive nav being hidden only by whether it is requested. final int sysui = mLastSystemUiFlags; final int behavior = mLastBehavior; final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_NAVIGATION_BAR); boolean navVisible = ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL ? (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 : isNavigationBarRequestedVisible(); : provider != null ? provider.isClientVisible() : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR); boolean navTranslucent = (sysui & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0; boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0 Loading @@ -1517,7 +1528,7 @@ public class DisplayPolicy { && (mNotificationShade.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0; updateHideNavInputEventReceiver(navVisible, navAllowedHidden); updateHideNavInputEventReceiver(); // For purposes of positioning and showing the nav bar, if we have decided that it can't // be hidden (because of the screen aspect ratio), then take that into account. Loading @@ -1539,30 +1550,38 @@ public class DisplayPolicy { mLastNotificationShadeForcesShowingNavigation = notificationShadeForcesShowingNavigation; } boolean isNavigationBarRequestedVisible() { final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_NAVIGATION_BAR); return provider == null ? InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR) : provider.isClientVisible(); } void updateHideNavInputEventReceiver(boolean navVisible, boolean navAllowedHidden) { void updateHideNavInputEventReceiver() { final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController() .peekSourceProvider(ITYPE_NAVIGATION_BAR); final InsetsControlTarget navControlTarget = provider != null ? provider.getControlTarget() : null; final WindowState navControllingWin = navControlTarget instanceof WindowState ? (WindowState) navControlTarget : null; final InsetsState requestedState = navControllingWin != null ? navControllingWin.getRequestedInsetsState() : null; final InsetsSource navSource = requestedState != null ? requestedState.peekSource(ITYPE_NAVIGATION_BAR) : null; final boolean navVisible = navSource != null ? navSource.isVisible() : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR); final boolean showBarsByTouch = navControllingWin != null && navControllingWin.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_BARS_BY_TOUCH; // When the navigation bar isn't visible, we put up a fake input window to catch all // touch events. This way we can detect when the user presses anywhere to bring back the // nav bar and ensure the application doesn't see the event. if (navVisible || navAllowedHidden) { if (navVisible || !showBarsByTouch) { if (mInputConsumer != null) { mInputConsumer.dismiss(); mHandler.sendMessage( mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer)); mInputConsumer = null; Slog.v(TAG, INPUT_CONSUMER_NAVIGATION + " dismissed."); } } else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) { mInputConsumer = mDisplayContent.getInputMonitor().createInputConsumer( mHandler.getLooper(), INPUT_CONSUMER_NAVIGATION, HideNavInputEventReceiver::new); Slog.v(TAG, INPUT_CONSUMER_NAVIGATION + " created."); // As long as mInputConsumer is active, hover events are not dispatched to the app // and the pointer icon is likely to become stale. Hide it to avoid confusion. InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL); Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +2 −9 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static android.view.InsetsController.ANIMATION_TYPE_SHOW; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.SyncRtSurfaceTransactionApplier.applyParams; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; Loading Loading @@ -95,13 +94,7 @@ class InsetsPolicy { || focusedWin != getNavControlTarget(focusedWin) || focusedWin.getRequestedInsetsState().getSource(ITYPE_NAVIGATION_BAR) .isVisible()); updateHideNavInputEventReceiver(); } private void updateHideNavInputEventReceiver() { mPolicy.updateHideNavInputEventReceiver(mPolicy.isNavigationBarRequestedVisible(), mFocusedWin != null && mFocusedWin.mAttrs.insetsFlags.behavior != BEHAVIOR_SHOW_BARS_BY_TOUCH); mPolicy.updateHideNavInputEventReceiver(); } boolean isHidden(@InternalInsetsType int type) { Loading Loading @@ -201,7 +194,7 @@ class InsetsPolicy { if (windowState == getNavControlTarget(mFocusedWin)) { mNavBar.setVisible(state.getSource(ITYPE_NAVIGATION_BAR).isVisible()); } updateHideNavInputEventReceiver(); mPolicy.updateHideNavInputEventReceiver(); } /** Loading
services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +46 −1 Original line number Diff line number Diff line Loading @@ -16,9 +16,12 @@ package com.android.server.wm; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; Loading @@ -29,29 +32,33 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 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_TOAST; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.graphics.PixelFormat; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.InsetsState; import android.view.WindowManager; import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import org.junit.Test; Loading Loading @@ -307,4 +314,42 @@ public class DisplayPolicyTests extends WindowTestsBase { win.mHasSurface = true; return win; } @Test public void testUpdateHideNavInputEventReceiver() { final InsetsPolicy insetsPolicy = mDisplayContent.getInsetsPolicy(); final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); displayPolicy.addWindowLw(mStatusBarWindow, mStatusBarWindow.mAttrs); displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs); displayPolicy.addWindowLw(mNotificationShadeWindow, mNotificationShadeWindow.mAttrs); spyOn(displayPolicy); doReturn(true).when(displayPolicy).hasNavigationBar(); // App doesn't request to hide navigation bar. insetsPolicy.updateBarControlTarget(mAppWindow); assertNull(displayPolicy.mInputConsumer); // App requests to hide navigation bar. final InsetsState requestedState = new InsetsState(); requestedState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false); mAppWindow.updateRequestedInsetsState(requestedState); insetsPolicy.onInsetsModified(mAppWindow, requestedState); assertNotNull(displayPolicy.mInputConsumer); // App still requests to hide navigation bar, but without BEHAVIOR_SHOW_BARS_BY_TOUCH. mAppWindow.mAttrs.insetsFlags.behavior = BEHAVIOR_SHOW_BARS_BY_SWIPE; insetsPolicy.updateBarControlTarget(mAppWindow); assertNull(displayPolicy.mInputConsumer); // App still requests to hide navigation bar, but with BEHAVIOR_SHOW_BARS_BY_TOUCH. mAppWindow.mAttrs.insetsFlags.behavior = BEHAVIOR_SHOW_BARS_BY_TOUCH; insetsPolicy.updateBarControlTarget(mAppWindow); assertNotNull(displayPolicy.mInputConsumer); // App still requests to hide navigation bar with BEHAVIOR_SHOW_BARS_BY_TOUCH, // but notification shade forcibly shows navigation bar mNotificationShadeWindow.mAttrs.privateFlags |= PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; insetsPolicy.updateBarControlTarget(mAppWindow); assertNull(displayPolicy.mInputConsumer); } }