From 65d15d03326456457039dde69ae37e9ae1db6d6e Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Mon, 14 Mar 2016 13:59:32 -0700 Subject: [PATCH] Fixing misc issues that leads to black screen when pressing Home - Make sure to clear usingTransferredAnimation flag together when setting app animator's animation to null. Not clearing it will cause setAppVisibility to not apply dummy animation (placeholder) to a closing app token while it should, and the closing app token will then exit early before the opening app is ready, since it doesn't have any animation set. This causes a brief blank period. - When app relayout to invisible, make sure to mark mWinAnimator's mAnimating to true if we decided exit animation is running. Note that even if we didn't actually apply the animation (which could happen if the window is no longer visible by policy), if the app token itself is under any animation, we need to mark mAnimating otherwise the clean up code in FinishExit will not run, and the window will be stuck in Exiting state. - We no longer change mAnimatingExit flag in setAppVisibility(), but wait for app's relayoutWindow calls to change it if applicable. setAppVisibilty doesn't apply the animation until transition is good to go. Setting the flag without the animation applied will disable setTokenVisibilityLocked and relayoutWindow to actually apply the animation, because they may think the window is no longer visible. bug: 27391256 Change-Id: I292305847d742cdbb5ebe6aa8daa5d83bf65483b --- .../android/server/wm/AppWindowAnimator.java | 12 ++++++++---- .../com/android/server/wm/AppWindowToken.java | 17 ----------------- .../android/server/wm/WindowManagerService.java | 13 +++++++++---- .../java/com/android/server/wm/WindowState.java | 4 ++-- .../android/server/wm/WindowSurfacePlacer.java | 6 +++--- 5 files changed, 22 insertions(+), 30 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 55b3c7baf4a2a..3a5dec9397210 100644 --- a/services/core/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -171,17 +171,21 @@ public class AppWindowAnimator { transformation.setAlpha(mAppToken.isVisible() ? 1 : 0); } + void setNullAnimation() { + animation = null; + usingTransferredAnimation = false; + } + public void clearAnimation() { if (animation != null) { - animation = null; animating = true; } clearThumbnail(); + setNullAnimation(); if (mAppToken.deferClearAllDrawn) { mAppToken.allDrawn = false; mAppToken.deferClearAllDrawn = false; } - usingTransferredAnimation = false; } public boolean isAnimating() { @@ -202,9 +206,9 @@ public class AppWindowAnimator { if (animation != null) { toAppAnimator.animation = animation; - animation = null; toAppAnimator.animating = animating; toAppAnimator.animLayerAdjustment = animLayerAdjustment; + setNullAnimation(); animLayerAdjustment = 0; toAppAnimator.updateLayers(); updateLayers(); @@ -311,7 +315,7 @@ public class AppWindowAnimator { if (mProlongAnimation == PROLONG_ANIMATION_AT_END) { hasMoreFrames = true; } else { - animation = null; + setNullAnimation(); clearThumbnail(); if (DEBUG_ANIM) Slog.v(TAG, "Finished animation in " + mAppToken + " @ " + currentTime); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 9795c93e8e024..4ec297e310152 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -322,23 +322,6 @@ class AppWindowToken extends WindowToken { } } - void setWindowsExiting(boolean exiting) { - for (int i = allAppWindows.size() - 1; i >= 0; i--) { - WindowState win = allAppWindows.get(i); - // If the app already requested to remove its window, we don't modify - // its exiting state. Otherwise the stale window won't get removed on - // exit and could cause focus to be given to the wrong window. - if (!(win.mRemoveOnExit && win.mAnimatingExit)) { - win.mAnimatingExit = exiting; - } - // If we're no longer exiting, remove the window from destroying list - if (!win.mAnimatingExit && win.mDestroying) { - win.mDestroying = false; - service.mDestroySurface.remove(win); - } - } - } - // Here we destroy surfaces which have been marked as eligible by the animator, taking care // to ensure the client has finished with them. If the client could still be using them // we will skip destruction and try again when the client has stopped. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index a998bc3be63b8..b20dd3930083f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2825,10 +2825,12 @@ public class WindowManagerService extends IWindowManager.Stub if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { focusMayChange = isDefaultDisplay; win.mAnimatingExit = true; + win.mWinAnimator.mAnimating = true; } else if (win.mWinAnimator.isAnimating()) { // Currently in a hide animation... turn this into // an exit. win.mAnimatingExit = true; + win.mWinAnimator.mAnimating = true; } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) { // If the wallpaper is currently behind this // window, we need to change both of them inside @@ -4085,7 +4087,7 @@ public class WindowManagerService extends IWindowManager.Stub if (transit != AppTransition.TRANSIT_UNSET) { if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { - wtoken.mAppAnimator.animation = null; + wtoken.mAppAnimator.setNullAnimation(); } if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) { delayed = runningAppAnimation = true; @@ -4195,7 +4197,7 @@ public class WindowManagerService extends IWindowManager.Stub void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) { if (transit != AppTransition.TRANSIT_UNSET) { if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { - wtoken.mAppAnimator.animation = null; + wtoken.mAppAnimator.setNullAnimation(); } applyAnimationLocked(wtoken, null, transit, false, false); } @@ -4255,7 +4257,6 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ADD_REMOVE) Slog.v( TAG_WM, "No longer Stopped: " + wtoken); wtoken.mAppStopped = false; - wtoken.setWindowsExiting(false); mOpeningApps.add(wtoken); wtoken.startingMoved = false; @@ -4287,6 +4288,11 @@ public class WindowManagerService extends IWindowManager.Stub // animation is going on (in this case an application transition). If the animation // was transferred from another application/animator, no dummy animator should be // created since an animation is already in progress. + if (wtoken.mAppAnimator.usingTransferredAnimation + && wtoken.mAppAnimator.animation == null) { + Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken + + ", using null transfered animation!"); + } if (!wtoken.mAppAnimator.usingTransferredAnimation && (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) { if (DEBUG_APP_TRANSITIONS) Slog.v( @@ -4297,7 +4303,6 @@ public class WindowManagerService extends IWindowManager.Stub if (visible) { wtoken.mEnteringAnimation = true; } else { - wtoken.setWindowsExiting(true); mClosingApps.add(wtoken); wtoken.mEnteringAnimation = false; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 617d2b4d28e3a..1e3e1df6e056b 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -670,8 +670,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { } if (windowsAreFloating) { - // In floating modes (e.g. freeform, pinned) we have only to set the rectangle - // if it wasn't set already. No need to intersect it with the (visible) + // In floating modes (e.g. freeform, pinned) we have only to set the rectangle + // if it wasn't set already. No need to intersect it with the (visible) // "content frame" since it is allowed to be outside the visible desktop. if (mContainingFrame.isEmpty()) { mContainingFrame.set(cf); diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 8ada2f1a1646b..5ad771fbcd04e 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -1158,7 +1158,7 @@ class WindowSurfacePlacer { if (!appAnimator.usingTransferredAnimation) { appAnimator.clearThumbnail(); - appAnimator.animation = null; + appAnimator.setNullAnimation(); } wtoken.inPendingTransaction = false; @@ -1231,7 +1231,7 @@ class WindowSurfacePlacer { final AppWindowAnimator appAnimator = wtoken.mAppAnimator; if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); appAnimator.clearThumbnail(); - appAnimator.animation = null; + appAnimator.setNullAnimation(); wtoken.inPendingTransaction = false; mService.setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); @@ -1494,7 +1494,7 @@ class WindowSurfacePlacer { if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken); appAnimator.clearThumbnail(); - appAnimator.animation = null; + appAnimator.setNullAnimation(); mService.updateTokenInPlaceLocked(wtoken, transit); wtoken.updateReportedVisibilityLocked();