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