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

Commit b76adc51 authored by Chong Zhang's avatar Chong Zhang Committed by android-build-merger
Browse files

Clean up surfaces when app is resumed without being stopped.

am: 45e6d2dc

Change-Id: I9ae5c2a9c6a93246338221252cf943db6763e1c4
parents a0450f65 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
    }