blob: 932e456840d7c89b364c30303d0b71bf08d9509e [file] [log] [blame]
Dianne Hackborna1111872010-11-23 20:55:11 -08001/*
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
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080017package com.android.server.wm;
Dianne Hackborna1111872010-11-23 20:55:11 -080018
Dianne Hackborn4dcece82012-02-10 14:50:32 -080019import java.io.PrintWriter;
20
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080021import android.content.Context;
Dianne Hackborna1111872010-11-23 20:55:11 -080022import android.graphics.Matrix;
Dianne Hackborna1111872010-11-23 20:55:11 -080023import android.graphics.PixelFormat;
24import android.graphics.Rect;
Dianne Hackborna1111872010-11-23 20:55:11 -080025import android.util.Slog;
Dianne Hackborna1111872010-11-23 20:55:11 -080026import android.view.Surface;
27import android.view.SurfaceSession;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080028import android.view.animation.Animation;
29import android.view.animation.AnimationUtils;
30import android.view.animation.Transformation;
Dianne Hackborna1111872010-11-23 20:55:11 -080031
Craig Mautnerdbb79912012-03-01 18:59:14 -080032class ScreenRotationAnimation implements WindowManagerService.StepAnimator {
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080033 static final String TAG = "ScreenRotationAnimation";
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -080034 static final boolean DEBUG_STATE = false;
35 static final boolean DEBUG_TRANSFORMS = false;
Dianne Hackborna1111872010-11-23 20:55:11 -080036
Dianne Hackborn50660e22011-02-02 17:12:25 -080037 static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
38
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080039 final Context mContext;
Dianne Hackborna1111872010-11-23 20:55:11 -080040 Surface mSurface;
Dianne Hackborn7916ac62011-05-16 20:45:48 -070041 BlackFrame mBlackFrame;
Dianne Hackborna1111872010-11-23 20:55:11 -080042 int mWidth, mHeight;
43
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080044 int mSnapshotRotation;
45 int mSnapshotDeltaRotation;
46 int mOriginalRotation;
47 int mOriginalWidth, mOriginalHeight;
Dianne Hackborna1111872010-11-23 20:55:11 -080048 int mCurRotation;
Dianne Hackborna1111872010-11-23 20:55:11 -080049
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -080050 // 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.
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080088 final Transformation mExitTransformation = new Transformation();
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080089 final Transformation mEnterTransformation = new Transformation();
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -080090
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080091 boolean mStarted;
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -080092 boolean mAnimRunning;
93 boolean mFinishAnimReady;
94 long mFinishAnimStartTime;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080095
Dianne Hackbornf9d0be92010-11-24 12:35:25 -080096 final Matrix mSnapshotInitialMatrix = new Matrix();
97 final Matrix mSnapshotFinalMatrix = new Matrix();
Dianne Hackborn50660e22011-02-02 17:12:25 -080098 final Matrix mTmpMatrix = new Matrix();
Dianne Hackborna1111872010-11-23 20:55:11 -080099 final float[] mTmpFloats = new float[9];
Craig Mautnerdbb79912012-03-01 18:59:14 -0800100 private boolean mMoreRotateEnter;
101 private boolean mMoreRotateExit;
102 private boolean mMoreFinishEnter;
103 private boolean mMoreFinishExit;
104 private boolean mMoreStartEnter;
105 private boolean mMoreStartExit;
Dianne Hackborna1111872010-11-23 20:55:11 -0800106
Dianne Hackborn4dcece82012-02-10 14:50:32 -0800107 public void printTo(String prefix, PrintWriter pw) {
108 pw.print(prefix); pw.print("mSurface="); pw.print(mSurface);
109 pw.print(" mWidth="); pw.print(mWidth);
110 pw.print(" mHeight="); pw.println(mHeight);
111 pw.print(prefix); pw.print("mBlackFrame="); pw.println(mBlackFrame);
112 pw.print(prefix); pw.print("mSnapshotRotation="); pw.print(mSnapshotRotation);
113 pw.print(" mSnapshotDeltaRotation="); pw.print(mSnapshotDeltaRotation);
114 pw.print(" mCurRotation="); pw.println(mCurRotation);
115 pw.print(prefix); pw.print("mOriginalRotation="); pw.print(mOriginalRotation);
116 pw.print(" mOriginalWidth="); pw.print(mOriginalWidth);
117 pw.print(" mOriginalHeight="); pw.println(mOriginalHeight);
118 pw.print(prefix); pw.print("mStarted="); pw.print(mStarted);
119 pw.print(" mAnimRunning="); pw.print(mAnimRunning);
120 pw.print(" mFinishAnimReady="); pw.print(mFinishAnimReady);
121 pw.print(" mFinishAnimStartTime="); pw.println(mFinishAnimStartTime);
122 pw.print(prefix); pw.print("mStartExitAnimation="); pw.print(mStartExitAnimation);
123 pw.print(" "); mStartExitTransformation.printShortString(pw); pw.println();
124 pw.print(prefix); pw.print("mStartEnterAnimation="); pw.print(mStartEnterAnimation);
125 pw.print(" "); mStartEnterTransformation.printShortString(pw); pw.println();
126 pw.print(prefix); pw.print("mFinishExitAnimation="); pw.print(mFinishExitAnimation);
127 pw.print(" "); mFinishExitTransformation.printShortString(pw); pw.println();
128 pw.print(prefix); pw.print("mFinishEnterAnimation="); pw.print(mFinishEnterAnimation);
129 pw.print(" "); mFinishEnterTransformation.printShortString(pw); pw.println();
130 pw.print(prefix); pw.print("mRotateExitAnimation="); pw.print(mRotateExitAnimation);
131 pw.print(" "); mRotateExitTransformation.printShortString(pw); pw.println();
132 pw.print(prefix); pw.print("mRotateEnterAnimation="); pw.print(mRotateEnterAnimation);
133 pw.print(" "); mRotateEnterTransformation.printShortString(pw); pw.println();
134 pw.print(prefix); pw.print("mLastRotateExitAnimation=");
135 pw.print(mLastRotateExitAnimation);
136 pw.print(" "); mLastRotateExitTransformation.printShortString(pw); pw.println();
137 pw.print(prefix); pw.print("mExitTransformation=");
138 mExitTransformation.printShortString(pw); pw.println();
139 pw.print(prefix); pw.print("mEnterTransformation=");
140 mEnterTransformation.printShortString(pw); pw.println();
141 pw.print(prefix); pw.print("mSnapshotInitialMatrix=");
142 mSnapshotInitialMatrix.printShortString(pw);
143 pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw);
144 pw.println();
145 }
146
Jeff Brownbc68a592011-07-25 12:58:12 -0700147 public ScreenRotationAnimation(Context context, SurfaceSession session,
148 boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800149 mContext = context;
Dianne Hackborna1111872010-11-23 20:55:11 -0800150
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800151 // Screenshot does NOT include rotation!
152 mSnapshotRotation = 0;
Mathias Agopian0ab84ef2011-10-13 16:02:48 -0700153 if (originalRotation == Surface.ROTATION_90
154 || originalRotation == Surface.ROTATION_270) {
155 mWidth = originalHeight;
156 mHeight = originalWidth;
157 } else {
158 mWidth = originalWidth;
159 mHeight = originalHeight;
160 }
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800161
Jeff Brownbc68a592011-07-25 12:58:12 -0700162 mOriginalRotation = originalRotation;
163 mOriginalWidth = originalWidth;
164 mOriginalHeight = originalHeight;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800165
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800166 if (!inTransaction) {
Dianne Hackborn36991742011-10-11 21:35:26 -0700167 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800168 ">>> OPEN TRANSACTION ScreenRotationAnimation");
169 Surface.openTransaction();
170 }
Dianne Hackborn352cc982011-01-04 11:34:18 -0800171
Dianne Hackborna1111872010-11-23 20:55:11 -0800172 try {
Dianne Hackborn352cc982011-01-04 11:34:18 -0800173 try {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800174 mSurface = new Surface(session, 0, "FreezeSurface",
Mathias Agopiane65beaa2011-11-01 14:39:06 -0700175 -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
Mathias Agopian0ab84ef2011-10-13 16:02:48 -0700176 if (mSurface == null || !mSurface.isValid()) {
177 // Screenshot failed, punt.
178 mSurface = null;
179 return;
180 }
Dianne Hackborn50660e22011-02-02 17:12:25 -0800181 mSurface.setLayer(FREEZE_LAYER + 1);
Mathias Agopiane65beaa2011-11-01 14:39:06 -0700182 mSurface.show();
Dianne Hackborn352cc982011-01-04 11:34:18 -0800183 } catch (Surface.OutOfResourcesException e) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800184 Slog.w(TAG, "Unable to allocate freeze surface", e);
Dianne Hackborn352cc982011-01-04 11:34:18 -0800185 }
Dianne Hackborna1111872010-11-23 20:55:11 -0800186
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700187 if (WindowManagerService.SHOW_TRANSACTIONS ||
188 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
189 " FREEZE " + mSurface + ": CREATE");
190
Jeff Brownbc68a592011-07-25 12:58:12 -0700191 setRotation(originalRotation);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800192 } finally {
193 if (!inTransaction) {
194 Surface.closeTransaction();
Dianne Hackborn36991742011-10-11 21:35:26 -0700195 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800196 "<<< CLOSE TRANSACTION ScreenRotationAnimation");
Dianne Hackborn352cc982011-01-04 11:34:18 -0800197 }
Dianne Hackborn0f761d62010-11-30 22:06:10 -0800198 }
Dianne Hackborna1111872010-11-23 20:55:11 -0800199 }
200
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800201 boolean hasScreenshot() {
202 return mSurface != null;
203 }
204
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800205 static int deltaRotation(int oldRotation, int newRotation) {
206 int delta = newRotation - oldRotation;
Dianne Hackborna1111872010-11-23 20:55:11 -0800207 if (delta < 0) delta += 4;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800208 return delta;
209 }
Dianne Hackborna1111872010-11-23 20:55:11 -0800210
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800211 void setSnapshotTransform(Matrix matrix, float alpha) {
Dianne Hackborn352cc982011-01-04 11:34:18 -0800212 if (mSurface != null) {
213 matrix.getValues(mTmpFloats);
Dianne Hackbornd040edb2011-08-31 12:47:58 -0700214 mSurface.setPosition(mTmpFloats[Matrix.MTRANS_X],
215 mTmpFloats[Matrix.MTRANS_Y]);
Dianne Hackborn352cc982011-01-04 11:34:18 -0800216 mSurface.setMatrix(
217 mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
218 mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
219 mSurface.setAlpha(alpha);
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800220 if (DEBUG_TRANSFORMS) {
Dianne Hackborn352cc982011-01-04 11:34:18 -0800221 float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
222 float[] dstPnts = new float[4];
223 matrix.mapPoints(dstPnts, srcPnts);
224 Slog.i(TAG, "Original : (" + srcPnts[0] + "," + srcPnts[1]
225 + ")-(" + srcPnts[2] + "," + srcPnts[3] + ")");
226 Slog.i(TAG, "Transformed: (" + dstPnts[0] + "," + dstPnts[1]
227 + ")-(" + dstPnts[2] + "," + dstPnts[3] + ")");
228 }
Dianne Hackborna1111872010-11-23 20:55:11 -0800229 }
230 }
231
Dianne Hackborn0aae2d42010-12-07 23:51:29 -0800232 public static void createRotationMatrix(int rotation, int width, int height,
233 Matrix outMatrix) {
234 switch (rotation) {
235 case Surface.ROTATION_0:
236 outMatrix.reset();
237 break;
238 case Surface.ROTATION_90:
239 outMatrix.setRotate(90, 0, 0);
240 outMatrix.postTranslate(height, 0);
241 break;
242 case Surface.ROTATION_180:
243 outMatrix.setRotate(180, 0, 0);
244 outMatrix.postTranslate(width, height);
245 break;
246 case Surface.ROTATION_270:
247 outMatrix.setRotate(270, 0, 0);
248 outMatrix.postTranslate(0, width);
249 break;
250 }
251 }
252
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800253 // Must be called while in a transaction.
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800254 private void setRotation(int rotation) {
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800255 mCurRotation = rotation;
256
257 // Compute the transformation matrix that must be applied
258 // to the snapshot to make it stay in the same original position
259 // with the current screen rotation.
260 int delta = deltaRotation(rotation, mSnapshotRotation);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -0800261 createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800262
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800263 if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800264 setSnapshotTransform(mSnapshotInitialMatrix, 1.0f);
265 }
266
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800267 // Must be called while in a transaction.
268 public boolean setRotation(int rotation, SurfaceSession session,
269 long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) {
270 setRotation(rotation);
271 return startAnimation(session, maxAnimationDuration, animationScale,
272 finalWidth, finalHeight, false);
273 }
274
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800275 /**
276 * Returns true if animating.
277 */
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800278 private boolean startAnimation(SurfaceSession session, long maxAnimationDuration,
279 float animationScale, int finalWidth, int finalHeight, boolean dismissing) {
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800280 if (mSurface == null) {
281 // Can't do animation.
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800282 return false;
283 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800284 if (mStarted) {
285 return true;
286 }
287
288 mStarted = true;
289
290 boolean firstStart = false;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800291
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800292 // Figure out how the screen has moved from the original rotation.
293 int delta = deltaRotation(mCurRotation, mOriginalRotation);
294
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800295 if (mFinishExitAnimation == null && (!dismissing || delta != Surface.ROTATION_0)) {
296 if (DEBUG_STATE) Slog.v(TAG, "Creating start and finish animations");
297 firstStart = true;
298 mStartExitAnimation = AnimationUtils.loadAnimation(mContext,
299 com.android.internal.R.anim.screen_rotate_start_exit);
300 mStartEnterAnimation = AnimationUtils.loadAnimation(mContext,
301 com.android.internal.R.anim.screen_rotate_start_enter);
302 mFinishExitAnimation = AnimationUtils.loadAnimation(mContext,
303 com.android.internal.R.anim.screen_rotate_finish_exit);
304 mFinishEnterAnimation = AnimationUtils.loadAnimation(mContext,
305 com.android.internal.R.anim.screen_rotate_finish_enter);
306 }
307
308 if (DEBUG_STATE) Slog.v(TAG, "Rotation delta: " + delta + " finalWidth="
309 + finalWidth + " finalHeight=" + finalHeight
310 + " origWidth=" + mOriginalWidth + " origHeight=" + mOriginalHeight);
311
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800312 switch (delta) {
313 case Surface.ROTATION_0:
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800314 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800315 com.android.internal.R.anim.screen_rotate_0_exit);
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800316 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800317 com.android.internal.R.anim.screen_rotate_0_enter);
318 break;
319 case Surface.ROTATION_90:
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800320 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800321 com.android.internal.R.anim.screen_rotate_plus_90_exit);
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800322 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800323 com.android.internal.R.anim.screen_rotate_plus_90_enter);
324 break;
325 case Surface.ROTATION_180:
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800326 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800327 com.android.internal.R.anim.screen_rotate_180_exit);
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800328 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800329 com.android.internal.R.anim.screen_rotate_180_enter);
330 break;
331 case Surface.ROTATION_270:
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800332 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800333 com.android.internal.R.anim.screen_rotate_minus_90_exit);
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800334 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800335 com.android.internal.R.anim.screen_rotate_minus_90_enter);
336 break;
337 }
338
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800339 // Initialize the animations. This is a hack, redefining what "parent"
340 // means to allow supplying the last and next size. In this definition
341 // "%p" is the original (let's call it "previous") size, and "%" is the
342 // screen's current/new size.
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800343 if (firstStart) {
344 if (DEBUG_STATE) Slog.v(TAG, "Initializing start and finish animations");
345 mStartEnterAnimation.initialize(finalWidth, finalHeight,
346 mOriginalWidth, mOriginalHeight);
347 mStartExitAnimation.initialize(finalWidth, finalHeight,
348 mOriginalWidth, mOriginalHeight);
349 mFinishEnterAnimation.initialize(finalWidth, finalHeight,
350 mOriginalWidth, mOriginalHeight);
351 mFinishExitAnimation.initialize(finalWidth, finalHeight,
352 mOriginalWidth, mOriginalHeight);
353 }
354 mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
355 mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
356 mAnimRunning = false;
357 mFinishAnimReady = false;
358 mFinishAnimStartTime = -1;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800359
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800360 if (firstStart) {
361 mStartExitAnimation.restrictDuration(maxAnimationDuration);
362 mStartExitAnimation.scaleCurrentDuration(animationScale);
363 mStartEnterAnimation.restrictDuration(maxAnimationDuration);
364 mStartEnterAnimation.scaleCurrentDuration(animationScale);
365 mFinishExitAnimation.restrictDuration(maxAnimationDuration);
366 mFinishExitAnimation.scaleCurrentDuration(animationScale);
367 mFinishEnterAnimation.restrictDuration(maxAnimationDuration);
368 mFinishEnterAnimation.scaleCurrentDuration(animationScale);
369 }
370 mRotateExitAnimation.restrictDuration(maxAnimationDuration);
371 mRotateExitAnimation.scaleCurrentDuration(animationScale);
372 mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
373 mRotateEnterAnimation.scaleCurrentDuration(animationScale);
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800374
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800375 if (mBlackFrame == null) {
376 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
377 WindowManagerService.TAG,
378 ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
379 Surface.openTransaction();
Dianne Hackborn50660e22011-02-02 17:12:25 -0800380
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800381 try {
382 Rect outer = new Rect(-finalWidth*1, -finalHeight*1, finalWidth*2, finalHeight*2);
383 Rect inner = new Rect(0, 0, finalWidth, finalHeight);
384 mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
385 } catch (Surface.OutOfResourcesException e) {
386 Slog.w(TAG, "Unable to allocate black surface", e);
387 } finally {
388 Surface.closeTransaction();
389 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
390 WindowManagerService.TAG,
391 "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
392 }
Dianne Hackborn50660e22011-02-02 17:12:25 -0800393 }
394
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800395 return true;
396 }
397
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800398 /**
399 * Returns true if animating.
400 */
401 public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
402 float animationScale, int finalWidth, int finalHeight) {
403 if (DEBUG_STATE) Slog.v(TAG, "Dismiss!");
404 if (mSurface == null) {
405 // Can't do animation.
406 return false;
407 }
408 if (!mStarted) {
409 startAnimation(session, maxAnimationDuration, animationScale, finalWidth, finalHeight,
410 true);
411 }
412 if (!mStarted) {
413 return false;
414 }
415 if (DEBUG_STATE) Slog.v(TAG, "Setting mFinishAnimReady = true");
416 mFinishAnimReady = true;
417 return true;
418 }
419
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800420 public void kill() {
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800421 if (DEBUG_STATE) Slog.v(TAG, "Kill!");
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800422 if (mSurface != null) {
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700423 if (WindowManagerService.SHOW_TRANSACTIONS ||
424 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
425 " FREEZE " + mSurface + ": DESTROY");
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800426 mSurface.destroy();
427 mSurface = null;
428 }
Dianne Hackborn7916ac62011-05-16 20:45:48 -0700429 if (mBlackFrame != null) {
430 mBlackFrame.kill();
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800431 mBlackFrame = null;
Dianne Hackborn352cc982011-01-04 11:34:18 -0800432 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800433 if (mStartExitAnimation != null) {
434 mStartExitAnimation.cancel();
435 mStartExitAnimation = null;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800436 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800437 if (mStartEnterAnimation != null) {
438 mStartEnterAnimation.cancel();
439 mStartEnterAnimation = null;
440 }
441 if (mFinishExitAnimation != null) {
442 mFinishExitAnimation.cancel();
443 mFinishExitAnimation = null;
444 }
445 if (mStartEnterAnimation != null) {
446 mStartEnterAnimation.cancel();
447 mStartEnterAnimation = null;
448 }
449 if (mRotateExitAnimation != null) {
450 mRotateExitAnimation.cancel();
451 mRotateExitAnimation = null;
452 }
453 if (mRotateEnterAnimation != null) {
454 mRotateEnterAnimation.cancel();
455 mRotateEnterAnimation = null;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800456 }
457 }
458
459 public boolean isAnimating() {
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800460 return mStartEnterAnimation != null || mStartExitAnimation != null
461 && mFinishEnterAnimation != null || mFinishExitAnimation != null
462 && mRotateEnterAnimation != null || mRotateExitAnimation != null;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800463 }
464
Craig Mautnerdbb79912012-03-01 18:59:14 -0800465 @Override
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800466 public boolean stepAnimation(long now) {
Craig Mautnerdbb79912012-03-01 18:59:14 -0800467
468 if (mFinishAnimReady && mFinishAnimStartTime < 0) {
469 if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
470 mFinishAnimStartTime = now;
471 }
472
473 // If the start animation is no longer running, we want to keep its
474 // transformation intact until the finish animation also completes.
475
476 mMoreStartExit = false;
477 if (mStartExitAnimation != null) {
478 mStartExitTransformation.clear();
479 mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
480 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
481 if (!mMoreStartExit) {
482 if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!");
483 mStartExitAnimation.cancel();
484 mStartExitAnimation = null;
485 }
486 }
487
488 mMoreStartEnter = false;
489 if (mStartEnterAnimation != null) {
490 mStartEnterTransformation.clear();
491 mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
492 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
493 if (!mMoreStartEnter) {
494 if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!");
495 mStartEnterAnimation.cancel();
496 mStartEnterAnimation = null;
497 }
498 }
499
500 long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0;
501 if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);
502
503 mFinishExitTransformation.clear();
504 mMoreFinishExit = false;
505 if (mFinishExitAnimation != null) {
506 mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
507 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
508 if (!mMoreStartExit && !mMoreFinishExit) {
509 if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!");
510 mStartExitTransformation.clear();
511 mFinishExitAnimation.cancel();
512 mFinishExitAnimation = null;
513 mFinishExitTransformation.clear();
514 }
515 }
516
517 mFinishEnterTransformation.clear();
518 mMoreFinishEnter = false;
519 if (mFinishEnterAnimation != null) {
520 mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
521 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
522 if (!mMoreStartEnter && !mMoreFinishEnter) {
523 if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!");
524 mStartEnterTransformation.clear();
525 mFinishEnterAnimation.cancel();
526 mFinishEnterAnimation = null;
527 mFinishEnterTransformation.clear();
528 }
529 }
530
531 mRotateExitTransformation.clear();
532 mMoreRotateExit = false;
533 if (mRotateExitAnimation != null) {
534 mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
535 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
536 }
537
538 if (!mMoreFinishExit && !mMoreRotateExit) {
539 if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!");
540 mRotateExitAnimation.cancel();
541 mRotateExitAnimation = null;
542 mRotateExitTransformation.clear();
543 }
544
545 mRotateEnterTransformation.clear();
546 mMoreRotateEnter = false;
547 if (mRotateEnterAnimation != null) {
548 mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
549 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
550 }
551
552 if (!mMoreFinishEnter && !mMoreRotateEnter) {
553 if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!");
554 mRotateEnterAnimation.cancel();
555 mRotateEnterAnimation = null;
556 mRotateEnterTransformation.clear();
557 }
558
559 mExitTransformation.set(mRotateExitTransformation);
560 mExitTransformation.compose(mStartExitTransformation);
561 mExitTransformation.compose(mFinishExitTransformation);
562
563 mEnterTransformation.set(mRotateEnterTransformation);
564 mEnterTransformation.compose(mStartEnterTransformation);
565 mEnterTransformation.compose(mFinishEnterTransformation);
566
567 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
568 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);
569
570 final boolean more = mMoreStartEnter || mMoreStartExit || mMoreFinishEnter
571 || mMoreFinishExit || mMoreRotateEnter || mMoreRotateExit || !mFinishAnimReady;
572
573 mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
574
575 if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
576
577 return more;
578 }
579
580 void updateSurfaces() {
581 if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
582 if (mSurface != null) {
583 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
584 mSurface.hide();
585 }
586 }
587
588 if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) {
589 if (mBlackFrame != null) {
590 if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, hiding black frame");
591 mBlackFrame.hide();
592 }
593 } else {
594 if (mBlackFrame != null) {
595 mBlackFrame.setMatrix(mEnterTransformation.getMatrix());
596 }
597 }
598
599 setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
600 }
601
602 public boolean startAndFinishAnimationLocked(long now) {
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800603 if (!isAnimating()) {
604 if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
Craig Mautnera731cd32012-03-02 15:23:55 -0800605 mFinishAnimReady = false;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800606 return false;
607 }
608
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800609 if (!mAnimRunning) {
610 if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate");
611 if (mStartEnterAnimation != null) {
612 mStartEnterAnimation.setStartTime(now);
Dianne Hackborn89620282011-09-11 12:47:45 -0700613 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800614 if (mStartExitAnimation != null) {
615 mStartExitAnimation.setStartTime(now);
Dianne Hackborn89620282011-09-11 12:47:45 -0700616 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800617 if (mFinishEnterAnimation != null) {
618 mFinishEnterAnimation.setStartTime(0);
619 }
620 if (mFinishExitAnimation != null) {
621 mFinishExitAnimation.setStartTime(0);
622 }
623 if (mRotateEnterAnimation != null) {
624 mRotateEnterAnimation.setStartTime(now);
625 }
626 if (mRotateExitAnimation != null) {
627 mRotateExitAnimation.setStartTime(now);
628 }
629 mAnimRunning = true;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800630 }
Craig Mautnerdbb79912012-03-01 18:59:14 -0800631
632 return true;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800633 }
634
635 public Transformation getEnterTransformation() {
636 return mEnterTransformation;
Dianne Hackborna1111872010-11-23 20:55:11 -0800637 }
638}