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