From 29daa92be91d0a756f2486d49cadefee24f24467 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Fri, 27 Apr 2018 11:56:48 -0700 Subject: [PATCH] Detach children when stopping app. Prior to the implementation of detachChildren we handled this case via the "mWindowStopped" codepath in SurfaceView.java which this CL deletes. That codepath however causes confusion due to it's failure to set null the SurfaceControl, meaning we may not necessarily recreate it when resuming if we didn't hit any other code-path to do such as happens in linked bug 78588930. Anyway it seems clearest to handle all these preserve-child-surfaces-on-tear-down cases via one mechanism (detachChildren). Bug: 78588930 Test: Manual. Change-Id: Iac7c0bc0c6b4da0d405bdc2b57d13d5c881611b0 --- core/java/android/view/SurfaceView.java | 12 +++--------- .../java/com/android/server/am/ActivityRecord.java | 4 ++++ .../server/wm/AppWindowContainerController.java | 11 +++++++++++ .../java/com/android/server/wm/AppWindowToken.java | 8 ++++++-- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 7e5464761e38c..db34856e0ad6c 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -700,15 +700,9 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mIsCreating = false; if (mSurfaceControl != null && !mSurfaceCreated) { mSurface.release(); - // If we are not in the stopped state, then the destruction of the Surface - // represents a visual change we need to display, and we should go ahead - // and destroy the SurfaceControl. However if we are in the stopped state, - // we can just leave the Surface around so it can be a part of animations, - // and we let the life-time be tied to the parent surface. - if (!mWindowStopped) { - mSurfaceControl.destroy(); - mSurfaceControl = null; - } + + mSurfaceControl.destroy(); + mSurfaceControl = null; } } } catch (Exception ex) { diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 16c5969a91678..e73f42fa42645 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -1626,6 +1626,10 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo if (parent != null) { parent.onActivityStateChanged(this, state, reason); } + + if (state == STOPPING) { + mWindowContainerController.notifyAppStopping(); + } } ActivityState getState() { diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index 165a409028d66..644e3c3c732b5 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -671,6 +671,17 @@ public class AppWindowContainerController } } + public void notifyAppStopping() { + synchronized(mWindowMap) { + if (mContainer == null) { + Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: " + + mToken); + return; + } + mContainer.detachChildren(); + } + } + public void notifyAppStopped() { synchronized(mWindowMap) { if (mContainer == null) { diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index a701d42986e34..1d581d4702f77 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -913,12 +913,16 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // try and clean up it's child surfaces. We need to prevent this from // happening, so we sever the children, transfering their ownership // from the client it-self to the parent surface (owned by us). + detachChildren(); + + mPendingRelaunchCount++; + } + + void detachChildren() { for (int i = mChildren.size() - 1; i >= 0; i--) { final WindowState w = mChildren.get(i); w.mWinAnimator.detachChildren(); } - - mPendingRelaunchCount++; } void finishRelaunching() {