Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b07f3fd9 authored by Robin Lee's avatar Robin Lee
Browse files

Simplify the "fixHideOverlay" flagging

- Completely separated the code

- Fixed a bug where calling for the same window with surfaceShown=false
  twice would cause it to be double-counted.

- Factored out an "effective" for readability

Test: atest 'WindowManagerServiceTests'
Fix: 402186473
Flag: com.android.window.flags.fix_hide_overlay_api
Change-Id: I14af1e8207e0aaacd63d7d160f2775310e8b922b
parent 310deb44
Loading
Loading
Loading
Loading
+30 −33
Original line number Diff line number Diff line
@@ -8835,49 +8835,46 @@ 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)) {

        if (effective) {
            mHidingNonSystemOverlayWindows.add(win);
                int uid = win.getOwningUid();
                int count = mHidingNonSystemOverlayWindowsCountPerUid.getOrDefault(uid, 0);
                mHidingNonSystemOverlayWindowsCountPerUid.put(uid, count + 1);
            }
        } 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 {
            if (systemAlertWindowsHidden == hideSystemAlertWindows) {
                return;
                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 {
            // 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 */);
        }
    }

    /** Called from Accessibility Controller to apply magnification spec */
    public void applyMagnificationSpecLocked(int displayId, MagnificationSpec spec) {
+40 −0
Original line number Diff line number Diff line
@@ -1485,6 +1485,46 @@ public class WindowManagerServiceTests extends WindowTestsBase {
        verify(overlayWindow).setForceHideNonSystemOverlayWindowIfNeeded(true);
    }

    @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() {