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

Commit 8d5a542f authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Clear app token mAppStopped when app resumes.

It is possible for an activity to be in the stopped state without
setting it's visiblility to false in window manager.
For example, the home acitivty behind the lock screen. Since the
lock screen isn't an activity it doesn't affect the visiblity set
of the home activity, so AM doesn't tell WM to hide the app token.
However, AM uses another channel to detect that the device is locked
and moves the activity into stopped state. WM on the other hand also
detects that the device is locked and hides the window surfaces of
all windows behind the lock screen. So, at this point AM has also
told WM that the activity is stopped. Once you unlock the screen
AM resumes the activity but doesn't report any visiblility changes to WM
since it's internal state didn't change. So, if you go from the home
activity to another app the home activity window will be destroyed
before the activity is stopped because mAppStopped is set to true.
We now set mAppStopped to false when the activity is resumed.

Bug: 27286867
Change-Id: Ic75456d30abd582fa44f932f5aeeb449950157ee
parent 6d6bbf5f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ 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);
    void notifyAppStopped(IBinder token, boolean stopped);
    void startAppFreezingScreen(IBinder token, int configChanges);
    void stopAppFreezingScreen(IBinder token, boolean force);
    void removeAppToken(IBinder token);
+5 −1
Original line number Diff line number Diff line
@@ -1115,7 +1115,7 @@ final class ActivityStack {
            r.stopped = true;
            r.state = ActivityState.STOPPED;

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

            if (getVisibleBehindActivity() == r) {
                mStackSupervisor.requestVisibleBehindLocked(r, false);
@@ -2247,6 +2247,10 @@ final class ActivityStack {
                    next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
                }

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

                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                        System.identityHashCode(next), next.task.taskId, next.shortComponentName);

+17 −8
Original line number Diff line number Diff line
@@ -354,6 +354,11 @@ class AppWindowToken extends WindowToken {
                continue;
            }

            if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + win
                    + " destroySurfaces: mAppStopped=" + mAppStopped
                    + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
                    + " win.mRemoveOnExit=" + win.mRemoveOnExit);

            win.destroyOrSaveSurface();
            if (win.mRemoveOnExit) {
                win.mAnimatingExit = false;
@@ -372,16 +377,20 @@ class AppWindowToken extends WindowToken {
        }
    }

    // The application has stopped, so 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();
    /**
     * If the application has stopped it is okay to destroy any surfaces which were keeping alive
     * in case they were still being used.
     */
    void notifyAppStopped(boolean stopped) {
        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: stopped=" + stopped + " " + this);
        mAppStopped = stopped;

        if (stopped) {
            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.
+4 −2
Original line number Diff line number Diff line
@@ -4197,7 +4197,7 @@ public class WindowManagerService extends IWindowManager.Stub
    }

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

@@ -4247,6 +4247,8 @@ public class WindowManagerService extends IWindowManager.Stub
                wtoken.appDied = false;
                wtoken.removeAllWindows();
            } else if (visible) {
                if (DEBUG_ADD_REMOVE) Slog.v(
                        TAG_WM, "No longer Stopped: " + wtoken);
                wtoken.mAppStopped = false;
                wtoken.setWindowsExiting(false);
            }
+1 −1
Original line number Diff line number Diff line
@@ -349,7 +349,7 @@ public class IWindowManagerImpl implements IWindowManager {
    }

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