From 8d5a542f66beae774354038f15dd1afe7fcf754b Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Thu, 3 Mar 2016 18:28:21 -0800 Subject: [PATCH] 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 --- core/java/android/view/IWindowManager.aidl | 2 +- .../com/android/server/am/ActivityStack.java | 6 ++++- .../com/android/server/wm/AppWindowToken.java | 25 +++++++++++++------ .../server/wm/WindowManagerService.java | 6 +++-- .../src/android/view/IWindowManagerImpl.java | 2 +- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 9543acfba51be..804830101ffbe 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -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); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 74c836390a0bf..d1e1d27af1f69 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -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); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index ecfbc0a30256b..2731f42991a53 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -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,15 +377,19 @@ 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; - // Remove any starting window that was added for this app if they are still around. - mTask.mService.scheduleRemoveStartingWindowLocked(this); + if (stopped) { + destroySurfaces(); + // Remove any starting window that was added for this app if they are still around. + mTask.mService.scheduleRemoveStartingWindowLocked(this); + } } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 7c2a8e3385579..b64aaa89475a4 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -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); } diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index d2103c811d3eb..97195e4b32dac 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -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 }