New screen rotation animation design.

We now have an animation that can start as soon as we detect to
rotate the screen, and have a different phase once the new UI
is ready to complete the transition into it.

Change-Id: I05b9c12a699232acbddc36b4a994a4452db71476
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 8fc9a70..55fb038 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -17,13 +17,8 @@
 package com.android.server.wm;
 
 import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.Matrix;
-import android.graphics.Paint;
 import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.util.Slog;
 import android.view.Surface;
@@ -34,7 +29,8 @@
 
 class ScreenRotationAnimation {
     static final String TAG = "ScreenRotationAnimation";
-    static final boolean DEBUG = false;
+    static final boolean DEBUG_STATE = false;
+    static final boolean DEBUG_TRANSFORMS = false;
 
     static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
 
@@ -49,11 +45,51 @@
     int mOriginalWidth, mOriginalHeight;
     int mCurRotation;
 
-    Animation mExitAnimation;
+    // For all animations, "exit" is for the UI elements that are going
+    // away (that is the snapshot of the old screen), and "enter" is for
+    // the new UI elements that are appearing (that is the active windows
+    // in their final orientation).
+
+    // The starting animation for the exiting and entering elements.  This
+    // animation applies a transformation while the rotation is in progress.
+    // It is started immediately, before the new entering UI is ready.
+    Animation mStartExitAnimation;
+    final Transformation mStartExitTransformation = new Transformation();
+    Animation mStartEnterAnimation;
+    final Transformation mStartEnterTransformation = new Transformation();
+
+    // The finishing animation for the exiting and entering elements.  This
+    // animation needs to undo the transformation of the starting animation.
+    // It starts running once the new rotation UI elements are ready to be
+    // displayed.
+    Animation mFinishExitAnimation;
+    final Transformation mFinishExitTransformation = new Transformation();
+    Animation mFinishEnterAnimation;
+    final Transformation mFinishEnterTransformation = new Transformation();
+
+    // The current active animation to move from the old to the new rotated
+    // state.  Which animation is run here will depend on the old and new
+    // rotations.
+    Animation mRotateExitAnimation;
+    final Transformation mRotateExitTransformation = new Transformation();
+    Animation mRotateEnterAnimation;
+    final Transformation mRotateEnterTransformation = new Transformation();
+
+    // A previously running rotate animation.  This will be used if we need
+    // to switch to a new rotation before finishing the previous one.
+    Animation mLastRotateExitAnimation;
+    final Transformation mLastRotateExitTransformation = new Transformation();
+    Animation mLastRotateEnterAnimation;
+    final Transformation mLastRotateEnterTransformation = new Transformation();
+
+    // Complete transformations being applied.
     final Transformation mExitTransformation = new Transformation();
-    Animation mEnterAnimation;
     final Transformation mEnterTransformation = new Transformation();
+
     boolean mStarted;
+    boolean mAnimRunning;
+    boolean mFinishAnimReady;
+    long mFinishAnimStartTime;
 
     final Matrix mSnapshotInitialMatrix = new Matrix();
     final Matrix mSnapshotFinalMatrix = new Matrix();
@@ -133,7 +169,7 @@
                     mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
                     mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
             mSurface.setAlpha(alpha);
-            if (DEBUG) {
+            if (DEBUG_TRANSFORMS) {
                 float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
                 float[] dstPnts = new float[4];
                 matrix.mapPoints(dstPnts, srcPnts);
@@ -167,7 +203,7 @@
     }
 
     // Must be called while in a transaction.
-    public void setRotation(int rotation) {
+    private void setRotation(int rotation) {
         mCurRotation = rotation;
 
         // Compute the transformation matrix that must be applied
@@ -176,46 +212,78 @@
         int delta = deltaRotation(rotation, mSnapshotRotation);
         createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
 
-        if (DEBUG) Slog.v(TAG, "**** ROTATION: " + delta);
+        if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
         setSnapshotTransform(mSnapshotInitialMatrix, 1.0f);
     }
 
+    // Must be called while in a transaction.
+    public boolean setRotation(int rotation, SurfaceSession session,
+            long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) {
+        setRotation(rotation);
+        return startAnimation(session, maxAnimationDuration, animationScale,
+                finalWidth, finalHeight, false);
+    }
+
     /**
      * Returns true if animating.
      */
-    public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
-            float animationScale, int finalWidth, int finalHeight) {
+    private boolean startAnimation(SurfaceSession session, long maxAnimationDuration,
+            float animationScale, int finalWidth, int finalHeight, boolean dismissing) {
         if (mSurface == null) {
             // Can't do animation.
             return false;
         }
+        if (mStarted) {
+            return true;
+        }
+
+        mStarted = true;
+
+        boolean firstStart = false;
 
         // Figure out how the screen has moved from the original rotation.
         int delta = deltaRotation(mCurRotation, mOriginalRotation);
 
+        if (mFinishExitAnimation == null && (!dismissing || delta != Surface.ROTATION_0)) {
+            if (DEBUG_STATE) Slog.v(TAG, "Creating start and finish animations");
+            firstStart = true;
+            mStartExitAnimation = AnimationUtils.loadAnimation(mContext,
+                    com.android.internal.R.anim.screen_rotate_start_exit);
+            mStartEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                    com.android.internal.R.anim.screen_rotate_start_enter);
+            mFinishExitAnimation = AnimationUtils.loadAnimation(mContext,
+                    com.android.internal.R.anim.screen_rotate_finish_exit);
+            mFinishEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                    com.android.internal.R.anim.screen_rotate_finish_enter);
+        }
+
+        if (DEBUG_STATE) Slog.v(TAG, "Rotation delta: " + delta + " finalWidth="
+                + finalWidth + " finalHeight=" + finalHeight
+                + " origWidth=" + mOriginalWidth + " origHeight=" + mOriginalHeight);
+
         switch (delta) {
             case Surface.ROTATION_0:
-                mExitAnimation = AnimationUtils.loadAnimation(mContext,
+                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_0_exit);
-                mEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_0_enter);
                 break;
             case Surface.ROTATION_90:
-                mExitAnimation = AnimationUtils.loadAnimation(mContext,
+                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_plus_90_exit);
-                mEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_plus_90_enter);
                 break;
             case Surface.ROTATION_180:
-                mExitAnimation = AnimationUtils.loadAnimation(mContext,
+                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_180_exit);
-                mEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_180_enter);
                 break;
             case Surface.ROTATION_270:
