From e42d0e102dbdf5287703389183a69019b64fc35e Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Mon, 2 May 2016 16:40:59 -0700 Subject: [PATCH] Don't remove all app token windows when window client dies AppWindowToken can contain windows from multiple clients (Processes) If one of the client dies we shouldn't remove all windows in the app token. We should only remove dea windows. Bug: 28467642 Change-Id: I8be6a98e0acc79719158567114f4902066069c1b --- .../com/android/server/wm/AppWindowToken.java | 22 +++++++++++++------ .../core/java/com/android/server/wm/Task.java | 6 ++--- .../server/wm/WindowManagerService.java | 18 +++++++-------- .../com/android/server/wm/WindowState.java | 10 +++------ 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index b4ead440405ec..805c986b1445f 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -109,7 +109,6 @@ class AppWindowToken extends WindowToken { // Set to true when the token has been removed from the window mgr. boolean removed; - boolean appDied; // Information about an application starting window if displayed. StartingData startingData; WindowState startingWindow; @@ -458,12 +457,12 @@ class AppWindowToken extends WindowToken { void removeAllDeadWindows() { for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; - // removeWindowLocked at bottom of loop may remove multiple entries from - // allAppWindows if the window to be removed has child windows. It also may - // not remove any windows from allAppWindows at all if win is exiting and - // currently animating away. This ensures that winNdx is monotonically decreasing - // and never beyond allAppWindows bounds. - winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) { + // removeWindowLocked at bottom of loop may remove multiple entries from + // allAppWindows if the window to be removed has child windows. It also may + // not remove any windows from allAppWindows at all if win is exiting and + // currently animating away. This ensures that winNdx is monotonically decreasing + // and never beyond allAppWindows bounds. + winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) { WindowState win = allAppWindows.get(winNdx); if (win.mAppDied) { if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) { @@ -476,6 +475,15 @@ class AppWindowToken extends WindowToken { } } + boolean hasWindowsAlive() { + for (int i = allAppWindows.size() - 1; i >= 0; i--) { + if (!allAppWindows.get(i).mAppDied) { + return true; + } + } + return false; + } + void setReplacingWindows(boolean animate) { if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken + " with replacing windows."); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 8d41dab431f7e..7ee26a048185a 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -125,9 +125,9 @@ class Task implements DimLayer.DimLayerUser { mHomeTask = homeTask; } - private boolean hasAppTokensAlive() { + private boolean hasWindowsAlive() { for (int i = mAppTokens.size() - 1; i >= 0; i--) { - if (!mAppTokens.get(i).appDied) { + if (mAppTokens.get(i).hasWindowsAlive()) { return true; } } @@ -135,7 +135,7 @@ class Task implements DimLayer.DimLayerUser { } void removeLocked() { - if (hasAppTokensAlive() && mStack.isAnimating()) { + if (hasWindowsAlive() && mStack.isAnimating()) { if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId); mDeferRemoval = true; return; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 57f551cff098f..8d93c35658692 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2000,11 +2000,6 @@ public class WindowManagerService extends IWindowManager.Stub return WindowManagerGlobal.ADD_INVALID_DISPLAY; } - if (atoken != null && atoken.appDied) { - Slog.d(TAG_WM, "App is now revived: " + atoken); - atoken.appDied = false; - } - mPolicy.adjustWindowParamsLw(win.mAttrs); win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs)); @@ -2260,6 +2255,10 @@ public class WindowManagerService extends IWindowManager.Stub } void removeWindowLocked(WindowState win) { + removeWindowLocked(win, false); + } + + void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) { win.mWindowRemovalAllowed = true; if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowLocked: " + win + " callers=" + Debug.getCallers(4)); @@ -2317,7 +2316,7 @@ public class WindowManagerService extends IWindowManager.Stub // If we are not currently running the exit animation, we need to see about starting one wasVisible = win.isWinVisibleLw(); - if (win.shouldKeepVisibleDeadAppWindow()) { + if (keepVisibleDeadWindow) { if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Not removing " + win + " because app died while it's visible"); @@ -4408,12 +4407,11 @@ public class WindowManagerService extends IWindowManager.Stub wtoken.waitingToShow = false; wtoken.hiddenRequested = !visible; - if (!visible && wtoken.appDied) { - // This app is dead while it was visible, we kept its dead window on screen. + if (!visible) { + // If the app is dead while it was visible, we kept its dead window on screen. // Now that the app is going invisible, we can remove it. It will be restarted // if made visible again. - wtoken.appDied = false; - wtoken.removeAllWindows(); + wtoken.removeAllDeadWindows(); } else if (visible) { if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) { // Add the app mOpeningApps if transition is unset but ready. This means diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index dd88bea0597bb..6a2a91dac1dde 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1740,10 +1740,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { WindowState win = mService.windowForClientLocked(mSession, mClient, false); Slog.i(TAG, "WIN DEATH: " + win); if (win != null) { - if (win.mAppToken != null && !win.mAppToken.clientHidden) { - win.mAppToken.appDied = true; - } - mService.removeWindowLocked(win); + mService.removeWindowLocked(win, shouldKeepVisibleDeadAppWindow()); if (win.mAttrs.type == TYPE_DOCK_DIVIDER) { // The owner of the docked divider died :( We reset the docked stack, // just in case they have the divider at an unstable position. Better @@ -1761,8 +1758,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } } catch (IllegalArgumentException ex) { - // This will happen if the window has already been - // removed. + // This will happen if the window has already been removed. } } } @@ -1773,7 +1769,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { * interacts with it. */ boolean shouldKeepVisibleDeadAppWindow() { - if (!isWinVisibleLw() || mAppToken == null || !mAppToken.appDied) { + if (!isWinVisibleLw() || mAppToken == null || mAppToken.clientHidden) { // Not a visible app window or the app isn't dead. return false; }