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