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