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

Commit e86da3bc authored by Chong Zhang's avatar Chong Zhang Committed by Android (Google) Code Review
Browse files

Merge "Clean up surfaces when app is resumed without being stopped." into nyc-mr1-dev

parents 1dcda854 45e6d2dc
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -173,7 +173,8 @@ interface IWindowManager
            in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
            int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
    void setAppVisibility(IBinder token, boolean visible);
    void notifyAppStopped(IBinder token, boolean stopped);
    void notifyAppResumed(IBinder token, boolean wasStopped);
    void notifyAppStopped(IBinder token);
    void startAppFreezingScreen(IBinder token, int configChanges);
    void stopAppFreezingScreen(IBinder token, boolean force);
    void removeAppToken(IBinder token);
+2 −2
Original line number Diff line number Diff line
@@ -1249,7 +1249,7 @@ final class ActivityStack {
            r.stopped = true;
            r.state = ActivityState.STOPPED;

            mWindowManager.notifyAppStopped(r.appToken, true);
            mWindowManager.notifyAppStopped(r.appToken);

            if (getVisibleBehindActivity() == r) {
                mStackSupervisor.requestVisibleBehindLocked(r, false);
@@ -2490,7 +2490,7 @@ final class ActivityStack {

                // Well the app will no longer be stopped.
                // Clear app token stopped state in window manager if needed.
                mWindowManager.notifyAppStopped(next.appToken, false);
                mWindowManager.notifyAppResumed(next.appToken, next.stopped);

                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                        System.identityHashCode(next), next.task.taskId, next.shortComponentName);
+46 −15
Original line number Diff line number Diff line
@@ -337,21 +337,41 @@ class AppWindowToken extends WindowToken {
        }
    }

    // Here we destroy surfaces which have been marked as eligible by the animator, taking care
    // to ensure the client has finished with them. If the client could still be using them
    // we will skip destruction and try again when the client has stopped.
    void destroySurfaces() {
        destroySurfaces(false /*cleanupOnResume*/);
    }

    /**
     * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
     * the client has finished with them.
     *
     * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
     * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
     * others so that they are ready to be reused. If set to false (common case), destroy all
     * surfaces that's eligible, if the app is already stopped.
     */

    private void destroySurfaces(boolean cleanupOnResume) {
        final ArrayList<WindowState> allWindows = (ArrayList<WindowState>) allAppWindows.clone();
        final DisplayContentList displayList = new DisplayContentList();
        for (int i = allWindows.size() - 1; i >= 0; i--) {
            final WindowState win = allWindows.get(i);

            if (!(mAppStopped || win.mWindowRemovalAllowed)) {
            if (!(mAppStopped || win.mWindowRemovalAllowed || cleanupOnResume)) {
                continue;
            }

            win.mWinAnimator.destroyPreservedSurfaceLocked();

            if (cleanupOnResume) {
                // If the window has an unfinished exit animation, consider that animation
                // done and mark the window destroying so that it goes through the cleanup.
                if (win.mAnimatingExit) {
                    win.mDestroying = true;
                    win.mAnimatingExit = false;
                }
            }

            if (!win.mDestroying) {
                continue;
            }
@@ -361,7 +381,9 @@ class AppWindowToken extends WindowToken {
                    + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
                    + " win.mRemoveOnExit=" + win.mRemoveOnExit);

            if (!cleanupOnResume || win.mRemoveOnExit) {
                win.destroyOrSaveSurface();
            }
            if (win.mRemoveOnExit) {
                service.removeWindowInnerLocked(win);
            }
@@ -379,19 +401,28 @@ class AppWindowToken extends WindowToken {
    }

    /**
     * If the application has stopped it is okay to destroy any surfaces which were keeping alive
     * in case they were still being used.
     * Notify that the app is now resumed, and it was not stopped before, perform a clean
     * up of the surfaces
     */
    void notifyAppStopped(boolean stopped) {
        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: stopped=" + stopped + " " + this);
        mAppStopped = stopped;
    void notifyAppResumed(boolean wasStopped) {
        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped + " " + this);
        mAppStopped = false;
        if (!wasStopped) {
            destroySurfaces(true /*cleanupOnResume*/);
        }
    }

        if (stopped) {
    /**
     * Notify that the app has stopped, and it is okay to destroy any surfaces which were
     * keeping alive in case they were still being used.
     */
    void notifyAppStopped() {
        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
        mAppStopped = true;
        destroySurfaces();
        // Remove any starting window that was added for this app if they are still around.
        mTask.mService.scheduleRemoveStartingWindowLocked(this);
    }
    }

    /**
     * Checks whether we should save surfaces for this app.
+21 −3
Original line number Diff line number Diff line
@@ -4476,7 +4476,25 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    @Override
    public void notifyAppStopped(IBinder token, boolean stopped) {
    public void notifyAppResumed(IBinder token, boolean wasStopped) {
        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                "notifyAppResumed()")) {
            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
        }

        synchronized(mWindowMap) {
            final AppWindowToken wtoken;
            wtoken = findAppWindowToken(token);
            if (wtoken == null) {
                Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + token);
                return;
            }
            wtoken.notifyAppResumed(wasStopped);
        }
    }

    @Override
    public void notifyAppStopped(IBinder token) {
        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                "notifyAppStopped()")) {
            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -4486,10 +4504,10 @@ public class WindowManagerService extends IWindowManager.Stub
            final AppWindowToken wtoken;
            wtoken = findAppWindowToken(token);
            if (wtoken == null) {
                Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
                Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: " + token);
                return;
            }
            wtoken.notifyAppStopped(stopped);
            wtoken.notifyAppStopped();
        }
    }

+6 −1
Original line number Diff line number Diff line
@@ -351,7 +351,12 @@ public class IWindowManagerImpl implements IWindowManager {
    }

    @Override
    public void notifyAppStopped(IBinder token, boolean stopped) throws RemoteException {
    public void notifyAppResumed(IBinder token, boolean wasStopped) throws RemoteException {
        // TODO Auto-generated method stub
    }

    @Override
    public void notifyAppStopped(IBinder token) throws RemoteException {
        // TODO Auto-generated method stub
    }