From e22006d936e0928b4a335646f19a8ca18a7fb1e2 Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Mon, 9 May 2016 10:59:59 -0700 Subject: [PATCH] Fix a flicker when opening app again quickly while it's exiting If the app is waiting for an opening animation with a dummy placeholder, we need to skip the surface placement (in addition to the animateLocked). Also, when animating is changing from exiting to entering, the mAnimating flag needs to be cleared until the new animation starts. This prevents the surface placement to place it wrong before the new animaition starts. bug: 28599295 bug: 27742244 Change-Id: I26f0ead80ee9993a6c766ae8686ab11d1729519c --- .../com/android/server/wm/WindowStateAnimator.java | 11 +++++++++-- .../com/android/server/wm/WindowSurfacePlacer.java | 14 +++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index a0784b5008db6..e5f603c7865bc 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -322,6 +322,14 @@ class WindowStateAnimator { return mAnimation != null; } + /** + * Is this window currently waiting to run an opening animation? + */ + boolean isWaitingForOpening() { + return mService.mAppTransition.isTransitionSet() && isDummyAnimation() + && mService.mOpeningApps.contains(mWin.mAppToken); + } + void cancelExitAnimationForNextAnimationLocked() { if (DEBUG_ANIM) Slog.d(TAG, "cancelExitAnimationForNextAnimationLocked: " + mWin); @@ -1448,8 +1456,7 @@ class WindowStateAnimator { // the same app again before the app's surface is destroyed or saved, the surface // is always ready in the whole process.) If we go ahead here, the opening app // will be shown with the full size before the correct animation spec arrives. - if (mService.mAppTransition.isTransitionSet() && isDummyAnimation() && - mService.mOpeningApps.contains(w.mAppToken)) { + if (isWaitingForOpening()) { return; } diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index fb4be303ced30..e20e245aa5748 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -772,7 +772,7 @@ class WindowSurfacePlacer { } } } - if (!winAnimator.isAnimationStarting()) { + if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) { // Updates the shown frame before we set up the surface. This is needed // because the resizing could change the top-left position (in addition to // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to @@ -1236,8 +1236,8 @@ class WindowSurfacePlacer { int topOpeningLayer = 0; if (animLp != null) { int layer = -1; - for (int j = 0; j < wtoken.windows.size(); j++) { - final WindowState win = wtoken.windows.get(j); + 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 @@ -1249,6 +1249,14 @@ class WindowSurfacePlacer { // 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;