From 46831fa9ffe3a8c240a9415efc1b192268d98cf1 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Fri, 12 Aug 2016 13:50:38 -0700 Subject: [PATCH] Copy exiting app token list while stepping animation. Stepping the animation can lead to WindowStateAnimator#finishExit, which can lead to WindowManagerService#removeWindowInnerLocked, which can immediately call WindowSurfacePlacer.performSurfacePlacement. From here we will directly modify mExitingAppTokens for each stack and remove tokens where exiting is complete. I think removeWindowInnerLocked making a direct call to performSurfacePlacement is questionable...but changing semantics there is very risky. For now, simply avoid processing tokens in the animator if the surface placer has removed them. It seems all we would want to do is trigger a layout pass, which has just occured anyway. Bug: 30813094 Change-Id: Iaff77d227e09839f7e6edda6b8f188d164e6da74 --- .../com/android/server/wm/WindowAnimator.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index e5eda0522f929..b0d357c6320c8 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -119,6 +119,8 @@ public class WindowAnimator { // check if some got replaced and can be removed. private boolean mRemoveReplacedWindows = false; + private final AppTokenList mTmpExitingAppTokens = new AppTokenList(); + private String forceHidingToString() { switch (mForceHiding) { case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN"; @@ -189,10 +191,19 @@ public class WindowAnimator { } } - final AppTokenList exitingAppTokens = stack.mExitingAppTokens; - final int exitingCount = exitingAppTokens.size(); + mTmpExitingAppTokens.clear(); + mTmpExitingAppTokens.addAll(stack.mExitingAppTokens); + + final int exitingCount = mTmpExitingAppTokens.size(); for (int i = 0; i < exitingCount; i++) { - final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator; + final AppWindowAnimator appAnimator = mTmpExitingAppTokens.get(i).mAppAnimator; + // stepAnimation can trigger finishExit->removeWindowInnerLocked + // ->performSurfacePlacement + // performSurfacePlacement will directly manipulate the mExitingAppTokens list + // so we need to iterate over a copy and check for modifications. + if (!stack.mExitingAppTokens.contains(appAnimator)) { + continue; + } appAnimator.wasAnimating = appAnimator.animating; if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) { setAnimating(true);