-                mExitAnimation = AnimationUtils.loadAnimation(mContext,
+                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_minus_90_exit);
-                mEnterAnimation = AnimationUtils.loadAnimation(mContext,
+                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_minus_90_enter);
                 break;
         }
@@ -224,35 +292,85 @@
         // means to allow supplying the last and next size.  In this definition
         // "%p" is the original (let's call it "previous") size, and "%" is the
         // screen's current/new size.
-        mEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
-        mExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
-        mStarted = false;
+        if (firstStart) {
+            if (DEBUG_STATE) Slog.v(TAG, "Initializing start and finish animations");
+            mStartEnterAnimation.initialize(finalWidth, finalHeight,
+                    mOriginalWidth, mOriginalHeight);
+            mStartExitAnimation.initialize(finalWidth, finalHeight,
+                    mOriginalWidth, mOriginalHeight);
+            mFinishEnterAnimation.initialize(finalWidth, finalHeight,
+                    mOriginalWidth, mOriginalHeight);
+            mFinishExitAnimation.initialize(finalWidth, finalHeight,
+                    mOriginalWidth, mOriginalHeight);
+        }
+        mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
+        mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
+        mAnimRunning = false;
+        mFinishAnimReady = false;
+        mFinishAnimStartTime = -1;
 
-        mExitAnimation.restrictDuration(maxAnimationDuration);
-        mExitAnimation.scaleCurrentDuration(animationScale);
-        mEnterAnimation.restrictDuration(maxAnimationDuration);
-        mEnterAnimation.scaleCurrentDuration(animationScale);
+        if (firstStart) {
+            mStartExitAnimation.restrictDuration(maxAnimationDuration);
+            mStartExitAnimation.scaleCurrentDuration(animationScale);
+            mStartEnterAnimation.restrictDuration(maxAnimationDuration);
+            mStartEnterAnimation.scaleCurrentDuration(animationScale);
+            mFinishExitAnimation.restrictDuration(maxAnimationDuration);
+            mFinishExitAnimation.scaleCurrentDuration(animationScale);
+            mFinishEnterAnimation.restrictDuration(maxAnimationDuration);
+            mFinishEnterAnimation.scaleCurrentDuration(animationScale);
+        }
+        mRotateExitAnimation.restrictDuration(maxAnimationDuration);
+        mRotateExitAnimation.scaleCurrentDuration(animationScale);
+        mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
+        mRotateEnterAnimation.scaleCurrentDuration(animationScale);
 
-        if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
-                ">>> OPEN TRANSACTION ScreenRotationAnimation.dismiss");
-        Surface.openTransaction();
+        if (mBlackFrame == null) {
+            if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+                    WindowManagerService.TAG,
+                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
+            Surface.openTransaction();
 
-        try {
-            Rect outer = new Rect(-finalWidth, -finalHeight, finalWidth * 2, finalHeight * 2);
-            Rect inner = new Rect(0, 0, finalWidth, finalHeight);
-            mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
-        } catch (Surface.OutOfResourcesException e) {
-            Slog.w(TAG, "Unable to allocate black surface", e);
-        } finally {
-            Surface.closeTransaction();
-            if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
-                    "<<< CLOSE TRANSACTION ScreenRotationAnimation.dismiss");
+            try {
+                Rect outer = new Rect(-finalWidth*1, -finalHeight*1, finalWidth*2, finalHeight*2);
+                Rect inner = new Rect(0, 0, finalWidth, finalHeight);
+                mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
+            } catch (Surface.OutOfResourcesException e) {
+                Slog.w(TAG, "Unable to allocate black surface", e);
+            } finally {
+                Surface.closeTransaction();
+                if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+                        WindowManagerService.TAG,
+                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
+            }
         }
 
         return true;
     }
 
