blob: 04a039fbcd56a485e3c63c41f8e89f651f1d342e [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
32class ScreenRotationAnimation {
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];
100
Dianne Hackborn4dcece82012-02-10 14:50:32 -0800101 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
Jeff Brownbc68a592011-07-25 12:58:12 -0700141 public ScreenRotationAnimation(Context context, SurfaceSession session,
142 boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800143 mContext = context;
Dianne Hackborna1111872010-11-23 20:55:11 -0800144
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800145 // Screenshot does NOT include rotation!
146 mSnapshotRotation = 0;
Mathias Agopian0ab84ef2011-10-13 16:02:48 -0700147 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 }
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800155
Jeff Brownbc68a592011-07-25 12:58:12 -0700156 mOriginalRotation = originalRotation;
157 mOriginalWidth = originalWidth;
158 mOriginalHeight = originalHeight;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800159
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800160 if (!inTransaction) {
Dianne Hackborn36991742011-10-11 21:35:26 -0700161 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800162 ">>> OPEN TRANSACTION ScreenRotationAnimation");
163 Surface.openTransaction();
164 }
Dianne Hackborn352cc982011-01-04 11:34:18 -0800165
Dianne Hackborna1111872010-11-23 20:55:11 -0800166 try {
Dianne Hackborn352cc982011-01-04 11:34:18 -0800167 try {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800168 mSurface = new Surface(session, 0, "FreezeSurface",
Mathias Agopiane65beaa2011-11-01 14:39:06 -0700169 -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
Mathias Agopian0ab84ef2011-10-13 16:02:48 -0700170 if (mSurface == null || !mSurface.isValid()) {
171 // Screenshot failed, punt.
172 mSurface = null;
173 return;
174 }
Dianne Hackborn50660e22011-02-02 17:12:25 -0800175 mSurface.setLayer(FREEZE_LAYER + 1);
Mathias Agopiane65beaa2011-11-01 14:39:06 -0700176 mSurface.show();
Dianne Hackborn352cc982011-01-04 11:34:18 -0800177 } catch (Surface.OutOfResourcesException e) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800178 Slog.w(TAG, "Unable to allocate freeze surface", e);
Dianne Hackborn352cc982011-01-04 11:34:18 -0800179 }
Dianne Hackborna1111872010-11-23 20:55:11 -0800180
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700181 if (WindowManagerService.SHOW_TRANSACTIONS ||
182 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
183 " FREEZE " + mSurface + ": CREATE");
184
Jeff Brownbc68a592011-07-25 12:58:12 -0700185 setRotation(originalRotation);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800186 } finally {
187 if (!inTransaction) {
188 Surface.closeTransaction();
Dianne Hackborn36991742011-10-11 21:35:26 -0700189 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -0800190 "<<< CLOSE TRANSACTION ScreenRotationAnimation");
Dianne Hackborn352cc982011-01-04 11:34:18 -0800191 }
Dianne Hackborn0f761d62010-11-30 22:06:10 -0800192 }
Dianne Hackborna1111872010-11-23 20:55:11 -0800193 }
194
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800195 boolean hasScreenshot() {
196 return mSurface != null;
197 }
198
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800199 static int deltaRotation(int oldRotation, int newRotation) {
200 int delta = newRotation - oldRotation;
Dianne Hackborna1111872010-11-23 20:55:11 -0800201 if (delta < 0) delta += 4;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800202 return delta;
203 }
Dianne Hackborna1111872010-11-23 20:55:11 -0800204
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800205 void setSnapshotTransform(Matrix matrix, float alpha) {
Dianne Hackborn352cc982011-01-04 11:34:18 -0800206 if (mSurface != null) {
207 matrix.getValues(mTmpFloats);
Dianne Hackbornd040edb2011-08-31 12:47:58 -0700208 mSurface.setPosition(mTmpFloats[Matrix.MTRANS_X],
209 mTmpFloats[Matrix.MTRANS_Y]);
Dianne Hackborn352cc982011-01-04 11:34:18 -0800210 mSurface.setMatrix(
211 mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
212 mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
213 mSurface.setAlpha(alpha);
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800214 if (DEBUG_TRANSFORMS) {
Dianne Hackborn352cc982011-01-04 11:34:18 -0800215 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 }
Dianne Hackborna1111872010-11-23 20:55:11 -0800223 }
224 }
225
Dianne Hackborn0aae2d42010-12-07 23:51:29 -0800226 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
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800247 // Must be called while in a transaction.
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800248 private void setRotation(int rotation) {
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800249 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);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -0800255 createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800256
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800257 if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800258 setSnapshotTransform(mSnapshotInitialMatrix, 1.0f);
259 }
260
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800261 // 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
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800269 /**
270 * Returns true if animating.
271 */
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800272 private boolean startAnimation(SurfaceSession session, long maxAnimationDuration,
273 float animationScale, int finalWidth, int finalHeight, boolean dismissing) {
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800274 if (mSurface == null) {
275 // Can't do animation.
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800276 return false;
277 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800278 if (mStarted) {
279 return true;
280 }
281
282 mStarted = true;
283
284 boolean firstStart = false;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800285
Dianne Hackbornde75cb42011-03-02 17:11:21 -0800286 // Figure out how the screen has moved from the original rotation.
287 int delta = deltaRotation(mCurRotation, mOriginalRotation);
288
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800289 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
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800306 switch (delta) {
307 case Surface.ROTATION_0:
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800308 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800309 com.android.internal.R.anim.screen_rotate_0_exit);
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800310 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800311 com.android.internal.R.anim.screen_rotate_0_enter);
312 break;
313 case Surface.ROTATION_90:
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_plus_90_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_plus_90_enter);
318 break;
319 case Surface.ROTATION_180:
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_180_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_180_enter);
324 break;
325 case Surface.ROTATION_270:
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_minus_90_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_minus_90_enter);
330 break;
331 }
332
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800333 // 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.
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800337 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;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800353
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800354 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);
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800368
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800369 if (mBlackFrame == null) {
370 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
371 WindowManagerService.TAG,
372 ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
373 Surface.openTransaction();
Dianne Hackborn50660e22011-02-02 17:12:25 -0800374
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800375 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 }
Dianne Hackborn50660e22011-02-02 17:12:25 -0800387 }
388
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800389 return true;
390 }
391
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800392 /**
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
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800414 public void kill() {
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800415 if (DEBUG_STATE) Slog.v(TAG, "Kill!");
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800416 if (mSurface != null) {
Dianne Hackborn5fd21692011-06-07 14:09:47 -0700417 if (WindowManagerService.SHOW_TRANSACTIONS ||
418 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
419 " FREEZE " + mSurface + ": DESTROY");
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800420 mSurface.destroy();
421 mSurface = null;
422 }
Dianne Hackborn7916ac62011-05-16 20:45:48 -0700423 if (mBlackFrame != null) {
424 mBlackFrame.kill();
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800425 mBlackFrame = null;
Dianne Hackborn352cc982011-01-04 11:34:18 -0800426 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800427 if (mStartExitAnimation != null) {
428 mStartExitAnimation.cancel();
429 mStartExitAnimation = null;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800430 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800431 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;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800450 }
451 }
452
453 public boolean isAnimating() {
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800454 return mStartEnterAnimation != null || mStartExitAnimation != null
455 && mFinishEnterAnimation != null || mFinishExitAnimation != null
456 && mRotateEnterAnimation != null || mRotateExitAnimation != null;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800457 }
458
459 public boolean stepAnimation(long now) {
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800460 if (!isAnimating()) {
461 if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800462 return false;
463 }
464
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800465 if (!mAnimRunning) {
466 if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate");
467 if (mStartEnterAnimation != null) {
468 mStartEnterAnimation.setStartTime(now);
Dianne Hackborn89620282011-09-11 12:47:45 -0700469 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800470 if (mStartExitAnimation != null) {
471 mStartExitAnimation.setStartTime(now);
Dianne Hackborn89620282011-09-11 12:47:45 -0700472 }
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800473 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;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800486 }
487
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800488 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;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800505 }
506 }
507
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800508 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());
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800605 }
606 }
607
Dianne Hackborn352cc982011-01-04 11:34:18 -0800608 mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
609 setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800610
Dianne Hackbornfd1c5ed2012-01-13 13:09:16 -0800611 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;
Dianne Hackbornf9d0be92010-11-24 12:35:25 -0800617 }
618
619 public Transformation getEnterTransformation() {
620 return mEnterTransformation;
Dianne Hackborna1111872010-11-23 20:55:11 -0800621 }
622}