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