+    /**
+     * Returns true if animating.
+     */
+    public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
+            float animationScale, int finalWidth, int finalHeight) {
+        if (DEBUG_STATE) Slog.v(TAG, "Dismiss!");
+        if (mSurface == null) {
+            // Can't do animation.
+            return false;
+        }
+        if (!mStarted) {
+            startAnimation(session, maxAnimationDuration, animationScale, finalWidth, finalHeight,
+                    true);
+        }
+        if (!mStarted) {
+            return false;
+        }
+        if (DEBUG_STATE) Slog.v(TAG, "Setting mFinishAnimReady = true");
+        mFinishAnimReady = true;
+        return true;
+    }
+
     public void kill() {
+        if (DEBUG_STATE) Slog.v(TAG, "Kill!");
         if (mSurface != null) {
             if (WindowManagerService.SHOW_TRANSACTIONS ||
                     WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
@@ -262,74 +380,198 @@
         }
         if (mBlackFrame != null) {
             mBlackFrame.kill();
+            mBlackFrame = null;
         }
-        if (mExitAnimation != null) {
-            mExitAnimation.cancel();
-            mExitAnimation = null;
+        if (mStartExitAnimation != null) {
+            mStartExitAnimation.cancel();
+            mStartExitAnimation = null;
         }
-        if (mEnterAnimation != null) {
-            mEnterAnimation.cancel();
-            mEnterAnimation = null;
+        if (mStartEnterAnimation != null) {
+            mStartEnterAnimation.cancel();
+            mStartEnterAnimation = null;
+        }
+        if (mFinishExitAnimation != null) {
+            mFinishExitAnimation.cancel();
+            mFinishExitAnimation = null;
+        }
+        if (mStartEnterAnimation != null) {
+            mStartEnterAnimation.cancel();
+            mStartEnterAnimation = null;
+        }
+        if (mRotateExitAnimation != null) {
+            mRotateExitAnimation.cancel();
+            mRotateExitAnimation = null;
+        }
+        if (mRotateEnterAnimation != null) {
+            mRotateEnterAnimation.cancel();
+            mRotateEnterAnimation = null;
         }
     }
 
     public boolean isAnimating() {
-        return mEnterAnimation != null || mExitAnimation != null;
+        return mStartEnterAnimation != null || mStartExitAnimation != null
+                && mFinishEnterAnimation != null || mFinishExitAnimation != null
+                && mRotateEnterAnimation != null || mRotateExitAnimation != null;
     }
 
     public boolean stepAnimation(long now) {
-        if (mEnterAnimation == null && mExitAnimation == null) {
+        if (!isAnimating()) {
+            if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
             return false;
         }
 
-        if (!mStarted) {
-            if (mEnterAnimation != null) {
-                mEnterAnimation.setStartTime(now);
+        if (!mAnimRunning) {
+            if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate");
+            if (mStartEnterAnimation != null) {
+                mStartEnterAnimation.setStartTime(now);
             }
-            if (mExitAnimation != null) {
-                mExitAnimation.setStartTime(now);
+            if (mStartExitAnimation != null) {
+                mStartExitAnimation.setStartTime(now);
             }
-            mStarted = true;
+            if (mFinishEnterAnimation != null) {
+                mFinishEnterAnimation.setStartTime(0);
+            }
+            if (mFinishExitAnimation != null) {
+                mFinishExitAnimation.setStartTime(0);
+            }
+            if (mRotateEnterAnimation != null) {
+                mRotateEnterAnimation.setStartTime(now);
+            }
+            if (mRotateExitAnimation != null) {
+                mRotateExitAnimation.setStartTime(now);
+            }
+            mAnimRunning = true;
         }
 
-        mExitTransformation.clear();
-        boolean moreExit = false;
-        if (mExitAnimation != null) {
-            moreExit = mExitAnimation.getTransformation(now, mExitTransformation);
-            if (DEBUG) Slog.v(TAG, "Stepped exit: " + mExitTransformation);
-            if (!moreExit) {
-                if (DEBUG) Slog.v(TAG, "Exit animation done!");
-                mExitAnimation.cancel();
-                mExitAnimation = null;
-                mExitTransformation.clear();
-                if (mSurface != null) {
-                    mSurface.hide();
-                }
+        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;
             }
         }
 
-        mEnterTransformation.clear();
-        boolean moreEnter = false;
-        if (mEnterAnimation != null) {
-            moreEnter = mEnterAnimation.getTransformation(now, mEnterTransformation);
-            if (!moreEnter) {
-                mEnterAnimation.cancel();
-                mEnterAnimation = null;
-                mEnterTransformation.clear();
-                if (mBlackFrame != null) {
-                    mBlackFrame.hide();
-                }
-            } else {
-                if (mBlackFrame != null) {
-                    mBlackFrame.setMatrix(mEnterTransformation.getMatrix());
-                }
+        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());
 
-        return moreEnter || moreExit;
+        final boolean more = moreStartEnter || moreStartExit || moreFinishEnter || moreFinishExit
+                || moreRotateEnter || moreRotateExit || !mFinishAnimReady;
+
+        if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
+
+        return more;
     }
 
     public Transformation getEnterTransformation() {