diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index a2b9cf9c5b3c3..73641f4d76ac8 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -287,7 +287,8 @@ class InsetsPolicy { if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) { return mDummyControlTarget; } - if (focusedWin == mPolicy.getNotificationShade()) { + final WindowState notificationShade = mPolicy.getNotificationShade(); + if (focusedWin == notificationShade) { // Notification shade has control anyways, no reason to force anything. return focusedWin; } @@ -308,9 +309,10 @@ class InsetsPolicy { // fake control to the client, so that it can re-show the bar during this scenario. return mDummyControlTarget; } - if (!canBeTopFullscreenOpaqueWindow(focusedWin) && mPolicy.topAppHidesStatusBar()) { + if (!canBeTopFullscreenOpaqueWindow(focusedWin) && mPolicy.topAppHidesStatusBar() + && (notificationShade == null || !notificationShade.canReceiveKeys())) { // Non-fullscreen focused window should not break the state that the top-fullscreen-app - // window hides status bar. + // window hides status bar, unless the notification shade can receive keys. return mPolicy.getTopFullscreenOpaqueWindow(); } return focusedWin; 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 02d9c42517670..bbe811d152589 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -29,6 +29,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -226,6 +227,40 @@ public class InsetsPolicyTest extends WindowTestsBase { // mTopFullscreenOpaqueWindowState is still fullscreenApp. verify(sbmi).setWindowState(mDisplayContent.mDisplayId, StatusBarManager.WINDOW_STATUS_BAR, StatusBarManager.WINDOW_STATE_SHOWING); + + // Add a system window: panel. + final WindowState panel = addWindow(TYPE_STATUS_BAR_SUB_PANEL, "panel"); + mDisplayContent.getInsetsPolicy().updateBarControlTarget(panel); + + // panel is the focused window, but it can only control navigation bar. + // Because fullscreenApp is hiding status bar. + InsetsSourceControl[] panelControls = + mDisplayContent.getInsetsStateController().getControlsForDispatch(panel); + assertNotNull(panelControls); + assertEquals(1, panelControls.length); + assertEquals(ITYPE_NAVIGATION_BAR, panelControls[0].getType()); + + // Add notificationShade and make it can receive keys. + final WindowState shade = addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade"); + shade.setHasSurface(true); + assertTrue(shade.canReceiveKeys()); + mDisplayContent.getInsetsPolicy().updateBarControlTarget(panel); + + // panel can control both system bars now. + panelControls = mDisplayContent.getInsetsStateController().getControlsForDispatch(panel); + assertNotNull(panelControls); + assertEquals(2, panelControls.length); + + // Make notificationShade cannot receive keys. + shade.mAttrs.flags |= FLAG_NOT_FOCUSABLE; + assertFalse(shade.canReceiveKeys()); + mDisplayContent.getInsetsPolicy().updateBarControlTarget(panel); + + // panel can only control navigation bar now. + panelControls = mDisplayContent.getInsetsStateController().getControlsForDispatch(panel); + assertNotNull(panelControls); + assertEquals(1, panelControls.length); + assertEquals(ITYPE_NAVIGATION_BAR, panelControls[0].getType()); } @UseTestDisplay(addWindows = W_ACTIVITY)