From 7b3d11dce3a4039a8726b0a91a4069a79dd30f08 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Thu, 15 Mar 2018 14:34:45 -0700 Subject: [PATCH] Ensure Surface is recreated if children are detached. If we detach the children of a Surface, then they are stuck around indefinitely and we can't use the Surface as the result of a future call to lay-out visible. This should also improve Surface lifetime-errors as now in the case of cancelling an exit animation we will fall in to this preserve surface codepath instead of the destroySurfaceUnchecked block in WindowStateAnimator#cancelExitAnimationForNextAnimationLocked. Bug: 68996752 Bug: 62536731 Bug: 72921025 Bug: 72873272 Change-Id: Ib0be6e7447c04d00bff8784d8b8072918d48e0ba --- .../core/java/com/android/server/wm/WindowState.java | 9 +++++++++ .../java/com/android/server/wm/WindowStateAnimator.java | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 68bb530fdf256..97d00bea27f20 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4297,6 +4297,15 @@ class WindowState extends WindowContainer implements WindowManagerP final boolean wasVisible = isVisibleLw(); result |= (!wasVisible || !isDrawnLw()) ? RELAYOUT_RES_FIRST_TIME : 0; + + if (mWinAnimator.mChildrenDetached) { + // If there are detached children hanging around we need to force + // the client receiving a new Surface. + mWinAnimator.preserveSurfaceLocked(); + result |= RELAYOUT_RES_SURFACE_CHANGED + | RELAYOUT_RES_FIRST_TIME; + } + if (mAnimatingExit) { Slog.d(TAG, "relayoutVisibleWindow: " + this + " mAnimatingExit=true, mRemoveOnExit=" + mRemoveOnExit + ", mDestroying=" + mDestroying); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 13f05e088cb1e..29beb58b334e6 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -221,6 +221,10 @@ class WindowStateAnimator { private final SurfaceControl.Transaction mReparentTransaction = 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; + WindowStateAnimator(final WindowState win) { final WindowManagerService service = win.mService; @@ -430,6 +434,7 @@ 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; @@ -1479,6 +1484,7 @@ class WindowStateAnimator { if (mSurfaceController != null) { mSurfaceController.detachChildren(); } + mChildrenDetached = true; } int getLayer() {