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 printTo(String prefix, PrintWriter pw)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 ScreenRotationAnimation(Context context, Display display, SurfaceSession session, boolean inTransaction, int originalWidth, int originalHeight, int originalRotation, int exitAnim, int enterAnim)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 hasScreenshot()257 boolean hasScreenshot() { 258 return mSurface != null; 259 } 260 deltaRotation(int oldRotation, int newRotation)261 static int deltaRotation(int oldRotation, int newRotation) { 262 int delta = newRotation - oldRotation; 263 if (delta < 0) delta += 4; 264 return delta; 265 } 266 setSnapshotTransformInTransaction(Matrix matrix, float alpha)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 createRotationMatrix(int rotation, int width, int height, Matrix outMatrix)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. setRotationInTransaction(int rotation)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. setRotationInTransaction(int rotation, SurfaceSession session, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight)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 */ startAnimation(SurfaceSession session, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight, boolean dismissing)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 */ dismiss(SurfaceSession session, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight)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 kill()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 isAnimating()667 public boolean isAnimating() { 668 return hasAnimations() || (TWO_PHASE_ANIMATION && mFinishAnimReady); 669 } 670 isRotating()671 public boolean isRotating() { 672 return mCurRotation != mOriginalRotation; 673 } 674 hasAnimations()675 private boolean hasAnimations() { 676 return (TWO_PHASE_ANIMATION && 677 (mStartEnterAnimation != null || mStartExitAnimation != null 678 || mFinishEnterAnimation != null || mFinishExitAnimation != null)) 679 || (USE_CUSTOM_BLACK_FRAME && 680 (mStartFrameAnimation != null || mRotateFrameAnimation != null 681 || mFinishFrameAnimation != null)) 682 || mRotateEnterAnimation != null || mRotateExitAnimation != null; 683 } 684 stepAnimation(long now)685 private boolean stepAnimation(long now) { 686 if (now > mHalfwayPoint) { 687 mHalfwayPoint = Long.MAX_VALUE; 688 } 689 if (mFinishAnimReady && mFinishAnimStartTime < 0) { 690 if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready"); 691 mFinishAnimStartTime = now; 692 } 693 694 if (TWO_PHASE_ANIMATION) { 695 mMoreStartExit = false; 696 if (mStartExitAnimation != null) { 697 mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation); 698 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation); 699 } 700 701 mMoreStartEnter = false; 702 if (mStartEnterAnimation != null) { 703 mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation); 704 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation); 705 } 706 } 707 if (USE_CUSTOM_BLACK_FRAME) { 708 mMoreStartFrame = false; 709 if (mStartFrameAnimation != null) { 710 mMoreStartFrame = mStartFrameAnimation.getTransformation(now, mStartFrameTransformation); 711 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start frame: " + mStartFrameTransformation); 712 } 713 } 714 715 long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0; 716 if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow); 717 718 if (TWO_PHASE_ANIMATION) { 719 mMoreFinishExit = false; 720 if (mFinishExitAnimation != null) { 721 mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation); 722 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation); 723 } 724 725 mMoreFinishEnter = false; 726 if (mFinishEnterAnimation != null) { 727 mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation); 728 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation); 729 } 730 } 731 if (USE_CUSTOM_BLACK_FRAME) { 732 mMoreFinishFrame = false; 733 if (mFinishFrameAnimation != null) { 734 mMoreFinishFrame = mFinishFrameAnimation.getTransformation(finishNow, mFinishFrameTransformation); 735 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish frame: " + mFinishFrameTransformation); 736 } 737 } 738 739 mMoreRotateExit = false; 740 if (mRotateExitAnimation != null) { 741 mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation); 742 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation); 743 } 744 745 mMoreRotateEnter = false; 746 if (mRotateEnterAnimation != null) { 747 mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation); 748 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation); 749 } 750 751 if (USE_CUSTOM_BLACK_FRAME) { 752 mMoreRotateFrame = false; 753 if (mRotateFrameAnimation != null) { 754 mMoreRotateFrame = mRotateFrameAnimation.getTransformation(now, mRotateFrameTransformation); 755 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate frame: " + mRotateFrameTransformation); 756 } 757 } 758 759 if (!mMoreRotateExit && (!TWO_PHASE_ANIMATION || (!mMoreStartExit && !mMoreFinishExit))) { 760 if (TWO_PHASE_ANIMATION) { 761 if (mStartExitAnimation != null) { 762 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing start exit anim!"); 763 mStartExitAnimation.cancel(); 764 mStartExitAnimation = null; 765 mStartExitTransformation.clear(); 766 } 767 if (mFinishExitAnimation != null) { 768 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing finish exit anim!"); 769 mFinishExitAnimation.cancel(); 770 mFinishExitAnimation = null; 771 mFinishExitTransformation.clear(); 772 } 773 } 774 if (mRotateExitAnimation != null) { 775 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing rotate exit anim!"); 776 mRotateExitAnimation.cancel(); 777 mRotateExitAnimation = null; 778 mRotateExitTransformation.clear(); 779 } 780 } 781 782 if (!mMoreRotateEnter && (!TWO_PHASE_ANIMATION || (!mMoreStartEnter && !mMoreFinishEnter))) { 783 if (TWO_PHASE_ANIMATION) { 784 if (mStartEnterAnimation != null) { 785 if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing start enter anim!"); 786 mStartEnterAnimation.cancel(); 787 mStartEnterAnimation = null; 788 mStartEnterTransformation.clear(); 789 } 790 if (mFinishEnterAnimation != null) { 791 if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing finish enter anim!"); 792 mFinishEnterAnimation.cancel(); 793 mFinishEnterAnimation = null; 794 mFinishEnterTransformation.clear(); 795 } 796 } 797 if (mRotateEnterAnimation != null) { 798 if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing rotate enter anim!"); 799 mRotateEnterAnimation.cancel(); 800 mRotateEnterAnimation = null; 801 mRotateEnterTransformation.clear(); 802 } 803 } 804 805 if (USE_CUSTOM_BLACK_FRAME && !mMoreStartFrame && !mMoreRotateFrame && !mMoreFinishFrame) { 806 if (mStartFrameAnimation != null) { 807 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing start frame anim!"); 808 mStartFrameAnimation.cancel(); 809 mStartFrameAnimation = null; 810 mStartFrameTransformation.clear(); 811 } 812 if (mFinishFrameAnimation != null) { 813 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing finish frame anim!"); 814 mFinishFrameAnimation.cancel(); 815 mFinishFrameAnimation = null; 816 mFinishFrameTransformation.clear(); 817 } 818 if (mRotateFrameAnimation != null) { 819 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing rotate frame anim!"); 820 mRotateFrameAnimation.cancel(); 821 mRotateFrameAnimation = null; 822 mRotateFrameTransformation.clear(); 823 } 824 } 825 826 mExitTransformation.set(mRotateExitTransformation); 827 mEnterTransformation.set(mRotateEnterTransformation); 828 if (TWO_PHASE_ANIMATION) { 829 mExitTransformation.compose(mStartExitTransformation); 830 mExitTransformation.compose(mFinishExitTransformation); 831 832 mEnterTransformation.compose(mStartEnterTransformation); 833 mEnterTransformation.compose(mFinishEnterTransformation); 834 } 835 836 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation); 837 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation); 838 839 if (USE_CUSTOM_BLACK_FRAME) { 840 //mFrameTransformation.set(mRotateExitTransformation); 841 //mFrameTransformation.compose(mStartExitTransformation); 842 //mFrameTransformation.compose(mFinishExitTransformation); 843 mFrameTransformation.set(mRotateFrameTransformation); 844 mFrameTransformation.compose(mStartFrameTransformation); 845 mFrameTransformation.compose(mFinishFrameTransformation); 846 mFrameTransformation.getMatrix().preConcat(mFrameInitialMatrix); 847 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final frame: " + mFrameTransformation); 848 } 849 850 final boolean more = (TWO_PHASE_ANIMATION 851 && (mMoreStartEnter || mMoreStartExit || mMoreFinishEnter || mMoreFinishExit)) 852 || (USE_CUSTOM_BLACK_FRAME 853 && (mMoreStartFrame || mMoreRotateFrame || mMoreFinishFrame)) 854 || mMoreRotateEnter || mMoreRotateExit 855 || !mFinishAnimReady; 856 857 mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix); 858 859 if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more); 860 861 return more; 862 } 863 updateSurfacesInTransaction()864 void updateSurfacesInTransaction() { 865 if (!mStarted) { 866 return; 867 } 868 869 if (mSurface != null) { 870 if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) { 871 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface"); 872 mSurface.hide(); 873 } 874 } 875 876 if (mCustomBlackFrame != null) { 877 if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) { 878 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame"); 879 mCustomBlackFrame.hide(); 880 } else { 881 mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix()); 882 } 883 } 884 885 if (mExitingBlackFrame != null) { 886 if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) { 887 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame"); 888 mExitingBlackFrame.hide(); 889 } else { 890 mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix); 891 mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix); 892 } 893 } 894 895 if (mEnteringBlackFrame != null) { 896 if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) { 897 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame"); 898 mEnteringBlackFrame.hide(); 899 } else { 900 mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix()); 901 } 902 } 903 904 setSnapshotTransformInTransaction(mSnapshotFinalMatrix, mExitTransformation.getAlpha()); 905 } 906 stepAnimationLocked(long now)907 public boolean stepAnimationLocked(long now) { 908 if (!hasAnimations()) { 909 if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running"); 910 mFinishAnimReady = false; 911 return false; 912 } 913 914 if (!mAnimRunning) { 915 if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate"); 916 if (TWO_PHASE_ANIMATION) { 917 if (mStartEnterAnimation != null) { 918 mStartEnterAnimation.setStartTime(now); 919 } 920 if (mStartExitAnimation != null) { 921 mStartExitAnimation.setStartTime(now); 922 } 923 if (mFinishEnterAnimation != null) { 924 mFinishEnterAnimation.setStartTime(0); 925 } 926 if (mFinishExitAnimation != null) { 927 mFinishExitAnimation.setStartTime(0); 928 } 929 } 930 if (USE_CUSTOM_BLACK_FRAME) { 931 if (mStartFrameAnimation != null) { 932 mStartFrameAnimation.setStartTime(now); 933 } 934 if (mFinishFrameAnimation != null) { 935 mFinishFrameAnimation.setStartTime(0); 936 } 937 if (mRotateFrameAnimation != null) { 938 mRotateFrameAnimation.setStartTime(now); 939 } 940 } 941 if (mRotateEnterAnimation != null) { 942 mRotateEnterAnimation.setStartTime(now); 943 } 944 if (mRotateExitAnimation != null) { 945 mRotateExitAnimation.setStartTime(now); 946 } 947 mAnimRunning = true; 948 mHalfwayPoint = now + mRotateEnterAnimation.getDuration() / 2; 949 } 950 951 return stepAnimation(now); 952 } 953 getEnterTransformation()954 public Transformation getEnterTransformation() { 955 return mEnterTransformation; 956 } 957 } 958