OSDN Git Service

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