From e05bcb15d5944dee38e21fe64315ebf6673e69c7 Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Tue, 26 Jul 2016 17:47:29 -0700 Subject: [PATCH] Cleanup mAnimatingExit flag before maybeUpdateTransitToWallpaper() If we get onStopped before next resume, but previous exit animation doesn't finish by the time the entering animation is started, notifyAppResumed() won't do a surface cleanup (since it's already stopped). Then maybeUpdateTransitToWallpaper() will think the wallpaper target (launcher) is invisible because of the mAnimatingExit==true, thus fails to pick WALLPAPER_OPEN animation. We need to clear mAnimatingExit and relevant flags before maybeUpdateTransitToWallpaper(). Currently we do it in handleOpeningApps but that's too late. bug: 30255354 Change-Id: Idb049c54978824709a190c413d82d42f40226aa7 --- .../com/android/server/wm/AppWindowToken.java | 33 ++++++++++++++----- .../server/wm/WindowSurfacePlacer.java | 26 ++++----------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index eac72b01c8f9c..a9624cfaba955 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -337,6 +337,30 @@ class AppWindowToken extends WindowToken { } } + void clearAnimatingFlags() { + for (int i = allAppWindows.size() - 1; i >= 0; i--) { + final WindowState win = allAppWindows.get(i); + // We don't want to clear it out for windows that get replaced, because the + // animation depends on the flag to remove the replaced window. + // + // We also don't clear the mAnimatingExit flag for windows which have the + // mRemoveOnExit flag. This indicates an explicit remove request has been issued + // by the client. We should let animation proceed and not clear this flag or + // they won't eventually be removed by WindowStateAnimator#finishExit. + if (!win.mWillReplaceWindow && !win.mRemoveOnExit) { + win.mAnimatingExit = false; + // Clear mAnimating flag together with mAnimatingExit. When animation + // changes from exiting to entering, we need to clear this flag until the + // new animation gets applied, so that isAnimationStarting() becomes true + // until then. + // Otherwise applySurfaceChangesTransaction will faill to skip surface + // placement for this window during this period, one or more frame will + // show up with wrong position or scale. + win.mWinAnimator.mAnimating = false; + } + } + } + void destroySurfaces() { destroySurfaces(false /*cleanupOnResume*/); } @@ -363,15 +387,6 @@ class AppWindowToken extends WindowToken { win.mWinAnimator.destroyPreservedSurfaceLocked(); - if (cleanupOnResume) { - // If the window has an unfinished exit animation, consider that animation - // done and mark the window destroying so that it goes through the cleanup. - if (win.mAnimatingExit) { - win.mDestroying = true; - win.mAnimatingExit = false; - } - } - if (!win.mDestroying) { continue; } diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 0bd5eafa3293c..ee4a9a4173796 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -1138,6 +1138,12 @@ class WindowSurfacePlacer { if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) { openingAppHasWallpaper = true; } + // Clearing the mAnimatingExit flag before entering animation. It's set to + // true if app window is removed, or window relayout to invisible. + // This also affects window visibility. We need to clear it *before* + // maybeUpdateTransitToWallpaper() as the transition selection depends on + // wallpaper target visibility. + wtoken.clearAnimatingFlags(); } voiceInteraction |= wtoken.voiceInteraction; @@ -1262,26 +1268,6 @@ class WindowSurfacePlacer { int layer = -1; for (int j = 0; j < wtoken.allAppWindows.size(); j++) { final WindowState win = wtoken.allAppWindows.get(j); - // Clearing the mAnimatingExit flag before entering animation. It will be set to true - // if app window is removed, or window relayout to invisible. We don't want to - // clear it out for windows that get replaced, because the animation depends on - // the flag to remove the replaced window. - // - // We also don't clear the mAnimatingExit flag for windows which have the - // mRemoveOnExit flag. This indicates an explicit remove request has been issued - // by the client. We should let animation proceed and not clear this flag or - // they won't eventually be removed by WindowStateAnimator#finishExit. - if (!win.mWillReplaceWindow && !win.mRemoveOnExit) { - win.mAnimatingExit = false; - // Clear mAnimating flag together with mAnimatingExit. When animation - // changes from exiting to entering, we need to clear this flag until the - // new animation gets applied, so that isAnimationStarting() becomes true - // until then. - // Otherwise applySurfaceChangesTransaction will faill to skip surface - // placement for this window during this period, one or more frame will - // show up with wrong position or scale. - win.mWinAnimator.mAnimating = false; - } if (win.mWinAnimator.mAnimLayer > layer) { layer = win.mWinAnimator.mAnimLayer; }