Separate animation steps into start, step and finish phases.
Fixes bug 6089126.

Change-Id: Iafbde36ff719640335a7ecf762e1d991cf7915e4
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 0e3d20a..b84fbdb 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -37,7 +37,7 @@
  * Version of WindowToken that is specifically for a particular application (or
  * really activity) that is displaying windows.
  */
-class AppWindowToken extends WindowToken {
+class AppWindowToken extends WindowToken implements WindowManagerService.StepAnimator {
     // Non-null only for application tokens.
     final IApplicationToken appToken;
 
@@ -195,8 +195,28 @@
         }
     }
 
+    @Override
+    public boolean stepAnimation(long currentTime) {
+        if (animation == null) {
+            return false;
+        }
+        transformation.clear();
+        final boolean more = animation.getTransformation(currentTime, transformation);
+        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+            WindowManagerService.TAG, "Stepped animation in " + this +
+            ": more=" + more + ", xform=" + transformation);
+        if (!more) {
+            animation = null;
+            if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                WindowManagerService.TAG, "Finished animation in " + this +
+                " @ " + currentTime);
+        }
+        hasTransformation = more;
+        return more;
+    }
+
     // This must be called while inside a transaction.
-    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
+    boolean startAndFinishAnimationLocked(long currentTime, int dw, int dh) {
         if (!service.mDisplayFrozen && service.mPolicy.isScreenOnFully()) {
             // We will run animations as long as the display isn't frozen.
 
@@ -219,21 +239,8 @@
                     animation.setStartTime(currentTime);
                     animating = true;
                 }
-                transformation.clear();
-                final boolean more = animation.getTransformation(
-                    currentTime, transformation);
-                if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                    WindowManagerService.TAG, "Stepped animation in " + this +
-                    ": more=" + more + ", xform=" + transformation);
-                if (more) {
-                    // we're done!
-                    hasTransformation = true;
-                    return true;
-                }
-                if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                    WindowManagerService.TAG, "Finished animation in " + this +
-                    " @ " + currentTime);
-                animation = null;
+                // we're done!
+                return true;
             }
         } else if (animation != null) {
             // If the display is frozen, and there is a pending animation,
@@ -369,6 +376,7 @@
         return null;
     }
 
