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