Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.wm;
     18 
     19 import java.io.PrintWriter;
     20 
     21 import static com.android.server.wm.WindowStateAnimator.SurfaceTrace;
     22 
     23 import android.content.Context;
     24 import android.graphics.Matrix;
     25 import android.graphics.PixelFormat;
     26 import android.graphics.Rect;
     27 import android.util.Slog;
     28 import android.view.Display;
     29 import android.view.DisplayInfo;
     30 import android.view.Surface.OutOfResourcesException;
     31 import android.view.Surface;
     32 import android.view.SurfaceControl;
     33 import android.view.SurfaceSession;
     34 import android.view.animation.Animation;
     35 import android.view.animation.AnimationUtils;
     36 import android.view.animation.Transformation;
     37 
     38 class ScreenRotationAnimation {
     39     static final String TAG = "ScreenRotationAnimation";
     40     static final boolean DEBUG_STATE = false;
     41     static final boolean DEBUG_TRANSFORMS = false;
     42     static final boolean TWO_PHASE_ANIMATION = false;
     43     static final boolean USE_CUSTOM_BLACK_FRAME = false;
     44 
     45     static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
     46 
     47     final Context mContext;
     48     final DisplayContent mDisplayContent;
     49     SurfaceControl mSurfaceControl;
     50     BlackFrame mCustomBlackFrame;
     51     BlackFrame mExitingBlackFrame;
     52     BlackFrame mEnteringBlackFrame;
     53     int mWidth, mHeight;
     54 
     55     int mOriginalRotation;
     56     int mOriginalWidth, mOriginalHeight;
     57     int mCurRotation;
     58     Rect mOriginalDisplayRect = new Rect();
     59     Rect mCurrentDisplayRect = new Rect();
     60 
     61     // For all animations, "exit" is for the UI elements that are going
     62     // away (that is the snapshot of the old screen), and "enter" is for
     63     // the new UI elements that are appearing (that is the active windows
     64     // in their final orientation).
     65 
     66     // The starting animation for the exiting and entering elements.  This
     67     // animation applies a transformation while the rotation is in progress.
     68     // It is started immediately, before the new entering UI is ready.
     69     Animation mStartExitAnimation;
     70     final Transformation mStartExitTransformation = new Transformation();
     71     Animation mStartEnterAnimation;
     72     final Transformation mStartEnterTransformation = new Transformation();
     73     Animation mStartFrameAnimation;
     74     final Transformation mStartFrameTransformation = new Transformation();
     75 
     76     // The finishing animation for the exiting and entering elements.  This
     77     // animation needs to undo the transformation of the starting animation.
     78     // It starts running once the new rotation UI elements are ready to be
     79     // displayed.
     80     Animation mFinishExitAnimation;
     81     final Transformation mFinishExitTransformation = new Transformation();
     82     Animation mFinishEnterAnimation;
     83     final Transformation mFinishEnterTransformation = new Transformation();
     84     Animation mFinishFrameAnimation;
     85     final Transformation mFinishFrameTransformation = new Transformation();
     86 
     87     // The current active animation to move from the old to the new rotated
     88     // state.  Which animation is run here will depend on the old and new
     89     // rotations.
     90     Animation mRotateExitAnimation;
     91     final Transformation mRotateExitTransformation = new Transformation();
     92     Animation mRotateEnterAnimation;
     93     final Transformation mRotateEnterTransformation = new Transformation();
     94     Animation mRotateFrameAnimation;
     95     final Transformation mRotateFrameTransformation = new Transformation();
     96 
     97     // A previously running rotate animation.  This will be used if we need
     98     // to switch to a new rotation before finishing the previous one.
     99     Animation mLastRotateExitAnimation;
    100     final Transformation mLastRotateExitTransformation = new Transformation();
    101     Animation mLastRotateEnterAnimation;
    102     final Transformation mLastRotateEnterTransformation = new Transformation();
    103     Animation mLastRotateFrameAnimation;
    104     final Transformation mLastRotateFrameTransformation = new Transformation();
    105 
    106     // Complete transformations being applied.
    107     final Transformation mExitTransformation = new Transformation();
    108     final Transformation mEnterTransformation = new Transformation();
    109     final Transformation mFrameTransformation = new Transformation();
    110 
    111     boolean mStarted;
    112     boolean mAnimRunning;
    113     boolean mFinishAnimReady;
    114     long mFinishAnimStartTime;
    115     boolean mForceDefaultOrientation;
    116 
    117     final Matrix mFrameInitialMatrix = new Matrix();
    118     final Matrix mSnapshotInitialMatrix = new Matrix();
    119     final Matrix mSnapshotFinalMatrix = new Matrix();
    120     final Matrix mExitFrameFinalMatrix = new Matrix();
    121     final Matrix mTmpMatrix = new Matrix();
    122     final float[] mTmpFloats = new float[9];
    123     private boolean mMoreRotateEnter;
    124     private boolean mMoreRotateExit;
    125     private boolean mMoreRotateFrame;
    126     private boolean mMoreFinishEnter;
    127     private boolean mMoreFinishExit;
    128     private boolean mMoreFinishFrame;
    129     private boolean mMoreStartEnter;
    130     private boolean mMoreStartExit;
    131     private boolean mMoreStartFrame;
    132     long mHalfwayPoint;
    133 
    134     public void printTo(String prefix, PrintWriter pw) {
    135         pw.print(prefix); pw.print("mSurface="); pw.print(mSurfaceControl);
    136                 pw.print(" mWidth="); pw.print(mWidth);
    137                 pw.print(" mHeight="); pw.println(mHeight);
    138         if (USE_CUSTOM_BLACK_FRAME) {
    139             pw.print(prefix); pw.print("mCustomBlackFrame="); pw.println(mCustomBlackFrame);
    140             if (mCustomBlackFrame != null) {
    141                 mCustomBlackFrame.printTo(prefix + "  ", pw);
    142             }
    143         }
    144         pw.print(prefix); pw.print("mExitingBlackFrame="); pw.println(mExitingBlackFrame);
    145         if (mExitingBlackFrame != null) {
    146             mExitingBlackFrame.printTo(prefix + "  ", pw);
    147         }
    148         pw.print(prefix); pw.print("mEnteringBlackFrame="); pw.println(mEnteringBlackFrame);
    149         if (mEnteringBlackFrame != null) {
    150             mEnteringBlackFrame.printTo(prefix + "  ", pw);
    151         }
    152         pw.print(prefix); pw.print("mCurRotation="); pw.print(mCurRotation);
    153                 pw.print(" mOriginalRotation="); pw.println(mOriginalRotation);
    154         pw.print(prefix); pw.print("mOriginalWidth="); pw.print(mOriginalWidth);
    155                 pw.print(" mOriginalHeight="); pw.println(mOriginalHeight);
    156         pw.print(prefix); pw.print("mStarted="); pw.print(mStarted);
    157                 pw.print(" mAnimRunning="); pw.print(mAnimRunning);
    158                 pw.print(" mFinishAnimReady="); pw.print(mFinishAnimReady);
    159                 pw.print(" mFinishAnimStartTime="); pw.println(mFinishAnimStartTime);
    160         pw.print(prefix); pw.print("mStartExitAnimation="); pw.print(mStartExitAnimation);
    161                 pw.print(" "); mStartExitTransformation.printShortString(pw); pw.println();
    162         pw.print(prefix); pw.print("mStartEnterAnimation="); pw.print(mStartEnterAnimation);
    163                 pw.print(" "); mStartEnterTransformation.printShortString(pw); pw.println();
    164         pw.print(prefix); pw.print("mStartFrameAnimation="); pw.print(mStartFrameAnimation);
    165                 pw.print(" "); mStartFrameTransformation.printShortString(pw); pw.println();
    166         pw.print(prefix); pw.print("mFinishExitAnimation="); pw.print(mFinishExitAnimation);
    167                 pw.print(" "); mFinishExitTransformation.printShortString(pw); pw.println();
    168         pw.print(prefix); pw.print("mFinishEnterAnimation="); pw.print(mFinishEnterAnimation);
    169                 pw.print(" "); mFinishEnterTransformation.printShortString(pw); pw.println();
    170         pw.print(prefix); pw.print("mFinishFrameAnimation="); pw.print(mFinishFrameAnimation);
    171                 pw.print(" "); mFinishFrameTransformation.printShortString(pw); pw.println();
    172         pw.print(prefix); pw.print("mRotateExitAnimation="); pw.print(mRotateExitAnimation);
    173                 pw.print(" "); mRotateExitTransformation.printShortString(pw); pw.println();
    174         pw.print(prefix); pw.print("mRotateEnterAnimation="); pw.print(mRotateEnterAnimation);
    175                 pw.print(" "); mRotateEnterTransformation.printShortString(pw); pw.println();
    176         pw.print(prefix); pw.print("mRotateFrameAnimation="); pw.print(mRotateFrameAnimation);
    177                 pw.print(" "); mRotateFrameTransformation.printShortString(pw); pw.println();
    178         pw.print(prefix); pw.print("mExitTransformation=");
    179                 mExitTransformation.printShortString(pw); pw.println();
    180         pw.print(prefix); pw.print("mEnterTransformation=");
    181                 mEnterTransformation.printShortString(pw); pw.println();
    182         pw.print(prefix); pw.print("mFrameTransformation=");
    183                 mEnterTransformation.printShortString(pw); pw.println();
    184         pw.print(prefix); pw.print("mFrameInitialMatrix=");
    185                 mFrameInitialMatrix.printShortString(pw);
    186                 pw.println();
    187         pw.print(prefix); pw.print("mSnapshotInitialMatrix=");
    188                 mSnapshotInitialMatrix.printShortString(pw);
    189                 pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw);
    190                 pw.println();
    191         pw.print(prefix); pw.print("mExitFrameFinalMatrix=");
    192                 mExitFrameFinalMatrix.printShortString(pw);
    193                 pw.println();
    194         pw.print(prefix); pw.print("mForceDefaultOrientation="); pw.print(mForceDefaultOrientation);
    195         if (mForceDefaultOrientation) {
    196             pw.print(" mOriginalDisplayRect="); pw.print(mOriginalDisplayRect.toShortString());
    197             pw.print(" mCurrentDisplayRect="); pw.println(mCurrentDisplayRect.toShortString());
    198         }
    199     }
    200 
    201     public ScreenRotationAnimation(Context context, DisplayContent displayContent,
    202             SurfaceSession session, boolean inTransaction, boolean forceDefaultOrientation,
    203             boolean isSecure) {
    204         mContext = context;
    205         mDisplayContent = displayContent;
    206         displayContent.getLogicalDisplayRect(mOriginalDisplayRect);
    207 
    208         // Screenshot does NOT include rotation!
    209         final Display display = displayContent.getDisplay();
    210         int originalRotation = display.getRotation();
    211         final int originalWidth;
    212         final int originalHeight;
    213         DisplayInfo displayInfo = displayContent.getDisplayInfo();
    214         if (forceDefaultOrientation) {
    215             // Emulated orientation.
    216             mForceDefaultOrientation = true;
    217             originalWidth = displayContent.mBaseDisplayWidth;
    218             originalHeight = displayContent.mBaseDisplayHeight;
    219         } else {
    220             // Normal situation
    221             originalWidth = displayInfo.logicalWidth;
    222             originalHeight = displayInfo.logicalHeight;
    223         }
    224         if (originalRotation == Surface.ROTATION_90
    225                 || originalRotation == Surface.ROTATION_270) {
    226             mWidth = originalHeight;
    227             mHeight = originalWidth;
    228         } else {
    229             mWidth = originalWidth;
    230             mHeight = originalHeight;
    231         }
    232 
    233         mOriginalRotation = originalRotation;
    234         mOriginalWidth = originalWidth;
    235         mOriginalHeight = originalHeight;
    236 
    237         if (!inTransaction) {
    238             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
    239                     ">>> OPEN TRANSACTION ScreenRotationAnimation");
    240             SurfaceControl.openTransaction();
    241         }
    242 
    243         try {
    244             try {
    245                 int flags = SurfaceControl.HIDDEN;
    246                 if (isSecure) {
    247                     flags |= SurfaceControl.SECURE;
    248                 }
    249 
    250                 if (WindowManagerService.DEBUG_SURFACE_TRACE) {
    251                     mSurfaceControl = new SurfaceTrace(session, "ScreenshotSurface",
    252                             mWidth, mHeight,
    253                             PixelFormat.OPAQUE, flags);
    254                     Slog.w(TAG, "ScreenRotationAnimation ctor: displayOffset="
    255                             + mOriginalDisplayRect.toShortString());
    256                 } else {
    257                     mSurfaceControl = new SurfaceControl(session, "ScreenshotSurface",
    258                             mWidth, mHeight,
    259                             PixelFormat.OPAQUE, flags);
    260                 }
    261                 // capture a screenshot into the surface we just created
    262                 Surface sur = new Surface();
    263                 sur.copyFrom(mSurfaceControl);
    264                 // FIXME: we should use the proper display
    265                 SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
    266                         SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur);
    267                 mSurfaceControl.setLayerStack(display.getLayerStack());
    268                 mSurfaceControl.setLayer(FREEZE_LAYER + 1);
    269                 mSurfaceControl.setAlpha(0);
    270                 mSurfaceControl.show();
    271                 sur.destroy();
    272             } catch (OutOfResourcesException e) {
    273                 Slog.w(TAG, "Unable to allocate freeze surface", e);
    274             }
    275 
    276             if (WindowManagerService.SHOW_TRANSACTIONS ||
    277                     WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
    278                             "  FREEZE " + mSurfaceControl + ": CREATE");
    279 
    280             setRotationInTransaction(originalRotation);
    281         } finally {
    282             if (!inTransaction) {
    283                 SurfaceControl.closeTransaction();
    284                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
    285                         "<<< CLOSE TRANSACTION ScreenRotationAnimation");
    286             }
    287         }
    288     }
    289 
    290     boolean hasScreenshot() {
    291         return mSurfaceControl != null;
    292     }
    293 
    294     static int deltaRotation(int oldRotation, int newRotation) {
    295         int delta = newRotation - oldRotation;
    296         if (delta < 0) delta += 4;
    297         return delta;
    298     }
    299 
    300     private void setSnapshotTransformInTransaction(Matrix matrix, float alpha) {
    301         if (mSurfaceControl != null) {
    302             matrix.getValues(mTmpFloats);
    303             float x = mTmpFloats[Matrix.MTRANS_X];
    304             float y = mTmpFloats[Matrix.MTRANS_Y];
    305             if (mForceDefaultOrientation) {
    306                 mDisplayContent.getLogicalDisplayRect(mCurrentDisplayRect);
    307                 x -= mCurrentDisplayRect.left;
    308                 y -= mCurrentDisplayRect.top;
    309             }
    310             mSurfaceControl.setPosition(x, y);
    311             mSurfaceControl.setMatrix(
    312                     mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
    313                     mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
    314             mSurfaceControl.setAlpha(alpha);
    315             if (DEBUG_TRANSFORMS) {
    316                 float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
    317                 float[] dstPnts = new float[4];
    318                 matrix.mapPoints(dstPnts, srcPnts);
    319                 Slog.i(TAG, "Original  : (" + srcPnts[0] + "," + srcPnts[1]
    320                         + ")-(" + srcPnts[2] + "," + srcPnts[3] + ")");
    321                 Slog.i(TAG, "Transformed: (" + dstPnts[0] + "," + dstPnts[1]
    322                         + ")-(" + dstPnts[2] + "," + dstPnts[3] + ")");
    323             }
    324         }
    325     }
    326 
    327     public static void createRotationMatrix(int rotation, int width, int height,
    328             Matrix outMatrix) {
    329         switch (rotation) {
    330             case Surface.ROTATION_0:
    331                 outMatrix.reset();
    332                 break;
    333             case Surface.ROTATION_90:
    334                 outMatrix.setRotate(90, 0, 0);
    335                 outMatrix.postTranslate(height, 0);
    336                 break;
    337             case Surface.ROTATION_180:
    338                 outMatrix.setRotate(180, 0, 0);
    339                 outMatrix.postTranslate(width, height);
    340                 break;
    341             case Surface.ROTATION_270:
    342                 outMatrix.setRotate(270, 0, 0);
    343                 outMatrix.postTranslate(0, width);
    344                 break;
    345         }
    346     }
    347 
    348     // Must be called while in a transaction.
    349     private void setRotationInTransaction(int rotation) {
    350         mCurRotation = rotation;
    351 
    352         // Compute the transformation matrix that must be applied
    353         // to the snapshot to make it stay in the same original position
    354         // with the current screen rotation.
    355         int delta = deltaRotation(rotation, Surface.ROTATION_0);
    356         createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
    357 
    358         if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
    359         setSnapshotTransformInTransaction(mSnapshotInitialMatrix, 1.0f);
    360     }
    361 
    362     // Must be called while in a transaction.
    363     public boolean setRotationInTransaction(int rotation, SurfaceSession session,
    364             long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) {
    365         setRotationInTransaction(rotation);
    366         if (TWO_PHASE_ANIMATION) {
    367             return startAnimation(session, maxAnimationDuration, animationScale,
    368                     finalWidth, finalHeight, false, 0, 0);
    369         }
    370 
    371         // Don't start animation yet.
    372         return false;
    373     }
    374 
    375     /**
    376      * Returns true if animating.
    377      */
    378     private boolean startAnimation(SurfaceSession session, long maxAnimationDuration,
    379             float animationScale, int finalWidth, int finalHeight, boolean dismissing,
    380             int exitAnim, int enterAnim) {
    381         if (mSurfaceControl == null) {
    382             // Can't do animation.
    383             return false;
    384         }
    385         if (mStarted) {
    386             return true;
    387         }
    388 
    389         mStarted = true;
    390 
    391         boolean firstStart = false;
    392 
    393         // Figure out how the screen has moved from the original rotation.
    394         int delta = deltaRotation(mCurRotation, mOriginalRotation);
    395 
    396         if (TWO_PHASE_ANIMATION && mFinishExitAnimation == null
    397                 && (!dismissing || delta != Surface.ROTATION_0)) {
    398             if (DEBUG_STATE) Slog.v(TAG, "Creating start and finish animations");
    399             firstStart = true;
    400             mStartExitAnimation = AnimationUtils.loadAnimation(mContext,
    401                     com.android.internal.R.anim.screen_rotate_start_exit);
    402             mStartEnterAnimation = AnimationUtils.loadAnimation(mContext,
    403                     com.android.internal.R.anim.screen_rotate_start_enter);
    404             if (USE_CUSTOM_BLACK_FRAME) {
    405                 mStartFrameAnimation = AnimationUtils.loadAnimation(mContext,
    406                         com.android.internal.R.anim.screen_rotate_start_frame);
    407             }
    408             mFinishExitAnimation = AnimationUtils.loadAnimation(mContext,
    409                     com.android.internal.R.anim.screen_rotate_finish_exit);
    410             mFinishEnterAnimation = AnimationUtils.loadAnimation(mContext,
    411                     com.android.internal.R.anim.screen_rotate_finish_enter);
    412             if (USE_CUSTOM_BLACK_FRAME) {
    413                 mFinishFrameAnimation = AnimationUtils.loadAnimation(mContext,
    414                         com.android.internal.R.anim.screen_rotate_finish_frame);
    415             }
    416         }
    417 
    418         if (DEBUG_STATE) Slog.v(TAG, "Rotation delta: " + delta + " finalWidth="
    419                 + finalWidth + " finalHeight=" + finalHeight
    420                 + " origWidth=" + mOriginalWidth + " origHeight=" + mOriginalHeight);
    421 
    422         final boolean customAnim;
    423         if (exitAnim != 0 && enterAnim != 0) {
    424             customAnim = true;
    425             mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, exitAnim);
    426             mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, enterAnim);
    427         } else {
    428             customAnim = false;
    429             switch (delta) {
    430                 case Surface.ROTATION_0:
    431                     mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
    432                             com.android.internal.R.anim.screen_rotate_0_exit);
    433                     mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
    434                             com.android.internal.R.anim.screen_rotate_0_enter);
    435                     if (USE_CUSTOM_BLACK_FRAME) {
    436                         mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
    437                                 com.android.internal.R.anim.screen_rotate_0_frame);
    438                     }
    439                     break;
    440                 case Surface.ROTATION_90:
    441                     mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
    442                             com.android.internal.R.anim.screen_rotate_plus_90_exit);
    443                     mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
    444                             com.android.internal.R.anim.screen_rotate_plus_90_enter);
    445                     if (USE_CUSTOM_BLACK_FRAME) {
    446                         mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
    447                                 com.android.internal.R.anim.screen_rotate_plus_90_frame);
    448                     }
    449                     break;
    450                 case Surface.ROTATION_180:
    451                     mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
    452                             com.android.internal.R.anim.screen_rotate_180_exit);
    453                     mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
    454                             com.android.internal.R.anim.screen_rotate_180_enter);
    455                     if (USE_CUSTOM_BLACK_FRAME) {
    456                         mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
    457                                 com.android.internal.R.anim.screen_rotate_180_frame);
    458                     }
    459                     break;
    460                 case Surface.ROTATION_270:
    461                     mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
    462                             com.android.internal.R.anim.screen_rotate_minus_90_exit);
    463                     mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
    464                             com.android.internal.R.anim.screen_rotate_minus_90_enter);
    465                     if (USE_CUSTOM_BLACK_FRAME) {
    466                         mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
    467                                 com.android.internal.R.anim.screen_rotate_minus_90_frame);
    468                     }
    469                     break;
    470             }
    471         }
    472 
    473         // Initialize the animations.  This is a hack, redefining what "parent"
    474         // means to allow supplying the last and next size.  In this definition
    475         // "%p" is the original (let's call it "previous") size, and "%" is the
    476         // screen's current/new size.
    477         if (TWO_PHASE_ANIMATION && firstStart) {
    478             // Compute partial steps between original and final sizes.  These
    479             // are used for the dimensions of the exiting and entering elements,
    480             // so they are never stretched too significantly.
    481             final int halfWidth = (finalWidth + mOriginalWidth) / 2;
    482             final int halfHeight = (finalHeight + mOriginalHeight) / 2;
    483 
    484             if (DEBUG_STATE) Slog.v(TAG, "Initializing start and finish animations");
    485             mStartEnterAnimation.initialize(finalWidth, finalHeight,
    486                     halfWidth, halfHeight);
    487             mStartExitAnimation.initialize(halfWidth, halfHeight,
    488                     mOriginalWidth, mOriginalHeight);
    489             mFinishEnterAnimation.initialize(finalWidth, finalHeight,
    490                     halfWidth, halfHeight);
    491             mFinishExitAnimation.initialize(halfWidth, halfHeight,
    492                     mOriginalWidth, mOriginalHeight);
    493             if (USE_CUSTOM_BLACK_FRAME) {
    494                 mStartFrameAnimation.initialize(finalWidth, finalHeight,
    495                         mOriginalWidth, mOriginalHeight);
    496                 mFinishFrameAnimation.initialize(finalWidth, finalHeight,
    497                         mOriginalWidth, mOriginalHeight);
    498             }
    499         }
    500         mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
    501         mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
    502         if (USE_CUSTOM_BLACK_FRAME) {
    503             mRotateFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth,
    504                     mOriginalHeight);
    505         }
    506         mAnimRunning = false;
    507         mFinishAnimReady = false;
    508         mFinishAnimStartTime = -1;
    509 
    510         if (TWO_PHASE_ANIMATION && firstStart) {
    511             mStartExitAnimation.restrictDuration(maxAnimationDuration);
    512             mStartExitAnimation.scaleCurrentDuration(animationScale);
    513             mStartEnterAnimation.restrictDuration(maxAnimationDuration);
    514             mStartEnterAnimation.scaleCurrentDuration(animationScale);
    515             mFinishExitAnimation.restrictDuration(maxAnimationDuration);
    516             mFinishExitAnimation.scaleCurrentDuration(animationScale);
    517             mFinishEnterAnimation.restrictDuration(maxAnimationDuration);
    518             mFinishEnterAnimation.scaleCurrentDuration(animationScale);
    519             if (USE_CUSTOM_BLACK_FRAME) {
    520                 mStartFrameAnimation.restrictDuration(maxAnimationDuration);
    521                 mStartFrameAnimation.scaleCurrentDuration(animationScale);
    522                 mFinishFrameAnimation.restrictDuration(maxAnimationDuration);
    523                 mFinishFrameAnimation.scaleCurrentDuration(animationScale);
    524             }
    525         }
    526         mRotateExitAnimation.restrictDuration(maxAnimationDuration);
    527         mRotateExitAnimation.scaleCurrentDuration(animationScale);
    528         mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
    529         mRotateEnterAnimation.scaleCurrentDuration(animationScale);
    530         if (USE_CUSTOM_BLACK_FRAME) {
    531             mRotateFrameAnimation.restrictDuration(maxAnimationDuration);
    532             mRotateFrameAnimation.scaleCurrentDuration(animationScale);
    533         }
    534 
    535         final int layerStack = mDisplayContent.getDisplay().getLayerStack();
    536         if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) {
    537             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
    538                     WindowManagerService.TAG,
    539                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
    540             SurfaceControl.openTransaction();
    541 
    542             // Compute the transformation matrix that must be applied
    543             // the the black frame to make it stay in the initial position
    544             // before the new screen rotation.  This is different than the
    545             // snapshot transformation because the snapshot is always based
    546             // of the native orientation of the screen, not the orientation
    547             // we were last in.
    548             createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);
    549 
    550             try {
    551                 Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
    552                         mOriginalWidth*2, mOriginalHeight*2);
    553                 Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
    554                 mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3,
    555                         layerStack, false);
    556                 mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
    557             } catch (OutOfResourcesException e) {
    558                 Slog.w(TAG, "Unable to allocate black surface", e);
    559             } finally {
    560                 SurfaceControl.closeTransaction();
    561                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
    562                         WindowManagerService.TAG,
    563                         "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
    564             }
    565         }
    566 
    567         if (!customAnim && mExitingBlackFrame == null) {
    568             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
    569                     WindowManagerService.TAG,
    570                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
    571             SurfaceControl.openTransaction();
    572             try {
    573                 // Compute the transformation matrix that must be applied
    574                 // the the black frame to make it stay in the initial position
    575                 // before the new screen rotation.  This is different than the
    576                 // snapshot transformation because the snapshot is always based
    577                 // of the native orientation of the screen, not the orientation
    578                 // we were last in.
    579                 createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);
    580 
    581                 final Rect outer;
    582                 final Rect inner;
    583                 if (mForceDefaultOrientation) {
    584                     // Going from a smaller Display to a larger Display, add curtains to sides
    585                     // or top and bottom. Going from a larger to smaller display will result in
    586                     // no BlackSurfaces being constructed.
    587                     outer = mCurrentDisplayRect;
    588                     inner = mOriginalDisplayRect;
    589                 } else {
    590                     outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
    591                             mOriginalWidth*2, mOriginalHeight*2);
    592                     inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
    593                 }
    594                 mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2,
    595                         layerStack, mForceDefaultOrientation);
    596                 mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
    597             } catch (OutOfResourcesException e) {
    598                 Slog.w(TAG, "Unable to allocate black surface", e);
    599             } finally {
    600                 SurfaceControl.closeTransaction();
    601                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
    602                         WindowManagerService.TAG,
    603                         "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
    604             }
    605         }
    606 
    607         if (customAnim && mEnteringBlackFrame == null) {
    608             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
    609                     WindowManagerService.TAG,
    610                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
    611             SurfaceControl.openTransaction();
    612 
    613             try {
    614                 Rect outer = new Rect(-finalWidth*1, -finalHeight*1,
    615                         finalWidth*2, finalHeight*2);
    616                 Rect inner = new Rect(0, 0, finalWidth, finalHeight);
    617                 mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER,
    618                         layerStack, false);
    619             } catch (OutOfResourcesException e) {
    620                 Slog.w(TAG, "Unable to allocate black surface", e);
    621             } finally {
    622                 SurfaceControl.closeTransaction();
    623                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
    624                         WindowManagerService.TAG,
    625                         "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
    626             }
    627         }
    628 
    629         return true;
    630     }
    631 
    632     /**
    633      * Returns true if animating.
    634      */
    635     public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
    636             float animationScale, int finalWidth, int finalHeight, int exitAnim, int enterAnim) {
    637         if (DEBUG_STATE) Slog.v(TAG, "Dismiss!");
    638         if (mSurfaceControl == null) {
    639             // Can't do animation.
    640             return false;
    641         }
    642         if (!mStarted) {
    643             startAnimation(session, maxAnimationDuration, animationScale, finalWidth, finalHeight,
    644                     true, exitAnim, enterAnim);
    645         }
    646         if (!mStarted) {
    647             return false;
    648         }
    649         if (DEBUG_STATE) Slog.v(TAG, "Setting mFinishAnimReady = true");
    650         mFinishAnimReady = true;
    651         return true;
    652     }
    653 
    654     public void kill() {
    655         if (DEBUG_STATE) Slog.v(TAG, "Kill!");
    656         if (mSurfaceControl != null) {
    657             if (WindowManagerService.SHOW_TRANSACTIONS ||
    658                     WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
    659                             "  FREEZE " + mSurfaceControl + ": DESTROY");
    660             mSurfaceControl.destroy();
    661             mSurfaceControl = null;
    662         }
    663         if (mCustomBlackFrame != null) {
    664             mCustomBlackFrame.kill();
    665             mCustomBlackFrame = null;
    666         }
    667         if (mExitingBlackFrame != null) {
    668             mExitingBlackFrame.kill();
    669             mExitingBlackFrame = null;
    670         }
    671         if (mEnteringBlackFrame != null) {
    672             mEnteringBlackFrame.kill();
    673             mEnteringBlackFrame = null;
    674         }
    675         if (TWO_PHASE_ANIMATION) {
    676             if (mStartExitAnimation != null) {
    677                 mStartExitAnimation.cancel();
    678                 mStartExitAnimation = null;
    679             }
    680             if (mStartEnterAnimation != null) {
    681                 mStartEnterAnimation.cancel();
    682                 mStartEnterAnimation = null;
    683             }
    684             if (mFinishExitAnimation != null) {
    685                 mFinishExitAnimation.cancel();
    686                 mFinishExitAnimation = null;
    687             }
    688             if (mFinishEnterAnimation != null) {
    689                 mFinishEnterAnimation.cancel();
    690                 mFinishEnterAnimation = null;
    691             }
    692         }
    693         if (USE_CUSTOM_BLACK_FRAME) {
    694             if (mStartFrameAnimation != null) {
    695                 mStartFrameAnimation.cancel();
    696                 mStartFrameAnimation = null;
    697             }
    698             if (mRotateFrameAnimation != null) {
    699                 mRotateFrameAnimation.cancel();
    700                 mRotateFrameAnimation = null;
    701             }
    702             if (mFinishFrameAnimation != null) {
    703                 mFinishFrameAnimation.cancel();
    704                 mFinishFrameAnimation = null;
    705             }
    706         }
    707         if (mRotateExitAnimation != null) {
    708             mRotateExitAnimation.cancel();
    709             mRotateExitAnimation = null;
    710         }
    711         if (mRotateEnterAnimation != null) {
    712             mRotateEnterAnimation.cancel();
    713             mRotateEnterAnimation = null;
    714         }
    715     }
    716 
    717     public boolean isAnimating() {
    718         return hasAnimations() || (TWO_PHASE_ANIMATION && mFinishAnimReady);
    719     }
    720 
    721     public boolean isRotating() {
    722         return mCurRotation != mOriginalRotation;
    723     }
    724 
    725     private boolean hasAnimations() {
    726         return (TWO_PHASE_ANIMATION &&
    727                     (mStartEnterAnimation != null || mStartExitAnimation != null
    728                     || mFinishEnterAnimation != null || mFinishExitAnimation != null))
    729                 || (USE_CUSTOM_BLACK_FRAME &&
    730                         (mStartFrameAnimation != null || mRotateFrameAnimation != null
    731                         || mFinishFrameAnimation != null))
    732                 || mRotateEnterAnimation != null || mRotateExitAnimation != null;
    733     }
    734 
    735     private boolean stepAnimation(long now) {
    736         if (now > mHalfwayPoint) {
    737             mHalfwayPoint = Long.MAX_VALUE;
    738         }
    739         if (mFinishAnimReady && mFinishAnimStartTime < 0) {
    740             if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
    741             mFinishAnimStartTime = now;
    742         }
    743 
    744         if (TWO_PHASE_ANIMATION) {
    745             mMoreStartExit = false;
    746             if (mStartExitAnimation != null) {
    747                 mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
    748                 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
    749             }
    750 
    751             mMoreStartEnter = false;
    752             if (mStartEnterAnimation != null) {
    753                 mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
    754                 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
    755             }
    756         }
    757         if (USE_CUSTOM_BLACK_FRAME) {
    758             mMoreStartFrame = false;
    759             if (mStartFrameAnimation != null) {
    760                 mMoreStartFrame = mStartFrameAnimation.getTransformation(now, mStartFrameTransformation);
    761                 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start frame: " + mStartFrameTransformation);
    762             }
    763         }
    764 
    765         long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0;
    766         if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);
    767 
    768         if (TWO_PHASE_ANIMATION) {
    769             mMoreFinishExit = false;
    770             if (mFinishExitAnimation != null) {
    771                 mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
    772                 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
    773             }
    774 
    775             mMoreFinishEnter = false;
    776             if (mFinishEnterAnimation != null) {
    777                 mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
    778                 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
    779             }
    780         }
    781         if (USE_CUSTOM_BLACK_FRAME) {
    782             mMoreFinishFrame = false;
    783             if (mFinishFrameAnimation != null) {
    784                 mMoreFinishFrame = mFinishFrameAnimation.getTransformation(finishNow, mFinishFrameTransformation);
    785                 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish frame: " + mFinishFrameTransformation);
    786             }
    787         }
    788 
    789         mMoreRotateExit = false;
    790         if (mRotateExitAnimation != null) {
    791             mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
    792             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
    793         }
    794 
    795         mMoreRotateEnter = false;
    796         if (mRotateEnterAnimation != null) {
    797             mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
    798             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
    799         }
    800 
    801         if (USE_CUSTOM_BLACK_FRAME) {
    802             mMoreRotateFrame = false;
    803             if (mRotateFrameAnimation != null) {
    804                 mMoreRotateFrame = mRotateFrameAnimation.getTransformation(now, mRotateFrameTransformation);
    805                 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate frame: " + mRotateFrameTransformation);
    806             }
    807         }
    808 
    809         if (!mMoreRotateExit && (!TWO_PHASE_ANIMATION || (!mMoreStartExit && !mMoreFinishExit))) {
    810             if (TWO_PHASE_ANIMATION) {
    811                 if (mStartExitAnimation != null) {
    812                     if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing start exit anim!");
    813                     mStartExitAnimation.cancel();
    814                     mStartExitAnimation = null;
    815                     mStartExitTransformation.clear();
    816                 }
    817                 if (mFinishExitAnimation != null) {
    818                     if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing finish exit anim!");
    819                     mFinishExitAnimation.cancel();
    820                     mFinishExitAnimation = null;
    821                     mFinishExitTransformation.clear();
    822                 }
    823             }
    824             if (mRotateExitAnimation != null) {
    825                 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing rotate exit anim!");
    826                 mRotateExitAnimation.cancel();
    827                 mRotateExitAnimation = null;
    828                 mRotateExitTransformation.clear();
    829             }
    830         }
    831 
    832         if (!mMoreRotateEnter && (!TWO_PHASE_ANIMATION || (!mMoreStartEnter && !mMoreFinishEnter))) {
    833             if (TWO_PHASE_ANIMATION) {
    834                 if (mStartEnterAnimation != null) {
    835                     if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing start enter anim!");
    836                     mStartEnterAnimation.cancel();
    837                     mStartEnterAnimation = null;
    838                     mStartEnterTransformation.clear();
    839                 }
    840                 if (mFinishEnterAnimation != null) {
    841                     if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing finish enter anim!");
    842                     mFinishEnterAnimation.cancel();
    843                     mFinishEnterAnimation = null;
    844                     mFinishEnterTransformation.clear();
    845                 }
    846             }
    847             if (mRotateEnterAnimation != null) {
    848                 if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing rotate enter anim!");
    849                 mRotateEnterAnimation.cancel();
    850                 mRotateEnterAnimation = null;
    851                 mRotateEnterTransformation.clear();
    852             }
    853         }
    854 
    855         if (USE_CUSTOM_BLACK_FRAME && !mMoreStartFrame && !mMoreRotateFrame && !mMoreFinishFrame) {
    856             if (mStartFrameAnimation != null) {
    857                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing start frame anim!");
    858                 mStartFrameAnimation.cancel();
    859                 mStartFrameAnimation = null;
    860                 mStartFrameTransformation.clear();
    861             }
    862             if (mFinishFrameAnimation != null) {
    863                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing finish frame anim!");
    864                 mFinishFrameAnimation.cancel();
    865                 mFinishFrameAnimation = null;
    866                 mFinishFrameTransformation.clear();
    867             }
    868             if (mRotateFrameAnimation != null) {
    869                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing rotate frame anim!");
    870                 mRotateFrameAnimation.cancel();
    871                 mRotateFrameAnimation = null;
    872                 mRotateFrameTransformation.clear();
    873             }
    874         }
    875 
    876         mExitTransformation.set(mRotateExitTransformation);
    877         mEnterTransformation.set(mRotateEnterTransformation);
    878         if (TWO_PHASE_ANIMATION) {
    879             mExitTransformation.compose(mStartExitTransformation);
    880             mExitTransformation.compose(mFinishExitTransformation);
    881 
    882             mEnterTransformation.compose(mStartEnterTransformation);
    883             mEnterTransformation.compose(mFinishEnterTransformation);
    884         }
    885 
    886         if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
    887         if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);
    888 
    889         if (USE_CUSTOM_BLACK_FRAME) {
    890             //mFrameTransformation.set(mRotateExitTransformation);
    891             //mFrameTransformation.compose(mStartExitTransformation);
    892             //mFrameTransformation.compose(mFinishExitTransformation);
    893             mFrameTransformation.set(mRotateFrameTransformation);
    894             mFrameTransformation.compose(mStartFrameTransformation);
    895             mFrameTransformation.compose(mFinishFrameTransformation);
    896             mFrameTransformation.getMatrix().preConcat(mFrameInitialMatrix);
    897             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final frame: " + mFrameTransformation);
    898         }
    899 
    900         final boolean more = (TWO_PHASE_ANIMATION
    901                     && (mMoreStartEnter || mMoreStartExit || mMoreFinishEnter || mMoreFinishExit))
    902                 || (USE_CUSTOM_BLACK_FRAME
    903                         && (mMoreStartFrame || mMoreRotateFrame || mMoreFinishFrame))
    904                 || mMoreRotateEnter || mMoreRotateExit
    905                 || !mFinishAnimReady;
    906 
    907         mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
    908 
    909         if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
    910 
    911         return more;
    912     }
    913 
    914     void updateSurfacesInTransaction() {
    915         if (!mStarted) {
    916             return;
    917         }
    918 
    919         if (mSurfaceControl != null) {
    920             if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
    921                 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
    922                 mSurfaceControl.hide();
    923             }
    924         }
    925 
    926         if (mCustomBlackFrame != null) {
    927             if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) {
    928                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame");
    929                 mCustomBlackFrame.hide();
    930             } else {
    931                 mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix());
    932             }
    933         }
    934 
    935         if (mExitingBlackFrame != null) {
    936             if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
    937                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame");
    938                 mExitingBlackFrame.hide();
    939             } else {
    940                 mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix);
    941                 mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix);
    942                 if (mForceDefaultOrientation) {
    943                     mExitingBlackFrame.setAlpha(mExitTransformation.getAlpha());
    944                 }
    945             }
    946         }
    947 
    948         if (mEnteringBlackFrame != null) {
    949             if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) {
    950                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame");
    951                 mEnteringBlackFrame.hide();
    952             } else {
    953                 mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix());
    954             }
    955         }
    956 
    957         setSnapshotTransformInTransaction(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
    958     }
    959 
    960     public boolean stepAnimationLocked(long now) {
    961         if (!hasAnimations()) {
    962             if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
    963             mFinishAnimReady = false;
    964             return false;
    965         }
    966 
    967         if (!mAnimRunning) {
    968             if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate");
    969             if (TWO_PHASE_ANIMATION) {
    970                 if (mStartEnterAnimation != null) {
    971                     mStartEnterAnimation.setStartTime(now);
    972                 }
    973                 if (mStartExitAnimation != null) {
    974                     mStartExitAnimation.setStartTime(now);
    975                 }
    976                 if (mFinishEnterAnimation != null) {
    977                     mFinishEnterAnimation.setStartTime(0);
    978                 }
    979                 if (mFinishExitAnimation != null) {
    980                     mFinishExitAnimation.setStartTime(0);
    981                 }
    982             }
    983             if (USE_CUSTOM_BLACK_FRAME) {
    984                 if (mStartFrameAnimation != null) {
    985                     mStartFrameAnimation.setStartTime(now);
    986                 }
    987                 if (mFinishFrameAnimation != null) {
    988                     mFinishFrameAnimation.setStartTime(0);
    989                 }
    990                 if (mRotateFrameAnimation != null) {
    991                     mRotateFrameAnimation.setStartTime(now);
    992                 }
    993             }
    994             if (mRotateEnterAnimation != null) {
    995                 mRotateEnterAnimation.setStartTime(now);
    996             }
    997             if (mRotateExitAnimation != null) {
    998                 mRotateExitAnimation.setStartTime(now);
    999             }
   1000             mAnimRunning = true;
   1001             mHalfwayPoint = now + mRotateEnterAnimation.getDuration() / 2;
   1002         }
   1003 
   1004         return stepAnimation(now);
   1005     }
   1006 
   1007     public Transformation getEnterTransformation() {
   1008         return mEnterTransformation;
   1009     }
   1010 }
   1011