+    @Override
     void dump(PrintWriter pw, String prefix) {
         super.dump(pw, prefix);
         if (appToken != null) {
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 04a039f..1335a44 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -29,7 +29,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.Transformation;
 
-class ScreenRotationAnimation {
+class ScreenRotationAnimation implements WindowManagerService.StepAnimator {
     static final String TAG = "ScreenRotationAnimation";
     static final boolean DEBUG_STATE = false;
     static final boolean DEBUG_TRANSFORMS = false;
@@ -97,6 +97,12 @@
     final Matrix mSnapshotFinalMatrix = new Matrix();
     final Matrix mTmpMatrix = new Matrix();
     final float[] mTmpFloats = new float[9];
+    private boolean mMoreRotateEnter;
+    private boolean mMoreRotateExit;
+    private boolean mMoreFinishEnter;
+    private boolean mMoreFinishExit;
+    private boolean mMoreStartEnter;
+    private boolean mMoreStartExit;
 
     public void printTo(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("mSurface="); pw.print(mSurface);
@@ -456,7 +462,144 @@
                 && mRotateEnterAnimation != null || mRotateExitAnimation != null;
     }
 
+    @Override
     public boolean stepAnimation(long now) {
+
+        if (mFinishAnimReady && mFinishAnimStartTime < 0) {
+            if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
+            mFinishAnimStartTime = now;
+        }
+
+        // If the start animation is no longer running, we want to keep its
+        // transformation intact until the finish animation also completes.
+
+        mMoreStartExit = false;
+        if (mStartExitAnimation != null) {
+            mStartExitTransformation.clear();
+            mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
+            if (!mMoreStartExit) {
+                if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!");
+                mStartExitAnimation.cancel();
+                mStartExitAnimation = null;
+            }
+        }
+
+        mMoreStartEnter = false;
+        if (mStartEnterAnimation != null) {
+            mStartEnterTransformation.clear();
+            mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
+            if (!mMoreStartEnter) {
+                if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!");
+                mStartEnterAnimation.cancel();
+                mStartEnterAnimation = null;
+            }
+        }
+
+        long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0;
+        if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);
+
+        mFinishExitTransformation.clear();
+        mMoreFinishExit = false;
+        if (mFinishExitAnimation != null) {
+            mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
+            if (!mMoreStartExit && !mMoreFinishExit) {
+                if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!");
+                mStartExitTransformation.clear();
+                mFinishExitAnimation.cancel();
+                mFinishExitAnimation = null;
+                mFinishExitTransformation.clear();
+            }
+        }
+
+        mFinishEnterTransformation.clear();
+        mMoreFinishEnter = false;
+        if (mFinishEnterAnimation != null) {
+            mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
+            if (!mMoreStartEnter && !mMoreFinishEnter) {
+                if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!");
+                mStartEnterTransformation.clear();
+                mFinishEnterAnimation.cancel();
+                mFinishEnterAnimation = null;
+                mFinishEnterTransformation.clear();
+            }
+        }
+
+        mRotateExitTransformation.clear();
+        mMoreRotateExit = false;
+        if (mRotateExitAnimation != null) {
+            mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
+        }
+
+        if (!mMoreFinishExit && !mMoreRotateExit) {
+            if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!");
+            mRotateExitAnimation.cancel();
+            mRotateExitAnimation = null;
+            mRotateExitTransformation.clear();
+        }
+
+        mRotateEnterTransformation.clear();
+        mMoreRotateEnter = false;
+        if (mRotateEnterAnimation != null) {
+            mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
+        }
+
+        if (!mMoreFinishEnter && !mMoreRotateEnter) {
+            if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!");
+            mRotateEnterAnimation.cancel();
+            mRotateEnterAnimation = null;
+            mRotateEnterTransformation.clear();
+        }
+
+        mExitTransformation.set(mRotateExitTransformation);
+        mExitTransformation.compose(mStartExitTransformation);
+        mExitTransformation.compose(mFinishExitTransformation);
+
+        mEnterTransformation.set(mRotateEnterTransformation);
+        mEnterTransformation.compose(mStartEnterTransformation);
+        mEnterTransformation.compose(mFinishEnterTransformation);
+
+        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
+        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);
+
+        final boolean more = mMoreStartEnter || mMoreStartExit || mMoreFinishEnter
+                || mMoreFinishExit || mMoreRotateEnter || mMoreRotateExit || !mFinishAnimReady;
+
+        mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
+
+        if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
+
+        return more;
+    }
+
+    void updateSurfaces() {
+        if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
+            if (mSurface != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
+                mSurface.hide();
+            }
+        }
+
+        if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) {
+            if (mBlackFrame != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, hiding black frame");
+                mBlackFrame.hide();
+            }
+        } else {
+            if (mBlackFrame != null) {
+                mBlackFrame.setMatrix(mEnterTransformation.getMatrix());
+            }
+        }
+
+        setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
+    }
+    
+    public boolean startAndFinishAnimationLocked(long now) {
         if (!isAnimating()) {
             if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
             return false;
@@ -484,136 +627,8 @@
             }
             mAnimRunning = true;
         }
