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

Commit bad132df authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Adjust process state for visible overlay window

This avoids process with system permission from being frozen by
CachedAppOptimizer if it only shows an overlay window without an
active application component (e.g. a running service).

Otherwise the window could meet ANR because its process is unable
to response for input events.

Assume:
A=add mAppOverlaySurfaces
B=add mAlertWindowSurfaces
C=log metrics
D=show notification
E=setHasOverlayUi (adjust process state)

app-overlay=TYPE_APPLICATION_OVERLAY
other-overlay=TYPE_[*PHONE|SYSTEM_ALERT|SYSTEM_ERROR|SYSTEM_OVERLAY]

Before:
- Window owner has system permission
   add other-overlay: do nothing
   add app-overlay: A+C+E
- Window owner doesn't have system permission
   add other-overlay: B+C+D
   add app-overlay: A+B+C+D+E

After:
- Window owner has system permission
   add other-overlay: B+E
   add app-overlay: B+C+E
- Window owner doesn't have system permission
   add other-overlay: B+C+D+E
   add app-overlay: B+C+D+E

The mAppOverlaySurfaces is removed because there is no need to
distinguish the overlay type for checking whether a process contains
an overlay window.

Bug: 290870920
Test: WindowManagerServiceTests#testTrackOverlayWindow
Change-Id: I7618d853ea6e7a7261a72b9f4883d9642d426450
parent a9d2c1f1
Loading
Loading
Loading
Loading
+36 −40
Original line number Diff line number Diff line
@@ -109,9 +109,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    private final String mStringName;
    SurfaceSession mSurfaceSession;
    private final ArrayList<WindowState> mAddedWindows = new ArrayList<>();
    // Set of visible application overlay window surfaces connected to this session.
    private final ArraySet<WindowSurfaceController> mAppOverlaySurfaces = new ArraySet<>();
    // Set of visible alert window surfaces connected to this session.
    /** Set of visible alert/app-overlay window surfaces connected to this session. */
    private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>();
    private final DragDropController mDragDropController;
    final boolean mCanAddInternalSystemWindow;
@@ -795,19 +793,31 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
        }

        boolean changed;

        if (!mCanAddInternalSystemWindow && !mCanCreateSystemApplicationOverlay) {
            // We want to track non-system apps adding alert windows so we can post an
            // on-going notification for the user to control their visibility.
        // Track non-system apps adding overlay/alert windows, so a notification can post for the
        // user to control their visibility.
        final boolean noSystemOverlayPermission =
                !mCanAddInternalSystemWindow && !mCanCreateSystemApplicationOverlay;
        if (visible) {
            changed = mAlertWindowSurfaces.add(surfaceController);
                MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, true);
            if (type == TYPE_APPLICATION_OVERLAY) {
                MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type,
                        false /* set false to only log for TYPE_APPLICATION_OVERLAY */);
            } else if (noSystemOverlayPermission) {
                MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type,
                        true /* only log for non-TYPE_APPLICATION_OVERLAY */);
            }
        } else {
            changed = mAlertWindowSurfaces.remove(surfaceController);
                MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, true);
            if (type == TYPE_APPLICATION_OVERLAY) {
                MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type,
                        false /* set false to only log for TYPE_APPLICATION_OVERLAY */);
            } else if (noSystemOverlayPermission) {
                MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type,
                        true /* only log for non-TYPE_APPLICATION_OVERLAY */);
            }
        }

            if (changed) {
        if (changed && noSystemOverlayPermission) {
            if (mAlertWindowSurfaces.isEmpty()) {
                cancelAlertWindowNotification();
            } else if (mAlertWindowNotification == null) {
@@ -817,24 +827,11 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
                }
            }
        }
        }

        if (type != TYPE_APPLICATION_OVERLAY) {
            return;
        }

        if (visible) {
            changed = mAppOverlaySurfaces.add(surfaceController);
            MetricsLoggerWrapper.logAppOverlayEnter(mUid, mPackageName, changed, type, false);
        } else {
            changed = mAppOverlaySurfaces.remove(surfaceController);
            MetricsLoggerWrapper.logAppOverlayExit(mUid, mPackageName, changed, type, false);
        }

        if (changed) {
            // Notify activity manager of changes to app overlay windows so it can adjust the
            // importance score for the process.
            setHasOverlayUi(!mAppOverlaySurfaces.isEmpty());
        if (changed && mPid != WindowManagerService.MY_PID) {
            // Notify activity manager that the process contains overlay/alert windows, so it can
            // adjust the importance score for the process.
            setHasOverlayUi(!mAlertWindowSurfaces.isEmpty());
        }
    }

@@ -869,12 +866,12 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
        mSurfaceSession = null;
        mAddedWindows.clear();
        mAlertWindowSurfaces.clear();
        mAppOverlaySurfaces.clear();
        setHasOverlayUi(false);
        cancelAlertWindowNotification();
    }

    private void setHasOverlayUi(boolean hasOverlayUi) {
    @VisibleForTesting
    void setHasOverlayUi(boolean hasOverlayUi) {
        mService.mH.obtainMessage(H.SET_HAS_OVERLAY_UI, mPid, hasOverlayUi ? 1 : 0).sendToTarget();
    }

@@ -889,7 +886,6 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.print("numWindow="); pw.print(mAddedWindows.size());
                pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow);
                pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces);
                pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces);
                pw.print(" mClientDead="); pw.print(mClientDead);
                pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
+16 −0
Original line number Diff line number Diff line
@@ -238,6 +238,22 @@ public class WindowManagerServiceTests extends WindowTestsBase {
        verify(mWm.mAtmService.mTaskSupervisor).wakeUp(anyString());
    }

    @Test
    public void testTrackOverlayWindow() {
        final WindowProcessController wpc = mSystemServicesTestRule.addProcess(
                "pkgName", "processName", 1000 /* pid */, Process.SYSTEM_UID);
        final Session session = createTestSession(mAtm, wpc.getPid(), wpc.mUid);
        spyOn(session);
        assertTrue(session.mCanAddInternalSystemWindow);
        final WindowSurfaceController winSurface = mock(WindowSurfaceController.class);
        session.onWindowSurfaceVisibilityChanged(winSurface, true /* visible */,
                LayoutParams.TYPE_PHONE);
        verify(session).setHasOverlayUi(true);
        session.onWindowSurfaceVisibilityChanged(winSurface, false /* visible */,
                LayoutParams.TYPE_PHONE);
        verify(session).setHasOverlayUi(false);
    }

    @Test
    public void testRelayoutExitingWindow() {
        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "appWin");