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