From 5057590fe969316ebfef5f5cae40a4b524a06a55 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Tue, 10 Apr 2018 17:49:30 +0200 Subject: Fix issue with leaked preserved surface Imagine a non-app-window going through the following sequence: 1. Window starts out visible 2. Client sets to GONE 3. Exit animation starts. 4. Client sets to VISIBLE 5. Before it can redraw, Client sets to GONE again In that case we preserve the surface because we need to client to force-retrieve a new surface. However, we never mark the surface as to be destroyed because we never enter the path in WSA.prepareSurfaceLocked that would mark the preserved surface to be destroyed, which is only the case when the client redraws. Fix this by also marking it as to be destroyed when the surface gets hidden. Test: Above flow. See bug for test app. Change-Id: Ic554ae787e7d2130b93b993fadf8c302913ed6ee Fixes: 77633603 --- services/core/java/com/android/server/wm/WindowState.java | 9 ++++----- .../core/java/com/android/server/wm/WindowStateAnimator.java | 6 ++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c5269e172f2a..f0c03b750eda 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4101,11 +4101,10 @@ class WindowState extends WindowContainer implements WindowManagerP mDestroying = true; final boolean hasSurface = mWinAnimator.hasSurface(); - if (hasSurface) { - // Use pendingTransaction here so hide is done the same transaction as the other - // animations when exiting - mWinAnimator.hide(getPendingTransaction(), "onExitAnimationDone"); - } + + // Use pendingTransaction here so hide is done the same transaction as the other + // animations when exiting + mWinAnimator.hide(getPendingTransaction(), "onExitAnimationDone"); // If we have an app token, we ask it to destroy the surface for us, so that it can take // care to ensure the activity has actually stopped and the surface is not still in use. diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index e92d460f2ec6..ed706944ae5a 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -301,6 +301,12 @@ class WindowStateAnimator { if (!mLastHidden) { //dump(); mLastHidden = true; + + // We may have a preserved surface which we no longer need. If there was a quick + // VISIBLE, GONE, VISIBLE, GONE sequence, the surface may never draw, so we don't mark + // it to be destroyed in prepareSurfaceLocked. + markPreservedSurfaceForDestroy(); + if (mSurfaceController != null) { mSurfaceController.hide(transaction, reason); } -- cgit v1.2.3-59-g8ed1b