Loading core/java/android/view/IWindowManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,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 startAppFreezingScreen(IBinder token, int configChanges); void stopAppFreezingScreen(IBinder token, boolean force); void removeAppToken(IBinder token); Loading services/core/java/com/android/server/am/ActivityStack.java +3 −0 Original line number Diff line number Diff line Loading @@ -1097,6 +1097,9 @@ final class ActivityStack { mHandler.removeMessages(STOP_TIMEOUT_MSG, r); r.stopped = true; r.state = ActivityState.STOPPED; mWindowManager.notifyAppStopped(r.appToken); if (getVisibleBehindActivity() == r) { mStackSupervisor.requestVisibleBehindLocked(r, false); } Loading services/core/java/com/android/server/wm/AppWindowToken.java +43 −0 Original line number Diff line number Diff line Loading @@ -127,6 +127,8 @@ class AppWindowToken extends WindowToken { boolean mAlwaysFocusable; boolean mAppStopped; ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); AppWindowToken(WindowManagerService _service, IApplicationToken _token, Loading Loading @@ -311,6 +313,47 @@ 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() { 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 (!win.mDestroying) { continue; } if (!mAppStopped && !win.mClientRemoveRequested) { return; } win.destroyOrSaveSurface(); if (win.mRemoveOnExit) { win.mExiting = false; service.removeWindowInnerLocked(win); } final DisplayContent displayContent = win.getDisplayContent(); if (displayContent != null && !displayList.contains(displayContent)) { displayList.add(displayContent); } win.mDestroying = false; } for (int i = 0; i < displayList.size(); i++) { final DisplayContent displayContent = displayList.get(i); service.mLayersController.assignLayersLocked(displayContent.getWindowList()); displayContent.layoutNeeded = true; } } // The application has stopped, so destroy any surfaces which were keeping alive // in case they were still being used. void notifyAppStopped() { mAppStopped = true; destroySurfaces(); } /** * Checks whether we should save surfaces for this app. * Loading services/core/java/com/android/server/wm/WindowManagerService.java +27 −0 Original line number Diff line number Diff line Loading @@ -2154,6 +2154,14 @@ public class WindowManagerService extends IWindowManager.Stub if (win == null) { return; } // We set this here instead of removeWindowLocked because we only want it to be // true when the client has requested we remove the window. In other remove // cases, we have to wait for activity stop to safely remove the window (as the // client may still be using the surface). In this case though, the client has // just dismissed a window (for example a Dialog) and activity stop isn't // necessarily imminent, so we need to know not to wait for it after our // hanimation (if applicable) finishes. win.mClientRemoveRequested = true; removeWindowLocked(win); } } Loading Loading @@ -4187,6 +4195,24 @@ public class WindowManagerService extends IWindowManager.Stub } } @Override public void notifyAppStopped(IBinder token) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "notifyAppStopped()")) { 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 set visibility of non-existing app token: " + token); return; } wtoken.notifyAppStopped(); } } @Override public void setAppVisibility(IBinder token, boolean visible) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, Loading @@ -4210,6 +4236,7 @@ public class WindowManagerService extends IWindowManager.Stub mOpeningApps.remove(wtoken); mClosingApps.remove(wtoken); wtoken.mAppStopped = false; wtoken.waitingToShow = false; wtoken.hiddenRequested = !visible; Loading services/core/java/com/android/server/wm/WindowState.java +7 −0 Original line number Diff line number Diff line Loading @@ -385,6 +385,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { /** Is this window now (or just being) removed? */ boolean mRemoved; /** * Has the client requested we remove the window? In this case we know * that we can dispose of it when we wish without further synchronization * with the client */ boolean mClientRemoveRequested; /** * Temp for keeping track of windows that have been removed when * rebuilding window list. Loading Loading
core/java/android/view/IWindowManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,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 startAppFreezingScreen(IBinder token, int configChanges); void stopAppFreezingScreen(IBinder token, boolean force); void removeAppToken(IBinder token); Loading
services/core/java/com/android/server/am/ActivityStack.java +3 −0 Original line number Diff line number Diff line Loading @@ -1097,6 +1097,9 @@ final class ActivityStack { mHandler.removeMessages(STOP_TIMEOUT_MSG, r); r.stopped = true; r.state = ActivityState.STOPPED; mWindowManager.notifyAppStopped(r.appToken); if (getVisibleBehindActivity() == r) { mStackSupervisor.requestVisibleBehindLocked(r, false); } Loading
services/core/java/com/android/server/wm/AppWindowToken.java +43 −0 Original line number Diff line number Diff line Loading @@ -127,6 +127,8 @@ class AppWindowToken extends WindowToken { boolean mAlwaysFocusable; boolean mAppStopped; ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); AppWindowToken(WindowManagerService _service, IApplicationToken _token, Loading Loading @@ -311,6 +313,47 @@ 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() { 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 (!win.mDestroying) { continue; } if (!mAppStopped && !win.mClientRemoveRequested) { return; } win.destroyOrSaveSurface(); if (win.mRemoveOnExit) { win.mExiting = false; service.removeWindowInnerLocked(win); } final DisplayContent displayContent = win.getDisplayContent(); if (displayContent != null && !displayList.contains(displayContent)) { displayList.add(displayContent); } win.mDestroying = false; } for (int i = 0; i < displayList.size(); i++) { final DisplayContent displayContent = displayList.get(i); service.mLayersController.assignLayersLocked(displayContent.getWindowList()); displayContent.layoutNeeded = true; } } // The application has stopped, so destroy any surfaces which were keeping alive // in case they were still being used. void notifyAppStopped() { mAppStopped = true; destroySurfaces(); } /** * Checks whether we should save surfaces for this app. * Loading
services/core/java/com/android/server/wm/WindowManagerService.java +27 −0 Original line number Diff line number Diff line Loading @@ -2154,6 +2154,14 @@ public class WindowManagerService extends IWindowManager.Stub if (win == null) { return; } // We set this here instead of removeWindowLocked because we only want it to be // true when the client has requested we remove the window. In other remove // cases, we have to wait for activity stop to safely remove the window (as the // client may still be using the surface). In this case though, the client has // just dismissed a window (for example a Dialog) and activity stop isn't // necessarily imminent, so we need to know not to wait for it after our // hanimation (if applicable) finishes. win.mClientRemoveRequested = true; removeWindowLocked(win); } } Loading Loading @@ -4187,6 +4195,24 @@ public class WindowManagerService extends IWindowManager.Stub } } @Override public void notifyAppStopped(IBinder token) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "notifyAppStopped()")) { 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 set visibility of non-existing app token: " + token); return; } wtoken.notifyAppStopped(); } } @Override public void setAppVisibility(IBinder token, boolean visible) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, Loading @@ -4210,6 +4236,7 @@ public class WindowManagerService extends IWindowManager.Stub mOpeningApps.remove(wtoken); mClosingApps.remove(wtoken); wtoken.mAppStopped = false; wtoken.waitingToShow = false; wtoken.hiddenRequested = !visible; Loading
services/core/java/com/android/server/wm/WindowState.java +7 −0 Original line number Diff line number Diff line Loading @@ -385,6 +385,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { /** Is this window now (or just being) removed? */ boolean mRemoved; /** * Has the client requested we remove the window? In this case we know * that we can dispose of it when we wish without further synchronization * with the client */ boolean mClientRemoveRequested; /** * Temp for keeping track of windows that have been removed when * rebuilding window list. Loading