From 8ebc82a63f7e4818bb615cf980b961757c8d6587 Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Wed, 13 May 2015 15:27:12 -0700 Subject: Don't stop animation when starting windows app token changes If another activity is starting while we are still animating the starting window of the previous activity to start, we transfer the starting window of the old activity to the one that is currently starting so we don't have to create another starting window and also to reduce jank from the starting window animation appearing to restart. However, there were several conditions that led to the starting window animation stopping when the transfers app tokens 1. Starting window animator not been removed from the previous app token animator causing it to finish/remove the starting window prematurily. 2. Starting window animator not been properly added to the new app token animator causing the animation not be be picked up. 3. WMS.mSkipAppTransitionAnimation been set to false regardless of if an app transition was actually prepared in WMS.prepareAppTransition() 4. WMS.mSkipAppTransitionAnimation not been set to true in all cases where the starting window transfers tokens even though we don't want the new app to do any transition animation is the starting window is animating. 5. New app not setting its animation to dummy animation when the next transition should be skipped due to starting window still animating. 6. Starting window animation been cleared for the new app in WMS.handleAppTransitionReadyLocked() even for cases where we transferred the animation from the previous app. Also, cleaned up some code. Bug: 20953232 Change-Id: I714d6bdfcdaeeaac29f9d464bab9f3e9c192e937 --- .../java/com/android/server/wm/AppTransition.java | 29 +++--- .../com/android/server/wm/AppWindowAnimator.java | 65 +++++++++---- .../android/server/wm/WindowManagerService.java | 105 +++++++++------------ 3 files changed, 109 insertions(+), 90 deletions(-) (limited to 'services/core/java/com/android/server/wm') diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 9033c9c..0357de2 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -289,11 +289,13 @@ public class AppTransition implements Dump { return mNextAppTransitionStartY; } - void prepare() { + boolean prepare() { if (!isRunning()) { mAppTransitionState = APP_STATE_IDLE; notifyAppTransitionPendingLocked(); + return true; } + return false; } void goodToGo(AppWindowAnimator openingAppAnimator, AppWindowAnimator closingAppAnimator) { @@ -953,8 +955,8 @@ public class AppTransition implements Dump { : com.android.internal.R.anim.voice_activity_open_exit); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation voice:" - + " anim=" + a + " transit=" + transit + " isEntrance=" + enter - + " Callers=" + Debug.getCallers(3)); + + " anim=" + a + " transit=" + appTransitionToString(transit) + + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_CLOSE || transit == TRANSIT_TASK_CLOSE || transit == TRANSIT_TASK_TO_BACK)) { @@ -963,22 +965,23 @@ public class AppTransition implements Dump { : com.android.internal.R.anim.voice_activity_close_exit); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation voice:" - + " anim=" + a + " transit=" + transit + " isEntrance=" + enter - + " Callers=" + Debug.getCallers(3)); + + " anim=" + a + " transit=" + appTransitionToString(transit) + + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) { a = loadAnimationRes(mNextAppTransitionPackage, enter ? mNextAppTransitionEnter : mNextAppTransitionExit); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=ANIM_CUSTOM" - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) { a = loadAnimationRes(mNextAppTransitionPackage, mNextAppTransitionInPlace); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation:" - + " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE" - + " transit=" + transit + " Callers=" + Debug.getCallers(3)); + + " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE" + + " transit=" + appTransitionToString(transit) + + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) { a = createClipRevealAnimationLocked(transit, enter, appFrame); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, @@ -990,7 +993,7 @@ public class AppTransition implements Dump { if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP" - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP || mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) { @@ -1003,7 +1006,7 @@ public class AppTransition implements Dump { "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN"; Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=" + animName - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP || @@ -1018,7 +1021,7 @@ public class AppTransition implements Dump { "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN"; Slog.v(TAG, "applyAnimation:" + " anim=" + a + " nextAppTransition=" + animName - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } } else { @@ -1084,7 +1087,7 @@ public class AppTransition implements Dump { "applyAnimation:" + " anim=" + a + " animAttr=0x" + Integer.toHexString(animAttr) - + " transit=" + transit + " isEntrance=" + enter + + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } return a; @@ -1188,7 +1191,7 @@ public class AppTransition implements Dump { @Override public String toString() { - return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition); + return "mNextAppTransition=" + appTransitionToString(mNextAppTransition); } /** diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 55ec9fc..268de03 100644 --- a/services/core/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -16,6 +16,11 @@ package com.android.server.wm; +import static com.android.server.wm.WindowManagerService.DEBUG_ANIM; +import static com.android.server.wm.WindowManagerService.DEBUG_LAYERS; +import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS; +import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; + import android.graphics.Matrix; import android.util.Slog; import android.util.TimeUtils; @@ -77,7 +82,11 @@ public class AppWindowAnimator { boolean deferFinalFrameCleanup; /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */ - ArrayList mAllAppWinAnimators = new ArrayList(); + ArrayList mAllAppWinAnimators = new ArrayList<>(); + + /** True if the current animation was transferred from another AppWindowAnimator. + * See {@link #transferCurrentAnimation}*/ + boolean usingTransferredAnimation = false; static final Animation sDummyAnimation = new DummyAnimation(); @@ -101,9 +110,9 @@ public class AppWindowAnimator { int zorder = anim.getZAdjustment(); int adj = 0; if (zorder == Animation.ZORDER_TOP) { - adj = WindowManagerService.TYPE_LAYER_OFFSET; + adj = TYPE_LAYER_OFFSET; } else if (zorder == Animation.ZORDER_BOTTOM) { - adj = -WindowManagerService.TYPE_LAYER_OFFSET; + adj = -TYPE_LAYER_OFFSET; } if (animLayerAdjustment != adj) { @@ -139,6 +148,7 @@ public class AppWindowAnimator { mAppToken.allDrawn = false; mAppToken.deferClearAllDrawn = false; } + usingTransferredAnimation = false; } public boolean isAnimating() { @@ -153,19 +163,38 @@ public class AppWindowAnimator { deferThumbnailDestruction = false; } + void transferCurrentAnimation( + AppWindowAnimator toAppAnimator, WindowStateAnimator transferWinAnimator) { + + if (animation != null) { + toAppAnimator.animation = animation; + animation = null; + toAppAnimator.animating = animating; + toAppAnimator.animLayerAdjustment = animLayerAdjustment; + animLayerAdjustment = 0; + toAppAnimator.updateLayers(); + updateLayers(); + toAppAnimator.usingTransferredAnimation = true; + } + if (transferWinAnimator != null) { + mAllAppWinAnimators.remove(transferWinAnimator); + toAppAnimator.mAllAppWinAnimators.add(transferWinAnimator); + transferWinAnimator.mAppAnimator = toAppAnimator; + } + } + void updateLayers() { - final int N = mAppToken.allAppWindows.size(); + final int windowCount = mAppToken.allAppWindows.size(); final int adj = animLayerAdjustment; thumbnailLayer = -1; - for (int i=0; i thumbnailLayer) { thumbnailLayer = winAnimator.mAnimLayer; } - if (WindowManagerService.DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " - + winAnimator.mAnimLayer); + if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " + winAnimator.mAnimLayer); if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) { mService.setInputMethodAnimLayerAdjustment(adj); } @@ -190,11 +219,11 @@ public class AppWindowAnimator { // cache often used attributes locally final float tmpFloats[] = mService.mTmpFloats; thumbnailTransformation.getMatrix().getValues(tmpFloats); - if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, + if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X] + ", " + tmpFloats[Matrix.MTRANS_Y], null); thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]); - if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, + if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail, "thumbnail", "alpha=" + thumbnailTransformation.getAlpha() + " layer=" + thumbnailLayer + " matrix=[" + tmpFloats[Matrix.MSCALE_X] @@ -227,14 +256,14 @@ public class AppWindowAnimator { deferFinalFrameCleanup = true; hasMoreFrames = true; } else { - if (false && WindowManagerService.DEBUG_ANIM) Slog.v( - TAG, "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames + - ", xform=" + transformation); + if (false && DEBUG_ANIM) Slog.v(TAG, + "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames + + ", xform=" + transformation); deferFinalFrameCleanup = false; animation = null; clearThumbnail(); - if (WindowManagerService.DEBUG_ANIM) Slog.v( - TAG, "Finished animation in " + mAppToken + " @ " + currentTime); + if (DEBUG_ANIM) Slog.v(TAG, + "Finished animation in " + mAppToken + " @ " + currentTime); } } hasTransformation = hasMoreFrames; @@ -257,8 +286,8 @@ public class AppWindowAnimator { if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed) && animation != null) { if (!animating) { - if (WindowManagerService.DEBUG_ANIM) Slog.v( - TAG, "Starting animation in " + mAppToken + + if (DEBUG_ANIM) Slog.v(TAG, + "Starting animation in " + mAppToken + " @ " + currentTime + " scale=" + mService.getTransitionAnimationScaleLocked() + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating); @@ -305,8 +334,8 @@ public class AppWindowAnimator { mService.moveInputMethodWindowsIfNeededLocked(true); } - if (WindowManagerService.DEBUG_ANIM) Slog.v( - TAG, "Animation done in " + mAppToken + if (DEBUG_ANIM) Slog.v(TAG, + "Animation done in " + mAppToken + ": reportedVisible=" + mAppToken.reportedVisible); transformation.clear(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 57bad51..476c39f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -471,7 +471,7 @@ public class WindowManagerService extends IWindowManager.Stub String mLastANRState; /** All DisplayContents in the world, kept here */ - SparseArray mDisplayContents = new SparseArray(2); + SparseArray mDisplayContents = new SparseArray<>(2); int mRotation = 0; int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -487,7 +487,7 @@ public class WindowManagerService extends IWindowManager.Stub deathRecipient = d; } } - ArrayList mRotationWatchers = new ArrayList(); + ArrayList mRotationWatchers = new ArrayList<>(); int mDeferredRotationPauseCount; int mSystemDecorLayer = 0; @@ -528,11 +528,10 @@ public class WindowManagerService extends IWindowManager.Stub private final PowerManager.WakeLock mScreenFrozenLock; final AppTransition mAppTransition; - boolean mStartingIconInTransition = false; boolean mSkipAppTransitionAnimation = false; - final ArraySet mOpeningApps = new ArraySet(); - final ArraySet mClosingApps = new ArraySet(); + final ArraySet mOpeningApps = new ArraySet<>(); + final ArraySet mClosingApps = new ArraySet<>(); boolean mIsTouchDevice; @@ -557,7 +556,7 @@ public class WindowManagerService extends IWindowManager.Stub int mInputMethodAnimLayerAdjustment; WindowState mInputMethodWindow = null; - final ArrayList mInputMethodDialogs = new ArrayList(); + final ArrayList mInputMethodDialogs = new ArrayList<>(); /** Temporary list for comparison. Always clear this after use so we don't end up with * orphaned windows references */ @@ -4127,8 +4126,8 @@ public class WindowManagerService extends IWindowManager.Stub } synchronized(mWindowMap) { - if (DEBUG_APP_TRANSITIONS) Slog.v( - TAG, "Prepare app transition: transit=" + transit + if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Prepare app transition:" + + " transit=" + AppTransition.appTransitionToString(transit) + " " + mAppTransition + " alwaysKeepCurrent=" + alwaysKeepCurrent + " Callers=" + Debug.getCallers(3)); @@ -4147,9 +4146,7 @@ public class WindowManagerService extends IWindowManager.Stub mAppTransition.setAppTransition(transit); } } - if (okToDisplay()) { - mAppTransition.prepare(); - mStartingIconInTransition = false; + if (okToDisplay() && mAppTransition.prepare()) { mSkipAppTransitionAnimation = false; } if (mAppTransition.isTransitionSet()) { @@ -4276,19 +4273,16 @@ public class WindowManagerService extends IWindowManager.Stub if (ttoken != null) { WindowState startingWindow = ttoken.startingWindow; if (startingWindow != null) { - if (mStartingIconInTransition) { - // In this case, the starting icon has already - // been displayed, so start letting windows get - // shown immediately without any more transitions. - mSkipAppTransitionAnimation = true; - } + // In this case, the starting icon has already been displayed, so start + // letting windows get shown immediately without any more transitions. + mSkipAppTransitionAnimation = true; + if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Moving existing starting " + startingWindow + " from " + ttoken + " to " + wtoken); final long origId = Binder.clearCallingIdentity(); - // Transfer the starting window over to the new - // token. + // Transfer the starting window over to the new token. wtoken.startingData = ttoken.startingData; wtoken.startingView = ttoken.startingView; wtoken.startingDisplayed = ttoken.startingDisplayed; @@ -4302,7 +4296,6 @@ public class WindowManagerService extends IWindowManager.Stub startingWindow.mToken = wtoken; startingWindow.mRootToken = wtoken; startingWindow.mAppToken = wtoken; - startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator; if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) { Slog.v(TAG, "Removing starting window: " + startingWindow); @@ -4336,17 +4329,8 @@ public class WindowManagerService extends IWindowManager.Stub wtoken.clientHidden = ttoken.clientHidden; wtoken.sendAppVisibilityToClients(); } - final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator; - final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator; - if (tAppAnimator.animation != null) { - wAppAnimator.animation = tAppAnimator.animation; - wAppAnimator.animating = tAppAnimator.animating; - wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment; - tAppAnimator.animation = null; - tAppAnimator.animLayerAdjustment = 0; - wAppAnimator.updateLayers(); - tAppAnimator.updateLayers(); - } + ttoken.mAppAnimator.transferCurrentAnimation( + wtoken.mAppAnimator, startingWindow.mWinAnimator); updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/); @@ -4446,7 +4430,6 @@ public class WindowManagerService extends IWindowManager.Stub } if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData"); - mStartingIconInTransition = true; wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags); Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); @@ -4547,8 +4530,8 @@ public class WindowManagerService extends IWindowManager.Stub changed = true; } - final int N = wtoken.allAppWindows.size(); - for (int i=0; i layer) { layer = win.mWinAnimator.mAnimLayer; @@ -9410,8 +9398,8 @@ public class WindowManagerService extends IWindowManager.Stub } } } - NN = mClosingApps.size(); - for (i=0; i layer) { layer = win.mWinAnimator.mAnimLayer; @@ -11398,8 +11386,7 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting); pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting); pw.print(" mTraversalScheduled="); pw.println(mTraversalScheduled); - pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); - pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); + pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); pw.println(" mLayoutToAnim:"); mAppTransition.dump(pw, " "); } -- cgit v1.1