ScreenRotationAnimation.java revision 4dcece8e509027cd28e20b1f9f14d2c0446d84c0
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 android.content.Context;
22import android.graphics.Matrix;
23import android.graphics.PixelFormat;
24import android.graphics.Rect;
25import android.util.Slog;
26import android.view.Surface;
27import android.view.SurfaceSession;
28import android.view.animation.Animation;
29import android.view.animation.AnimationUtils;
30import android.view.animation.Transformation;
31
32class ScreenRotationAnimation {
33    static final String TAG = "ScreenRotationAnimation";
34    static final boolean DEBUG_STATE = false;
35    static final boolean DEBUG_TRANSFORMS = false;
36
37    static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
38
39    final Context mContext;
40    Surface mSurface;
41    BlackFrame mBlackFrame;
42    int mWidth, mHeight;
43
44    int mSnapshotRotation;
45    int mSnapshotDeltaRotation;
46    int mOriginalRotation;
47    int mOriginalWidth, mOriginalHeight;
48    int mCurRotation;
49
50    // For all animations, "exit" is for the UI elements that are going
51    // away (that is the snapshot of the old screen), and "enter" is for
52    // the new UI elements that are appearing (that is the active windows
53    // in their final orientation).
54
55    // The starting animation for the exiting and entering elements.  This
56    // animation applies a transformation while the rotation is in progress.
57    // It is started immediately, before the new entering UI is ready.
58    Animation mStartExitAnimation;
59    final Transformation mStartExitTransformation = new Transformation();
60    Animation mStartEnterAnimation;
61    final Transformation mStartEnterTransformation = new Transformation();
62
63    // The finishing animation for the exiting and entering elements.  This
64    // animation needs to undo the transformation of the starting animation.
65    // It starts running once the new rotation UI elements are ready to be
66    // displayed.
67    Animation mFinishExitAnimation;
68    final Transformation mFinishExitTransformation = new Transformation();
69    Animation mFinishEnterAnimation;
70    final Transformation mFinishEnterTransformation = new Transformation();
71
72    // The current active animation to move from the old to the new rotated
73    // state.  Which animation is run here will depend on the old and new
74    // rotations.
75    Animation mRotateExitAnimation;
76    final Transformation mRotateExitTransformation = new Transformation();
77    Animation mRotateEnterAnimation;
78    final Transformation mRotateEnterTransformation = new Transformation();
79
80    // A previously running rotate animation.  This will be used if we need
81    // to switch to a new rotation before finishing the previous one.
82    Animation mLastRotateExitAnimation;
83    final Transformation mLastRotateExitTransformation = new Transformation();
84    Animation mLastRotateEnterAnimation;
85    final Transformation mLastRotateEnterTransformation = new Transformation();
86
87    // Complete transformations being applied.
88    final Transformation mExitTransformation = new Transformation();
89    final Transformation mEnterTransformation = new Transformation();
90
91    boolean mStarted;
92    boolean mAnimRunning;
93    boolean mFinishAnimReady;
94    long mFinishAnimStartTime;
95
96    final Matrix mSnapshotInitialMatrix = new Matrix();
97    final Matrix mSnapshotFinalMatrix = new Matrix();
98    final Matrix mTmpMatrix = new Matrix();
99    final float[] mTmpFloats = new float[9];
100
101    public void printTo(String prefix, PrintWriter pw) {
102        pw.print(prefix); pw.print("mSurface="); pw.print(mSurface);
103                pw.print(" mWidth="); pw.print(mWidth);
104                pw.print(" mHeight="); pw.println(mHeight);
105        pw.print(prefix); pw.print("mBlackFrame="); pw.println(mBlackFrame);
106        pw.print(prefix); pw.print("mSnapshotRotation="); pw.print(mSnapshotRotation);
107                pw.print(" mSnapshotDeltaRotation="); pw.print(mSnapshotDeltaRotation);
108                pw.print(" mCurRotation="); pw.println(mCurRotation);
109        pw.print(prefix); pw.print("mOriginalRotation="); pw.print(mOriginalRotation);
110                pw.print(" mOriginalWidth="); pw.print(mOriginalWidth);
111                pw.print(" mOriginalHeight="); pw.println(mOriginalHeight);
112        pw.print(prefix); pw.print("mStarted="); pw.print(mStarted);
113                pw.print(" mAnimRunning="); pw.print(mAnimRunning);
114                pw.print(" mFinishAnimReady="); pw.print(mFinishAnimReady);
115                pw.print(" mFinishAnimStartTime="); pw.println(mFinishAnimStartTime);
116        pw.print(prefix); pw.print("mStartExitAnimation="); pw.print(mStartExitAnimation);
117                pw.print(" "); mStartExitTransformation.printShortString(pw); pw.println();
118        pw.print(prefix); pw.print("mStartEnterAnimation="); pw.print(mStartEnterAnimation);
119                pw.print(" "); mStartEnterTransformation.printShortString(pw); pw.println();
120        pw.print(prefix); pw.print("mFinishExitAnimation="); pw.print(mFinishExitAnimation);
121                pw.print(" "); mFinishExitTransformation.printShortString(pw); pw.println();
122        pw.print(prefix); pw.print("mFinishEnterAnimation="); pw.print(mFinishEnterAnimation);
123                pw.print(" "); mFinishEnterTransformation.printShortString(pw); pw.println();
124        pw.print(prefix); pw.print("mRotateExitAnimation="); pw.print(mRotateExitAnimation);
125                pw.print(" "); mRotateExitTransformation.printShortString(pw); pw.println();
126        pw.print(prefix); pw.print("mRotateEnterAnimation="); pw.print(mRotateEnterAnimation);
127                pw.print(" "); mRotateEnterTransformation.printShortString(pw); pw.println();
128        pw.print(prefix); pw.print("mLastRotateExitAnimation=");
129                pw.print(mLastRotateExitAnimation);
130                pw.print(" "); mLastRotateExitTransformation.printShortString(pw); pw.println();
131        pw.print(prefix); pw.print("mExitTransformation=");
132                mExitTransformation.printShortString(pw); pw.println();
133        pw.print(prefix); pw.print("mEnterTransformation=");
134                mEnterTransformation.printShortString(pw); pw.println();
135        pw.print(prefix); pw.print("mSnapshotInitialMatrix=");
136                mSnapshotInitialMatrix.printShortString(pw);
137                pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw);
138                pw.println();
139    }
140
141    public ScreenRotationAnimation(Context context, SurfaceSession session,
142            boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
143        mContext = context;
144
145        // Screenshot does NOT include rotation!
146        mSnapshotRotation = 0;
147        if (originalRotation == Surface.ROTATION_90
148                || originalRotation == Surface.ROTATION_270) {
149            mWidth = originalHeight;
150            mHeight = originalWidth;
151        } else {
152            mWidth = originalWidth;
153            mHeight = originalHeight;
154        }
155
156        mOriginalRotation = originalRotation;
157        mOriginalWidth = originalWidth;
158        mOriginalHeight = originalHeight;
159
160        if (!inTransaction) {
161            if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
162                    ">>> OPEN TRANSACTION ScreenRotationAnimation");
163            Surface.openTransaction();
164        }
165
166        try {
167            try {
168                mSurface = new Surface(session, 0, "FreezeSurface",
169                        -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
170                if (mSurface == null || !mSurface.isValid()) {
171                    // Screenshot failed, punt.
172                    mSurface = null;
173                    return;
174                }
175                mSurface.setLayer(FREEZE_LAYER + 1);
176                mSurface.show();
177            } catch (Surface.OutOfResourcesException e) {
178                Slog.w(TAG, "Unable to allocate freeze surface", e);
179            }
180
181            if (WindowManagerService.SHOW_TRANSACTIONS ||
182                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
183                            "  FREEZE " + mSurface + ": CREATE");
184
185            setRotation(originalRotation);
186        } finally {
187            if (!inTransaction) {
188                Surface.closeTransaction();
189                if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
190                        "<<< CLOSE TRANSACTION ScreenRotationAnimation");
191            }
192        }
193    }
194
195    boolean hasScreenshot() {
196        return mSurface != null;
197    }
198
199    static int deltaRotation(int oldRotation, int newRotation) {
200        int delta = newRotation - oldRotation;
201        if (delta < 0) delta += 4;
202        return delta;
203    }
204
205    void setSnapshotTransform(Matrix matrix, float alpha) {
206        if (mSurface != null) {
207            matrix.getValues(mTmpFloats);
208            mSurface.setPosition(mTmpFloats[Matrix.MTRANS_X],
209                    mTmpFloats[Matrix.MTRANS_Y]);
210            mSurface.setMatrix(
211                    mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
212                    mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
213            mSurface.setAlpha(alpha);
214            if (DEBUG_TRANSFORMS) {
215                float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
216                float[] dstPnts = new float[4];
217                matrix.mapPoints(dstPnts, srcPnts);
218                Slog.i(TAG, "Original  : (" + srcPnts[0] + "," + srcPnts[1]
219                        + ")-(" + srcPnts[2] + "," + srcPnts[3] + ")");
220                Slog.i(TAG, "Transformed: (" + dstPnts[0] + "," + dstPnts[1]
221                        + ")-(" + dstPnts[2] + "," + dstPnts[3] + ")");
222            }
223        }
224    }
225
226    public static void createRotationMatrix(int rotation, int width, int height,
227            Matrix outMatrix) {
228        switch (rotation) {
229            case Surface.ROTATION_0:
230                outMatrix.reset();
231                break;
232            case Surface.ROTATION_90:
233                outMatrix.setRotate(90, 0, 0);
234                outMatrix.postTranslate(height, 0);
235                break;
236            case Surface.ROTATION_180:
237                outMatrix.setRotate(180, 0, 0);
238                outMatrix.postTranslate(width, height);
239                break;
240            case Surface.ROTATION_270:
241                outMatrix.setRotate(270, 0, 0);
242                outMatrix.postTranslate(0, width);
243                break;
244        }
245    }
246
247    // Must be called while in a transaction.
248    private void setRotation(int rotation) {
249        mCurRotation = rotation;
250
251        // Compute the transformation matrix that must be applied
252        // to the snapshot to make it stay in the same original position
253        // with the current screen rotation.
254        int delta = deltaRotation(rotation, mSnapshotRotation);
255        createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
256
257        if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
258        setSnapshotTransform(mSnapshotInitialMatrix, 1.0f);
259    }
260
261    // Must be called while in a transaction.
262    public boolean setRotation(int rotation, SurfaceSession session,
263            long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) {
264        setRotation(rotation);
265        return startAnimation(session, maxAnimationDuration, animationScale,
266                finalWidth, finalHeight, false);
267    }
268
269    /**
270     * Returns true if animating.
271     */
272    private boolean startAnimation(SurfaceSession session, long maxAnimationDuration,
273            float animationScale, int finalWidth, int finalHeight, boolean dismissing) {
274        if (mSurface == null) {
275            // Can't do animation.
276            return false;
277        }
278        if (mStarted) {
279            return true;
280        }
281
282        mStarted = true;
283
284        boolean firstStart = false;
285
286        // Figure out how the screen has moved from the original rotation.
287        int delta = deltaRotation(mCurRotation, mOriginalRotation);
288
289        if (mFinishExitAnimation == null && (!dismissing || delta != Surface.ROTATION_0)) {
290            if (DEBUG_STATE) Slog.v(TAG, "Creating start and finish animations");
291            firstStart = true;
292            mStartExitAnimation = AnimationUtils.loadAnimation(mContext,
293                    com.android.internal.R.anim.screen_rotate_start_exit);
294            mStartEnterAnimation = AnimationUtils.loadAnimation(mContext,
295                    com.android.internal.R.anim.screen_rotate_start_enter);
296            mFinishExitAnimation = AnimationUtils.loadAnimation(mContext,
297                    com.android.internal.R.anim.screen_rotate_finish_exit);
298            mFinishEnterAnimation = AnimationUtils.loadAnimation(mContext,
299                    com.android.internal.R.anim.screen_rotate_finish_enter);
300        }
301
302        if (DEBUG_STATE) Slog.v(TAG, "Rotation delta: " + delta + " finalWidth="
303                + finalWidth + " finalHeight=" + finalHeight
304                + " origWidth=" + mOriginalWidth + " origHeight=" + mOriginalHeight);
305
306        switch (delta) {
307            case Surface.ROTATION_0:
308                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
309                        com.android.internal.R.anim.screen_rotate_0_exit);
310                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
311                        com.android.internal.R.anim.screen_rotate_0_enter);
312                break;
313            case Surface.ROTATION_90:
314                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
315                        com.android.internal.R.anim.screen_rotate_plus_90_exit);
316                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
317                        com.android.internal.R.anim.screen_rotate_plus_90_enter);
318                break;
319            case Surface.ROTATION_180:
320                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
321                        com.android.internal.R.anim.screen_rotate_180_exit);
322                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
323                        com.android.internal.R.anim.screen_rotate_180_enter);
324                break;
325            case Surface.ROTATION_270:
326                mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
327                        com.android.internal.R.anim.screen_rotate_minus_90_exit);
328                mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
329                        com.android.internal.R.anim.screen_rotate_minus_90_enter);
330                break;
331        }
332
333        // Initialize the animations.  This is a hack, redefining what "parent"
334        // means to allow supplying the last and next size.  In this definition
335        // "%p" is the original (let's call it "previous") size, and "%" is the
336        // screen's current/new size.
337        if (firstStart) {
338            if (DEBUG_STATE) Slog.v(TAG, "Initializing start and finish animations");
339            mStartEnterAnimation.initialize(finalWidth, finalHeight,
340                    mOriginalWidth, mOriginalHeight);
341            mStartExitAnimation.initialize(finalWidth, finalHeight,
342                    mOriginalWidth, mOriginalHeight);
343            mFinishEnterAnimation.initialize(finalWidth, finalHeight,
344                    mOriginalWidth, mOriginalHeight);
345            mFinishExitAnimation.initialize(finalWidth, finalHeight,
346                    mOriginalWidth, mOriginalHeight);
347        }
348        mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
349        mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
350        mAnimRunning = false;
351        mFinishAnimReady = false;
352        mFinishAnimStartTime = -1;
353
354        if (firstStart) {
355            mStartExitAnimation.restrictDuration(maxAnimationDuration);
356            mStartExitAnimation.scaleCurrentDuration(animationScale);
357            mStartEnterAnimation.restrictDuration(maxAnimationDuration);
358            mStartEnterAnimation.scaleCurrentDuration(animationScale);
359            mFinishExitAnimation.restrictDuration(maxAnimationDuration);
360            mFinishExitAnimation.scaleCurrentDuration(animationScale);
361            mFinishEnterAnimation.restrictDuration(maxAnimationDuration);
362            mFinishEnterAnimation.scaleCurrentDuration(animationScale);
363        }
364        mRotateExitAnimation.restrictDuration(maxAnimationDuration);
365        mRotateExitAnimation.scaleCurrentDuration(animationScale);
366        mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
367        mRotateEnterAnimation.scaleCurrentDuration(animationScale);
368
369        if (mBlackFrame == null) {
370            if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
371                    WindowManagerService.TAG,
372                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
373            Surface.openTransaction();
374
375            try {
376                Rect outer = new Rect(-finalWidth*1, -finalHeight*1, finalWidth*2, finalHeight*2);
377                Rect inner = new Rect(0, 0, finalWidth, finalHeight);
378                mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
379            } catch (Surface.OutOfResourcesException e) {
380                Slog.w(TAG, "Unable to allocate black surface", e);
381            } finally {
382                Surface.closeTransaction();
383                if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
384                        WindowManagerService.TAG,
385                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
386            }
387        }
388
389        return true;
390    }
391
392    /**
393     * Returns true if animating.
394     */
395    public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
396            float animationScale, int finalWidth, int finalHeight) {
397        if (DEBUG_STATE) Slog.v(TAG, "Dismiss!");
398        if (mSurface == null) {
399            // Can't do animation.
400            return false;
401        }
402        if (!mStarted) {
403            startAnimation(session, maxAnimationDuration, animationScale, finalWidth, finalHeight,
404                    true);
405        }
406        if (!mStarted) {
407            return false;
408        }
409        if (DEBUG_STATE) Slog.v(TAG, "Setting mFinishAnimReady = true");
410        mFinishAnimReady = true;
411        return true;
412    }
413
414    public void kill() {
415        if (DEBUG_STATE) Slog.v(TAG, "Kill!");
416        if (mSurface != null) {
417            if (WindowManagerService.SHOW_TRANSACTIONS ||
418                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
419                            "  FREEZE " + mSurface + ": DESTROY");
420            mSurface.destroy();
421            mSurface = null;
422        }
423        if (mBlackFrame != null) {
424            mBlackFrame.kill();
425            mBlackFrame = null;
426        }
427        if (mStartExitAnimation != null) {
428            mStartExitAnimation.cancel();
429            mStartExitAnimation = null;
430        }
431        if (mStartEnterAnimation != null) {
432            mStartEnterAnimation.cancel();
433            mStartEnterAnimation = null;
434        }
435        if (mFinishExitAnimation != null) {
436            mFinishExitAnimation.cancel();
437            mFinishExitAnimation = null;
438        }
439        if (mStartEnterAnimation != null) {
440            mStartEnterAnimation.cancel();
441            mStartEnterAnimation = null;
442        }
443        if (mRotateExitAnimation != null) {
444            mRotateExitAnimation.cancel();
445            mRotateExitAnimation = null;
446        }
447        if (mRotateEnterAnimation != null) {
448            mRotateEnterAnimation.cancel();
449            mRotateEnterAnimation = null;
450        }
451    }
452
453    public boolean isAnimating() {
454        return mStartEnterAnimation != null || mStartExitAnimation != null
455                && mFinishEnterAnimation != null || mFinishExitAnimation != null
456                && mRotateEnterAnimation != null || mRotateExitAnimation != null;
457    }
458
459    public boolean stepAnimation(long now) {
460        if (!isAnimating()) {
461            if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
462            return false;
463        }
464
465        if (!mAnimRunning) {
466            if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate");
467            if (mStartEnterAnimation != null) {
468                mStartEnterAnimation.setStartTime(now);
469            }
470            if (mStartExitAnimation != null) {
471                mStartExitAnimation.setStartTime(now);
472            }
473            if (mFinishEnterAnimation != null) {
474                mFinishEnterAnimation.setStartTime(0);
475            }
476            if (mFinishExitAnimation != null) {
477                mFinishExitAnimation.setStartTime(0);
478            }
479            if (mRotateEnterAnimation != null) {
480                mRotateEnterAnimation.setStartTime(now);
481            }
482            if (mRotateExitAnimation != null) {
483                mRotateExitAnimation.setStartTime(now);
484            }
485            mAnimRunning = true;
486        }
487
488        if (mFinishAnimReady && mFinishAnimStartTime < 0) {
489            if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
490            mFinishAnimStartTime = now;
491        }
492
493        // If the start animation is no longer running, we want to keep its
494        // transformation intact until the finish animation also completes.
495
496        boolean moreStartExit = false;
497        if (mStartExitAnimation != null) {
498            mStartExitTransformation.clear();
499            moreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
500            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
501            if (!moreStartExit) {
502                if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!");
503                mStartExitAnimation.cancel();
504                mStartExitAnimation = null;
505            }
506        }
507
508        boolean moreStartEnter = false;
509        if (mStartEnterAnimation != null) {
510            mStartEnterTransformation.clear();
511            moreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
512            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
513            if (!moreStartEnter) {
514                if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!");
515                mStartEnterAnimation.cancel();
516                mStartEnterAnimation = null;
517            }
518        }
519
520        long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0;
521        if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);
522
523        mFinishExitTransformation.clear();
524        boolean moreFinishExit = false;
525        if (mFinishExitAnimation != null) {
526            moreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
527            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
528            if (!moreStartExit && !moreFinishExit) {
529                if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!");
530                mStartExitTransformation.clear();
531                mFinishExitAnimation.cancel();
532                mFinishExitAnimation = null;
533                mFinishExitTransformation.clear();
534            }
535        }
536
537        mFinishEnterTransformation.clear();
538        boolean moreFinishEnter = false;
539        if (mFinishEnterAnimation != null) {
540            moreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
541            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
542            if (!moreStartEnter && !moreFinishEnter) {
543                if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!");
544                mStartEnterTransformation.clear();
545                mFinishEnterAnimation.cancel();
546                mFinishEnterAnimation = null;
547                mFinishEnterTransformation.clear();
548            }
549        }
550
551        mRotateExitTransformation.clear();
552        boolean moreRotateExit = false;
553        if (mRotateExitAnimation != null) {
554            moreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
555            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
556        }
557
558        if (!moreFinishExit && !moreRotateExit) {
559            if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!");
560            mRotateExitAnimation.cancel();
561            mRotateExitAnimation = null;
562            mRotateExitTransformation.clear();
563        }
564
565        mRotateEnterTransformation.clear();
566        boolean moreRotateEnter = false;
567        if (mRotateEnterAnimation != null) {
568            moreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
569            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
570        }
571
572        if (!moreFinishEnter && !moreRotateEnter) {
573            if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!");
574            mRotateEnterAnimation.cancel();
575            mRotateEnterAnimation = null;
576            mRotateEnterTransformation.clear();
577        }
578
579        mExitTransformation.set(mRotateExitTransformation);
580        mExitTransformation.compose(mStartExitTransformation);
581        mExitTransformation.compose(mFinishExitTransformation);
582
583        mEnterTransformation.set(mRotateEnterTransformation);
584        mEnterTransformation.compose(mStartEnterTransformation);
585        mEnterTransformation.compose(mFinishEnterTransformation);
586
587        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
588        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);
589
590        if (!moreStartExit && !moreFinishExit && !moreRotateExit) {
591            if (mSurface != null) {
592                if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
593                mSurface.hide();
594            }
595        }
596
597        if (!moreStartEnter && !moreFinishEnter && !moreRotateEnter) {
598            if (mBlackFrame != null) {
599                if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, hiding black frame");
600                mBlackFrame.hide();
601            }
602        } else {
603            if (mBlackFrame != null) {
604                mBlackFrame.setMatrix(mEnterTransformation.getMatrix());
605            }
606        }
607
608        mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
609        setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
610
611        final boolean more = moreStartEnter || moreStartExit || moreFinishEnter || moreFinishExit
612                || moreRotateEnter || moreRotateExit || !mFinishAnimReady;
613
614        if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
615
616        return more;
617    }
618
619    public Transformation getEnterTransformation() {
620        return mEnterTransformation;
621    }
622}
623