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

Commit becc0610 authored by Yi Jiang's avatar Yi Jiang Committed by Android (Google) Code Review
Browse files

Merge "Update WindowManagerService#setHideOverlayWindows" into main

parents 9e25efbe 694a181b
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -106,3 +106,15 @@ flag {
    is_exported: true
    bug: "293949943"
}

flag {
    namespace: "window_surfaces"
    name: "fix_hide_overlay_api"
    description: "Application that calls setHideOverlayWindows() shouldn't hide its own windows, this flag gate the fix of this issue."
    is_fixed_read_only: true
    is_exported: true
    bug: "359424300"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+52 −9
Original line number Diff line number Diff line
@@ -326,7 +326,6 @@ import android.window.WindowContainerToken;
import android.window.WindowContextInfo;

import com.android.internal.R;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
@@ -343,6 +342,7 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.LatencyTracker;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.view.WindowManagerPolicyThread;
import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
@@ -388,7 +388,6 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
@@ -672,6 +671,14 @@ public class WindowManagerService extends IWindowManager.Stub
    /** List of window currently causing non-system overlay windows to be hidden. */
    private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();

    /**
     * A map that tracks uid/count of windows that cause non-system overlay windows to be hidden.
     * The key is the window's uid and the value is the number of windows with that uid that are
     * requesting hiding non-system overlay
     */
    private final ArrayMap<Integer, Integer> mHidingNonSystemOverlayWindowsCountPerUid =
            new ArrayMap<>();

    /**
     * In some cases (e.g. when {@link R.bool.config_reverseDefaultRotation} has value
     * {@value true}) we need to map some orientation to others. This {@link SparseIntArray}
@@ -1808,7 +1815,7 @@ public class WindowManagerService extends IWindowManager.Stub
                    UserHandle.getUserId(win.getOwningUid()));
            win.setHiddenWhileSuspended(suspended);

            final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
            final boolean hideSystemAlertWindows = shouldHideNonSystemOverlayWindow(win);
            win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);

            boolean imMayMove = true;
@@ -2032,6 +2039,22 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    private boolean shouldHideNonSystemOverlayWindow(WindowState win) {
        if (!Flags.fixHideOverlayApi()) {
            return !mHidingNonSystemOverlayWindows.isEmpty();
        }

        if (mHidingNonSystemOverlayWindows.isEmpty()) {
            return false;
        }

        if (mHidingNonSystemOverlayWindowsCountPerUid.size() == 1
                && mHidingNonSystemOverlayWindowsCountPerUid.containsKey(win.getOwningUid())) {
            return false;
        }
        return true;
    }

    /**
     * Set whether screen capture is disabled for all windows of a specific user from
     * the device policy cache, or specific windows based on sensitive content protections.
@@ -8733,22 +8756,42 @@ public class WindowManagerService extends IWindowManager.Stub
            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);
            }
        } 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();
        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;
            }
        } else {
            if (systemAlertWindowsHidden == hideSystemAlertWindows) {
                return;
            }

        }
        mRoot.forAllWindows((w) -> {
            w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
            w.setForceHideNonSystemOverlayWindowIfNeeded(shouldHideNonSystemOverlayWindow(w));
        }, false /* traverseTopToBottom */);
    }

+47 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
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_INPUT_METHOD_DIALOG;
@@ -1470,6 +1471,52 @@ public class WindowManagerServiceTests extends WindowTestsBase {
                eq(windowToken.token));
    }

    @Test
    @EnableFlags(Flags.FLAG_FIX_HIDE_OVERLAY_API)
    public void testUpdateOverlayWindows_singleWindowRequestsHiding_doNotHideOverlayWithSameUid() {
        WindowState overlayWindow = newWindowBuilder("overlay_window",
                TYPE_APPLICATION_OVERLAY).build();
        WindowState appWindow = newWindowBuilder("app_window", TYPE_APPLICATION).build();
        makeWindowVisible(appWindow, overlayWindow);

        int uid = 100000;
        spyOn(appWindow);
        spyOn(overlayWindow);
        doReturn(true).when(appWindow).hideNonSystemOverlayWindowsWhenVisible();
        doReturn(uid).when(appWindow).getOwningUid();
        doReturn(uid).when(overlayWindow).getOwningUid();

        mWm.updateNonSystemOverlayWindowsVisibilityIfNeeded(appWindow, true);

        verify(overlayWindow).setForceHideNonSystemOverlayWindowIfNeeded(false);
    }

    @Test
    @EnableFlags(Flags.FLAG_FIX_HIDE_OVERLAY_API)
    public void testUpdateOverlayWindows_multipleWindowsRequestHiding_hideOverlaysWithAnyUids() {
        WindowState overlayWindow = newWindowBuilder("overlay_window",
                TYPE_APPLICATION_OVERLAY).build();
        WindowState appWindow1 = newWindowBuilder("app_window_1", TYPE_APPLICATION).build();
        WindowState appWindow2 = newWindowBuilder("app_window_2", TYPE_APPLICATION).build();
        makeWindowVisible(appWindow1, appWindow2, overlayWindow);

        int uid1 = 100000;
        int uid2 = 100001;
        spyOn(appWindow1);
        spyOn(appWindow2);
        spyOn(overlayWindow);
        doReturn(true).when(appWindow1).hideNonSystemOverlayWindowsWhenVisible();
        doReturn(true).when(appWindow2).hideNonSystemOverlayWindowsWhenVisible();
        doReturn(uid1).when(appWindow1).getOwningUid();
        doReturn(uid1).when(overlayWindow).getOwningUid();
        doReturn(uid2).when(appWindow2).getOwningUid();

        mWm.updateNonSystemOverlayWindowsVisibilityIfNeeded(appWindow1, true);
        mWm.updateNonSystemOverlayWindowsVisibilityIfNeeded(appWindow2, true);

        verify(overlayWindow).setForceHideNonSystemOverlayWindowIfNeeded(true);
    }

    @Test
    @EnableFlags(Flags.FLAG_REPARENT_WINDOW_TOKEN_API)
    public void reparentWindowContextToDisplayArea_newDisplay_reparented() {