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