From a493c9a4286bf702af785d474c3f96080c4eb36b Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 10 Jun 2020 13:43:22 -0700 Subject: [PATCH] Ensure detached children aren't parented to new SurfaceControl The previous CL called preserveSurfaces when detachChildren were called to ensure a new SurfaceControl would get created. However, the check for when reparenting old children to the new surface was incorrect so children from the destroying surface would become children of the new surface. This was because mChildrenDetached was set to false when the new surface was created. The children were reparented after the new surface was created so mChildrenDetached would always be false. Instead, add a flag to the WindowSurfaceController when children are detached. This way we know which WindowSurfaceController has detached children and shouldn't reparent its children to the new surface. Test: Close and open apps with SV quickly. Child surfaces are cleaned up Fixes: 155694905 Bug: 157439199 Change-Id: I5f20f159bdc86c90e972400cd356df771d926fcc --- .../com/android/server/wm/WindowStateAnimator.java | 11 +++-------- .../android/server/wm/WindowSurfaceController.java | 4 ++++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index c0252363a159e..8115ac8c6bef5 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -247,10 +247,6 @@ class WindowStateAnimator { private final SurfaceControl.Transaction mPostDrawTransaction = new SurfaceControl.Transaction(); - // Used to track whether we have called detach children on the way to invisibility, in which - // case we need to give the client a new Surface if it lays back out to a visible state. - boolean mChildrenDetached = false; - // Set to true after the first frame of the Pinned stack animation // and reset after the last to ensure we only reset mForceScaleUntilResize // once per animation. @@ -425,7 +421,8 @@ class WindowStateAnimator { // transparent to the app. // If the children are detached, we don't want to reparent them to the new surface. // Instead let the children get removed when the old surface is deleted. - if (mSurfaceController != null && mPendingDestroySurface != null && !mChildrenDetached + if (mSurfaceController != null && mPendingDestroySurface != null + && !mPendingDestroySurface.mChildrenDetached && (mWin.mActivityRecord == null || !mWin.mActivityRecord.isRelaunching())) { mPostDrawTransaction.reparentChildren( mPendingDestroySurface.getClientViewRootSurface(), @@ -461,7 +458,6 @@ class WindowStateAnimator { if (mSurfaceController != null) { return mSurfaceController; } - mChildrenDetached = false; if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) { windowType = SurfaceControl.WINDOW_TYPE_DONT_SCREENSHOT; @@ -1365,7 +1361,7 @@ class WindowStateAnimator { mPostDrawTransaction.reparent(pendingSurfaceControl, null); // If the children are detached, we don't want to reparent them to the new surface. // Instead let the children get removed when the old surface is deleted. - if (!mChildrenDetached) { + if (!mPendingDestroySurface.mChildrenDetached) { mPostDrawTransaction.reparentChildren( mPendingDestroySurface.getClientViewRootSurface(), mSurfaceController.mSurfaceControl); @@ -1596,7 +1592,6 @@ class WindowStateAnimator { if (mSurfaceController != null) { mSurfaceController.detachChildren(); } - mChildrenDetached = true; // If the children are detached, it means the app is exiting. We don't want to tear the // content down too early, otherwise we could end up with a flicker. By preserving the // current surface, we ensure the content remains on screen until the window is completely diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 0a7ca5a0cf351..b2bfcdc8a9003 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -90,6 +90,9 @@ class WindowSurfaceController { private final SurfaceControl.Transaction mTmpTransaction; + // Used to track whether we have called detach children on the way to invisibility. + boolean mChildrenDetached; + WindowSurfaceController(String name, int w, int h, int format, int flags, WindowStateAnimator animator, int windowType, int ownerUid) { mAnimator = animator; @@ -144,6 +147,7 @@ class WindowSurfaceController { void detachChildren() { ProtoLog.i(WM_SHOW_TRANSACTIONS, "SEVER CHILDREN"); + mChildrenDetached = true; if (mSurfaceControl != null) { mSurfaceControl.detachChildren(); }