diff options
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 63 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java | 40 |
2 files changed, 70 insertions, 33 deletions
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index a9bb690d4e53..3858ffdd4467 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -8835,48 +8835,45 @@ public class WindowManagerService extends IWindowManager.Stub } void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) { - if (!win.hideNonSystemOverlayWindowsWhenVisible() - && !mHidingNonSystemOverlayWindows.contains(win)) { + final boolean effective = (surfaceShown && win.hideNonSystemOverlayWindowsWhenVisible()); + if (effective == mHidingNonSystemOverlayWindows.contains(win)) { return; } - final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty(); - final int numUIDsRequestHidingPreUpdate = mHidingNonSystemOverlayWindowsCountPerUid.size(); - if (surfaceShown && win.hideNonSystemOverlayWindowsWhenVisible()) { - if (!mHidingNonSystemOverlayWindows.contains(win)) { - mHidingNonSystemOverlayWindows.add(win); - int uid = win.getOwningUid(); - int count = mHidingNonSystemOverlayWindowsCountPerUid.getOrDefault(uid, 0); - mHidingNonSystemOverlayWindowsCountPerUid.put(uid, count + 1); - } + + if (effective) { + mHidingNonSystemOverlayWindows.add(win); } else { mHidingNonSystemOverlayWindows.remove(win); - int uid = win.getOwningUid(); - int count = mHidingNonSystemOverlayWindowsCountPerUid.getOrDefault(uid, 0); - if (count <= 1) { - mHidingNonSystemOverlayWindowsCountPerUid.remove(win.getOwningUid()); - } else { - mHidingNonSystemOverlayWindowsCountPerUid.put(uid, count - 1); - } } - final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); - final int numUIDSRequestHidingPostUpdate = mHidingNonSystemOverlayWindowsCountPerUid.size(); + + final boolean changed; if (Flags.fixHideOverlayApi()) { - if (numUIDSRequestHidingPostUpdate == numUIDsRequestHidingPreUpdate) { - return; - } - // The visibility of SAWs needs to be refreshed only when the number of uids that - // request hiding SAWs changes 0->1, 1->0, 1->2 or 2->1. - if (numUIDSRequestHidingPostUpdate != 1 && numUIDsRequestHidingPreUpdate != 1) { - return; + final int uid = win.getOwningUid(); + final int numUIDsPreUpdate = mHidingNonSystemOverlayWindowsCountPerUid.size(); + final int newCount = mHidingNonSystemOverlayWindowsCountPerUid.getOrDefault(uid, 0) + + (effective ? +1 : -1); + if (newCount <= 0) { + mHidingNonSystemOverlayWindowsCountPerUid.remove(uid); + } else { + mHidingNonSystemOverlayWindowsCountPerUid.put(uid, newCount); } + final int numUIDsPostUpdate = mHidingNonSystemOverlayWindowsCountPerUid.size(); + // The visibility of SAWs needs to be refreshed when the number of uids that + // request hiding SAWs changes between "0", "1", or "2+". + changed = (numUIDsPostUpdate != numUIDsPreUpdate) + && (numUIDsPostUpdate <= 1 || numUIDsPreUpdate <= 1); } else { - if (systemAlertWindowsHidden == hideSystemAlertWindows) { - return; - } + // The visibility of SAWs needs to be refreshed when the number of windows that + // request hiding SAWs changes between "0" or "1+". + changed = (effective && mHidingNonSystemOverlayWindows.size() == 1) + || (!effective && mHidingNonSystemOverlayWindows.isEmpty()); + } + + if (changed) { + mRoot.forAllWindows((w) -> { + w.setForceHideNonSystemOverlayWindowIfNeeded(shouldHideNonSystemOverlayWindow(w)); + }, false /* traverseTopToBottom */); } - mRoot.forAllWindows((w) -> { - w.setForceHideNonSystemOverlayWindowIfNeeded(shouldHideNonSystemOverlayWindow(w)); - }, false /* traverseTopToBottom */); } /** Called from Accessibility Controller to apply magnification spec */ diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java index 73102c4478d8..5427dc22e700 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java @@ -1486,6 +1486,46 @@ public class WindowManagerServiceTests extends WindowTestsBase { } @Test + @EnableFlags(Flags.FLAG_FIX_HIDE_OVERLAY_API) + public void testUpdateOverlayWindows_multipleWindowsFromSameUid_idempotent() { + // Deny INTERNAL_SYSTEM_WINDOW permission for WindowSession so that the saw isn't allowed to + // show despite hideNonSystemOverlayWindows. + doReturn(PackageManager.PERMISSION_DENIED).when(mWm.mContext).checkPermission( + eq(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW), anyInt(), anyInt()); + + WindowState saw = + newWindowBuilder("saw", TYPE_APPLICATION_OVERLAY).setOwnerId(10123).build(); + saw.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN; + saw.mWinAnimator.mSurfaceControl = mock(SurfaceControl.class); + assertThat(saw.mSession.mCanAddInternalSystemWindow).isFalse(); + + WindowState app1 = newWindowBuilder("app1", TYPE_APPLICATION).setOwnerId(10456).build(); + spyOn(app1); + doReturn(true).when(app1).hideNonSystemOverlayWindowsWhenVisible(); + + WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).setOwnerId(10456).build(); + spyOn(app2); + doReturn(true).when(app2).hideNonSystemOverlayWindowsWhenVisible(); + + makeWindowVisible(saw, app1, app2); + assertThat(saw.isVisibleByPolicy()).isTrue(); + + // Two hideNonSystemOverlayWindows windows: SAW is hidden. + mWm.updateNonSystemOverlayWindowsVisibilityIfNeeded(app1, true); + mWm.updateNonSystemOverlayWindowsVisibilityIfNeeded(app2, true); + assertThat(saw.isVisibleByPolicy()).isFalse(); + + // Marking the same window hidden twice: SAW is still hidden. + mWm.updateNonSystemOverlayWindowsVisibilityIfNeeded(app1, false); + mWm.updateNonSystemOverlayWindowsVisibilityIfNeeded(app1, false); + assertThat(saw.isVisibleByPolicy()).isFalse(); + + // Marking the remaining window hidden: SAW can be shown again. + mWm.updateNonSystemOverlayWindowsVisibilityIfNeeded(app2, false); + assertThat(saw.isVisibleByPolicy()).isTrue(); + } + + @Test @EnableFlags(Flags.FLAG_REPARENT_WINDOW_TOKEN_API) public void reparentWindowContextToDisplayArea_newDisplay_reparented() { final WindowToken windowToken = createTestClientWindowToken(TYPE_NOTIFICATION_SHADE, |