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