-
-        if (mFinishAnimReady && mFinishAnimStartTime < 0) {
-            if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
-            mFinishAnimStartTime = now;
-        }
-
-        // If the start animation is no longer running, we want to keep its
-        // transformation intact until the finish animation also completes.
-
-        boolean moreStartExit = false;
-        if (mStartExitAnimation != null) {
-            mStartExitTransformation.clear();
-            moreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
-            if (!moreStartExit) {
-                if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!");
-                mStartExitAnimation.cancel();
-                mStartExitAnimation = null;
-            }
-        }
-
-        boolean moreStartEnter = false;
-        if (mStartEnterAnimation != null) {
-            mStartEnterTransformation.clear();
-            moreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
-            if (!moreStartEnter) {
-                if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!");
-                mStartEnterAnimation.cancel();
-                mStartEnterAnimation = null;
-            }
-        }
-
-        long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0;
-        if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);
-
-        mFinishExitTransformation.clear();
-        boolean moreFinishExit = false;
-        if (mFinishExitAnimation != null) {
-            moreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
-            if (!moreStartExit && !moreFinishExit) {
-                if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!");
-                mStartExitTransformation.clear();
-                mFinishExitAnimation.cancel();
-                mFinishExitAnimation = null;
-                mFinishExitTransformation.clear();
-            }
-        }
-
-        mFinishEnterTransformation.clear();
-        boolean moreFinishEnter = false;
-        if (mFinishEnterAnimation != null) {
-            moreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
-            if (!moreStartEnter && !moreFinishEnter) {
-                if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!");
-                mStartEnterTransformation.clear();
-                mFinishEnterAnimation.cancel();
-                mFinishEnterAnimation = null;
-                mFinishEnterTransformation.clear();
-            }
-        }
-
-        mRotateExitTransformation.clear();
-        boolean moreRotateExit = false;
-        if (mRotateExitAnimation != null) {
-            moreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
-        }
-
-        if (!moreFinishExit && !moreRotateExit) {
-            if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!");
-            mRotateExitAnimation.cancel();
-            mRotateExitAnimation = null;
-            mRotateExitTransformation.clear();
-        }
-
-        mRotateEnterTransformation.clear();
-        boolean moreRotateEnter = false;
-        if (mRotateEnterAnimation != null) {
-            moreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
-        }
-
-        if (!moreFinishEnter && !moreRotateEnter) {
-            if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!");
-            mRotateEnterAnimation.cancel();
-            mRotateEnterAnimation = null;
-            mRotateEnterTransformation.clear();
-        }
-
-        mExitTransformation.set(mRotateExitTransformation);
-        mExitTransformation.compose(mStartExitTransformation);
-        mExitTransformation.compose(mFinishExitTransformation);
-
-        mEnterTransformation.set(mRotateEnterTransformation);
-        mEnterTransformation.compose(mStartEnterTransformation);
-        mEnterTransformation.compose(mFinishEnterTransformation);
-
-        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
-        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);
-
-        if (!moreStartExit && !moreFinishExit && !moreRotateExit) {
-            if (mSurface != null) {
-                if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
-                mSurface.hide();
-            }
-        }
-
-        if (!moreStartEnter && !moreFinishEnter && !moreRotateEnter) {
-            if (mBlackFrame != null) {
-                if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, hiding black frame");
-                mBlackFrame.hide();
-            }
-        } else {
-            if (mBlackFrame != null) {
-                mBlackFrame.setMatrix(mEnterTransformation.getMatrix());
-            }
-        }
-
-        mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
-        setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
-
-        final boolean more = moreStartEnter || moreStartExit || moreFinishEnter || moreFinishExit
-                || moreRotateEnter || moreRotateExit || !mFinishAnimReady;
-
-        if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
-
-        return more;
+        
+        return true;
     }
 
     public Transformation getEnterTransformation() {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 008793c..6221b90 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -617,6 +617,18 @@
     final AnimationRunnable mAnimationRunnable = new AnimationRunnable();
     boolean mAnimationScheduled;
 
+    interface StepAnimator {
+        /**
+         * Continue the stepping of an ongoing animation. When the animation completes this method
+         * must disable the animation on the StepAnimator. 
+         * @param currentTime Animation time in milliseconds. Use SystemClock.uptimeMillis().
+         * @return True if the animation is still going on, false if the animation has completed
+         *      and stepAnimation has cleared the animation locally.
+         */
+        boolean stepAnimation(long currentTime);
+    }
+    final ArrayList<StepAnimator> mStepAnimators = new ArrayList<StepAnimator>();
+    
     final class DragInputEventReceiver extends InputEventReceiver {
         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
             super(inputChannel, looper);
@@ -7615,37 +7627,53 @@
     }
 
     /**
+     * Run through each of the animating objects saved in mStepAnimators.
+     */
+    private void stepAnimations() {
+        final long currentTime = SystemClock.uptimeMillis();
+        for (final StepAnimator stepAnimator : mStepAnimators) {
+            final boolean more = stepAnimator.stepAnimation(currentTime);
+            if (DEBUG_ANIM) {
+                Slog.v(TAG, "stepAnimations: " + currentTime + ": Stepped " + stepAnimator
+                        + (more ? " more" : " done"));
+            }
+        }
+    }
+    
+    /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
      * Update animations of all applications, including those associated with exiting/removed apps.
      *
      * @param currentTime The time which animations use for calculating transitions.
      * @param innerDw Width of app window.
      * @param innerDh Height of app window.
-     * @return true if rotation has stopped, false otherwise
      */
     private void updateWindowsAppsAndRotationAnimationsLocked(long currentTime,
                                                           int innerDw, int innerDh) {
         int i;
-        for (i = mWindows.size() - 1; i >= 0; i--) {
-            mInnerFields.mAnimating |= mWindows.get(i).stepAnimationLocked(currentTime);
-        }
-
         final int NAT = mAppTokens.size();
         for (i=0; i<NAT; i++) {
-            mInnerFields.mAnimating |=
-                    mAppTokens.get(i).stepAnimationLocked(currentTime, innerDw, innerDh);
+            final AppWindowToken appToken = mAppTokens.get(i);
+            if (appToken.startAndFinishAnimationLocked(currentTime, innerDw, innerDh)) {
+                mStepAnimators.add(appToken);
+                mInnerFields.mAnimating = true;
+            }
         }
         final int NEAT = mExitingAppTokens.size();
         for (i=0; i<NEAT; i++) {
-            mInnerFields.mAnimating |=
-                    mExitingAppTokens.get(i).stepAnimationLocked(currentTime, innerDw, innerDh);
+            final AppWindowToken appToken = mAppTokens.get(i);
+            if (appToken.startAndFinishAnimationLocked(currentTime, innerDw, innerDh)) {
+                mStepAnimators.add(appToken);
+                mInnerFields.mAnimating = true;
+            }
         }
 
         if (mScreenRotationAnimation != null) {
             if (mScreenRotationAnimation.isAnimating()) {
-                if (mScreenRotationAnimation.stepAnimation(currentTime)) {
+                if (mScreenRotationAnimation.startAndFinishAnimationLocked(currentTime)) {
                     mInnerFields.mUpdateRotation = false;
                     mInnerFields.mAnimating = true;
+                    mStepAnimators.add(mScreenRotationAnimation);
                 } else {
                     mInnerFields.mUpdateRotation = true;
                     mScreenRotationAnimation.kill();
@@ -7704,7 +7732,13 @@
                 }
 
                 final boolean wasAnimating = w.mWasAnimating;
-                final boolean nowAnimating = w.mLocalAnimating;
+                
+                
+                final boolean nowAnimating = w.startAndFinishAnimationLocked(currentTime);
+                if (nowAnimating) {
+                    mStepAnimators.add(w);
+                    mInnerFields.mAnimating = true;
+                }
 
                 if (DEBUG_WALLPAPER) {
                     Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
@@ -8290,6 +8324,10 @@
         // difficult because we do need to resize surfaces in some
         // cases while they are hidden such as when first showing a
         // window.
+        
+        if (mScreenRotationAnimation != null) {
+            mScreenRotationAnimation.updateSurfaces();
+        }
         boolean displayed = false;
 
         w.computeShownFrameLocked();
@@ -8562,7 +8600,7 @@
             // so we want to leave all of them as unblurred (for
             // performance reasons).
             mInnerFields.mObscured = true;
-        } else if (canBeSeen && (attrFlags & FLAG_BLUR_BEHIND | FLAG_DIM_BEHIND) != 0) {
+        } else if (canBeSeen && (attrFlags & (FLAG_BLUR_BEHIND | FLAG_DIM_BEHIND)) != 0) {
             if (localLOGV) Slog.v(TAG, "Win " + w
                     + ": blurring=" + mInnerFields.mBlurring
                     + " obscured=" + mInnerFields.mObscured);
@@ -8735,6 +8773,7 @@
                 mInnerFields.mWindowAnimationBackground = null;
                 mInnerFields.mWindowAnimationBackgroundColor = 0;
 
+                mStepAnimators.clear();
                 changes = updateWindowsAndWallpaperLocked(currentTime, dw, dh, innerDw, innerDh);
 
                 if (mInnerFields.mTokenMayBeDrawn) {
@@ -8782,9 +8821,10 @@
 
             // Update animations of all applications, including those
             // associated with exiting/removed apps
-            mInnerFields.mAnimating = false;
 
             updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
+            
+            stepAnimations();
 
             // THIRD LOOP: Update the surfaces of all windows.
 
@@ -9667,8 +9707,8 @@
             pw.println();
             pw.println("  Application tokens in Z order:");
             for (int i=mAppTokens.size()-1; i>=0; i--) {
-                pw.print("  App #"); pw.print(i); pw.print(": ");
-                        pw.println(mAppTokens.get(i));
+                pw.print("  App #"); pw.print(i); pw.println(": ");
+                        mAppTokens.get(i).dump(pw, "    ");
             }
         }
         if (mFinishedStarting.size() > 0) {
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index eeecad1..b9ee660 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -54,7 +54,8 @@
 /**
  * A window in the window manager.
  */
-final class WindowState implements WindowManagerPolicy.WindowState {
+final class WindowState implements WindowManagerPolicy.WindowState,
+        WindowManagerService.StepAnimator {
     static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
     static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
     static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
@@ -977,9 +978,26 @@
         return true;
     }
 
+    @Override
+    public boolean stepAnimation(long currentTime) {
+        if ((mAnimation == null) || !mLocalAnimating) {
+            return false;
+        }
+        mTransformation.clear();
+        final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
+        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+            WindowManagerService.TAG, "Stepped animation in " + this +
+            ": more=" + more + ", xform=" + mTransformation);
+        if (!more) {
+            mAnimation.cancel();
+            mAnimation = null;
+        }
+        return more;
+    }
+
     // This must be called while inside a transaction.  Returns true if
     // there is more animation to run.
-    boolean stepAnimationLocked(long currentTime) {
+    boolean startAndFinishAnimationLocked(long currentTime) {
         // Save the animation state as it was before this step so WindowManagerService can tell if
         // we just started or just stopped animating by comparing mWasAnimating with isAnimating().
         mWasAnimating = mAnimating;
@@ -1001,24 +1019,12 @@
                     mLocalAnimating = true;
                     mAnimating = true;
                 }
-                mTransformation.clear();
-                final boolean more = mAnimation.getTransformation(
-                    currentTime, mTransformation);
-                if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                    WindowManagerService.TAG, "Stepped animation in " + this +
-                    ": more=" + more + ", xform=" + mTransformation);
-                if (more) {
-                    // we're not done!
+                if ((mAnimation != null) && mLocalAnimating) {
                     return true;
                 }
                 if (WindowManagerService.DEBUG_ANIM) Slog.v(
                     WindowManagerService.TAG, "Finished animation in " + this +
                     " @ " + currentTime);
-
-                if (mAnimation != null) {
-                    mAnimation.cancel();
-                    mAnimation = null;
-                }
                 //WindowManagerService.this.dump();
             }
             mHasLocalTransformation = false;