ScreenRotationAnimation.java revision 98365d7663cbd82979a5700faf0050220b01084d
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, 0, "FreezeSurface", 219 mDisplay.getLayerStack(), mWidth, mHeight, 220 PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN); 221 } else { 222 mSurface = new Surface(session, 0, "FreezeSurface", 223 mDisplay.getLayerStack(), 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.setLayer(FREEZE_LAYER + 1); 232 mSurface.setAlpha(0); 233 mSurface.show(); 234 } catch (Surface.OutOfResourcesException e) { 235 Slog.w(TAG, "Unable to allocate freeze surface", e); 236 } 237 238 if (WindowManagerService.SHOW_TRANSACTIONS || 239 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, 240 " FREEZE " + mSurface + ": CREATE"); 241 242 setRotation(originalRotation); 243 } finally { 244 if (!inTransaction) { 245 Surface.closeTransaction(); 246 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG, 247 "<<< CLOSE TRANSACTION ScreenRotationAnimation"); 248 } 249 } 250 } 251 252 boolean hasScreenshot() { 253 return mSurface != null; 254 } 255 256 static int deltaRotation(int oldRotation, int newRotation) { 257 int delta = newRotation - oldRotation; 258 if (delta < 0) delta += 4; 259 return delta; 260 } 261 262 void setSnapshotTransform(Matrix matrix, float alpha) { 263 if (mSurface != null) { 264 matrix.getValues(mTmpFloats); 265 mSurface.setPosition(mTmpFloats[Matrix.MTRANS_X], 266 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 setRotation(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 setSnapshotTransform(mSnapshotInitialMatrix, 1.0f); 316 } 317 318 // Must be called while in a transaction. 319 public boolean setRotation(int rotation, SurfaceSession session, 320 long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) { 321 setRotation(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 switch (delta) { 378 case Surface.ROTATION_0: 379 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, 380 com.android.internal.R.anim.screen_rotate_0_exit); 381 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, 382 com.android.internal.R.anim.screen_rotate_0_enter); 383 if (USE_CUSTOM_BLACK_FRAME) { 384 mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, 385 com.android.internal.R.anim.screen_rotate_0_frame); 386 } 387 break; 388 case Surface.ROTATION_90: 389 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, 390 com.android.internal.R.anim.screen_rotate_plus_90_exit); 391 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, 392 com.android.internal.R.anim.screen_rotate_plus_90_enter); 393 if (USE_CUSTOM_BLACK_FRAME) { 394 mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, 395 com.android.internal.R.anim.screen_rotate_plus_90_frame); 396 } 397 break; 398 case Surface.ROTATION_180: 399 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, 400 com.android.internal.R.anim.screen_rotate_180_exit); 401 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, 402 com.android.internal.R.anim.screen_rotate_180_enter); 403 mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, 404 com.android.internal.R.anim.screen_rotate_180_frame); 405 break; 406 case Surface.ROTATION_270: 407 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, 408 com.android.internal.R.anim.screen_rotate_minus_90_exit); 409 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, 410 com.android.internal.R.anim.screen_rotate_minus_90_enter); 411 if (USE_CUSTOM_BLACK_FRAME) { 412 mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext, 413 com.android.internal.R.anim.screen_rotate_minus_90_frame); 414 } 415 break; 416 } 417 418 // Compute partial steps between original and final sizes. These 419 // are used for the dimensions of the exiting and entering elements, 420 // so they are never stretched too significantly. 421 final int halfWidth = (finalWidth + mOriginalWidth) / 2; 422 final int halfHeight = (finalHeight + mOriginalHeight) / 2; 423 424 // Initialize the animations. This is a hack, redefining what "parent" 425 // means to allow supplying the last and next size. In this definition 426 // "%p" is the original (let's call it "previous") size, and "%" is the 427 // screen's current/new size. 428 if (TWO_PHASE_ANIMATION && firstStart) { 429 if (DEBUG_STATE) Slog.v(TAG, "Initializing start and finish animations"); 430 mStartEnterAnimation.initialize(finalWidth, finalHeight, 431 halfWidth, halfHeight); 432 mStartExitAnimation.initialize(halfWidth, halfHeight, 433 mOriginalWidth, mOriginalHeight); 434 mFinishEnterAnimation.initialize(finalWidth, finalHeight, 435 halfWidth, halfHeight); 436 mFinishExitAnimation.initialize(halfWidth, halfHeight, 437 mOriginalWidth, mOriginalHeight); 438 if (USE_CUSTOM_BLACK_FRAME) { 439 mStartFrameAnimation.initialize(finalWidth, finalHeight, 440 mOriginalWidth, mOriginalHeight); 441 mFinishFrameAnimation.initialize(finalWidth, finalHeight, 442 mOriginalWidth, mOriginalHeight); 443 } 444 } 445 mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight); 446 mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight); 447 if (USE_CUSTOM_BLACK_FRAME) { 448 mRotateFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, 449 mOriginalHeight); 450 } 451 mAnimRunning = false; 452 mFinishAnimReady = false; 453 mFinishAnimStartTime = -1; 454 455 if (TWO_PHASE_ANIMATION && firstStart) { 456 mStartExitAnimation.restrictDuration(maxAnimationDuration); 457 mStartExitAnimation.scaleCurrentDuration(animationScale); 458 mStartEnterAnimation.restrictDuration(maxAnimationDuration); 459 mStartEnterAnimation.scaleCurrentDuration(animationScale); 460 mFinishExitAnimation.restrictDuration(maxAnimationDuration); 461 mFinishExitAnimation.scaleCurrentDuration(animationScale); 462 mFinishEnterAnimation.restrictDuration(maxAnimationDuration); 463 mFinishEnterAnimation.scaleCurrentDuration(animationScale); 464 if (USE_CUSTOM_BLACK_FRAME) { 465 mStartFrameAnimation.restrictDuration(maxAnimationDuration); 466 mStartFrameAnimation.scaleCurrentDuration(animationScale); 467 mFinishFrameAnimation.restrictDuration(maxAnimationDuration); 468 mFinishFrameAnimation.scaleCurrentDuration(animationScale); 469 } 470 } 471 mRotateExitAnimation.restrictDuration(maxAnimationDuration); 472 mRotateExitAnimation.scaleCurrentDuration(animationScale); 473 mRotateEnterAnimation.restrictDuration(maxAnimationDuration); 474 mRotateEnterAnimation.scaleCurrentDuration(animationScale); 475 if (USE_CUSTOM_BLACK_FRAME) { 476 mRotateFrameAnimation.restrictDuration(maxAnimationDuration); 477 mRotateFrameAnimation.scaleCurrentDuration(animationScale); 478 } 479 480 if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) { 481 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( 482 WindowManagerService.TAG, 483 ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation"); 484 Surface.openTransaction(); 485 486 // Compute the transformation matrix that must be applied 487 // the the black frame to make it stay in the initial position 488 // before the new screen rotation. This is different than the 489 // snapshot transformation because the snapshot is always based 490 // of the native orientation of the screen, not the orientation 491 // we were last in. 492 createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix); 493 494 try { 495 Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1, 496 mOriginalWidth*2, mOriginalHeight*2); 497 Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight); 498 mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3); 499 mCustomBlackFrame.setMatrix(mFrameInitialMatrix); 500 } catch (Surface.OutOfResourcesException e) { 501 Slog.w(TAG, "Unable to allocate black surface", e); 502 } finally { 503 Surface.closeTransaction(); 504 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( 505 WindowManagerService.TAG, 506 "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation"); 507 } 508 } 509 510 if (mExitingBlackFrame == null) { 511 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( 512 WindowManagerService.TAG, 513 ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation"); 514 Surface.openTransaction(); 515 516 // Compute the transformation matrix that must be applied 517 // the the black frame to make it stay in the initial position 518 // before the new screen rotation. This is different than the 519 // snapshot transformation because the snapshot is always based 520 // of the native orientation of the screen, not the orientation 521 // we were last in. 522 createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix); 523 524 try { 525 Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1, 526 mOriginalWidth*2, mOriginalHeight*2); 527 Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight); 528 mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2); 529 mExitingBlackFrame.setMatrix(mFrameInitialMatrix); 530 } catch (Surface.OutOfResourcesException e) { 531 Slog.w(TAG, "Unable to allocate black surface", e); 532 } finally { 533 Surface.closeTransaction(); 534 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( 535 WindowManagerService.TAG, 536 "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation"); 537 } 538 } 539 540 if (false && mEnteringBlackFrame == null) { 541 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( 542 WindowManagerService.TAG, 543 ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation"); 544 Surface.openTransaction(); 545 546 try { 547 Rect outer = new Rect(-finalWidth*1, -finalHeight*1, 548 finalWidth*2, finalHeight*2); 549 Rect inner = new Rect(0, 0, finalWidth, finalHeight); 550 mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER); 551 } catch (Surface.OutOfResourcesException e) { 552 Slog.w(TAG, "Unable to allocate black surface", e); 553 } finally { 554 Surface.closeTransaction(); 555 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i( 556 WindowManagerService.TAG, 557 "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation"); 558 } 559 } 560 561 return true; 562 } 563 564 /** 565 * Returns true if animating. 566 */ 567 public boolean dismiss(SurfaceSession session, long maxAnimationDuration, 568 float animationScale, int finalWidth, int finalHeight) { 569 if (DEBUG_STATE) Slog.v(TAG, "Dismiss!"); 570 if (mSurface == null) { 571 // Can't do animation. 572 return false; 573 } 574 if (!mStarted) { 575 startAnimation(session, maxAnimationDuration, animationScale, finalWidth, finalHeight, 576 true); 577 } 578 if (!mStarted) { 579 return false; 580 } 581 if (DEBUG_STATE) Slog.v(TAG, "Setting mFinishAnimReady = true"); 582 mFinishAnimReady = true; 583 return true; 584 } 585 586 public void kill() { 587 if (DEBUG_STATE) Slog.v(TAG, "Kill!"); 588 if (mSurface != null) { 589 if (WindowManagerService.SHOW_TRANSACTIONS || 590 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, 591 " FREEZE " + mSurface + ": DESTROY"); 592 mSurface.destroy(); 593 mSurface = null; 594 } 595 if (mCustomBlackFrame != null) { 596 mCustomBlackFrame.kill(); 597 mCustomBlackFrame = null; 598 } 599 if (mExitingBlackFrame != null) { 600 mExitingBlackFrame.kill(); 601 mExitingBlackFrame = null; 602 } 603 if (mEnteringBlackFrame != null) { 604 mEnteringBlackFrame.kill(); 605 mEnteringBlackFrame = null; 606 } 607 if (TWO_PHASE_ANIMATION) { 608 if (mStartExitAnimation != null) { 609 mStartExitAnimation.cancel(); 610 mStartExitAnimation = null; 611 } 612 if (mStartEnterAnimation != null) { 613 mStartEnterAnimation.cancel(); 614 mStartEnterAnimation = null; 615 } 616 if (mFinishExitAnimation != null) { 617 mFinishExitAnimation.cancel(); 618 mFinishExitAnimation = null; 619 } 620 if (mFinishEnterAnimation != null) { 621 mFinishEnterAnimation.cancel(); 622 mFinishEnterAnimation = null; 623 } 624 } 625 if (USE_CUSTOM_BLACK_FRAME) { 626 if (mStartFrameAnimation != null) { 627 mStartFrameAnimation.cancel(); 628 mStartFrameAnimation = null; 629 } 630 if (mRotateFrameAnimation != null) { 631 mRotateFrameAnimation.cancel(); 632 mRotateFrameAnimation = null; 633 } 634 if (mFinishFrameAnimation != null) { 635 mFinishFrameAnimation.cancel(); 636 mFinishFrameAnimation = null; 637 } 638 } 639 if (mRotateExitAnimation != null) { 640 mRotateExitAnimation.cancel(); 641 mRotateExitAnimation = null; 642 } 643 if (mRotateEnterAnimation != null) { 644 mRotateEnterAnimation.cancel(); 645 mRotateEnterAnimation = null; 646 } 647 } 648 649 public boolean isAnimating() { 650 return hasAnimations() || (TWO_PHASE_ANIMATION && mFinishAnimReady); 651 } 652 653 private boolean hasAnimations() { 654 return (TWO_PHASE_ANIMATION && 655 (mStartEnterAnimation != null || mStartExitAnimation != null 656 || mFinishEnterAnimation != null || mFinishExitAnimation != null)) 657 || (USE_CUSTOM_BLACK_FRAME && 658 (mStartFrameAnimation != null || mRotateFrameAnimation != null 659 || mFinishFrameAnimation != null)) 660 || mRotateEnterAnimation != null || mRotateExitAnimation != null; 661 } 662 663 private boolean stepAnimation(long now) { 664 if (now > mHalfwayPoint) { 665 mHalfwayPoint = Long.MAX_VALUE; 666 } 667 if (mFinishAnimReady && mFinishAnimStartTime < 0) { 668 if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready"); 669 mFinishAnimStartTime = now; 670 } 671 672 if (TWO_PHASE_ANIMATION) { 673 mMoreStartExit = false; 674 if (mStartExitAnimation != null) { 675 mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation); 676 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation); 677 } 678 679 mMoreStartEnter = false; 680 if (mStartEnterAnimation != null) { 681 mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation); 682 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation); 683 } 684 } 685 if (USE_CUSTOM_BLACK_FRAME) { 686 mMoreStartFrame = false; 687 if (mStartFrameAnimation != null) { 688 mMoreStartFrame = mStartFrameAnimation.getTransformation(now, mStartFrameTransformation); 689 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start frame: " + mStartFrameTransformation); 690 } 691 } 692 693 long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0; 694 if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow); 695 696 if (TWO_PHASE_ANIMATION) { 697 mMoreFinishExit = false; 698 if (mFinishExitAnimation != null) { 699 mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation); 700 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation); 701 } 702 703 mMoreFinishEnter = false; 704 if (mFinishEnterAnimation != null) { 705 mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation); 706 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation); 707 } 708 } 709 if (USE_CUSTOM_BLACK_FRAME) { 710 mMoreFinishFrame = false; 711 if (mFinishFrameAnimation != null) { 712 mMoreFinishFrame = mFinishFrameAnimation.getTransformation(finishNow, mFinishFrameTransformation); 713 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish frame: " + mFinishFrameTransformation); 714 } 715 } 716 717 mMoreRotateExit = false; 718 if (mRotateExitAnimation != null) { 719 mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation); 720 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation); 721 } 722 723 mMoreRotateEnter = false; 724 if (mRotateEnterAnimation != null) { 725 mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation); 726 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation); 727 } 728 729 if (USE_CUSTOM_BLACK_FRAME) { 730 mMoreRotateFrame = false; 731 if (mRotateFrameAnimation != null) { 732 mMoreRotateFrame = mRotateFrameAnimation.getTransformation(now, mRotateFrameTransformation); 733 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate frame: " + mRotateFrameTransformation); 734 } 735 } 736 737 if (!mMoreRotateExit && (!TWO_PHASE_ANIMATION || (!mMoreStartExit && !mMoreFinishExit))) { 738 if (TWO_PHASE_ANIMATION) { 739 if (mStartExitAnimation != null) { 740 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing start exit anim!"); 741 mStartExitAnimation.cancel(); 742 mStartExitAnimation = null; 743 mStartExitTransformation.clear(); 744 } 745 if (mFinishExitAnimation != null) { 746 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing finish exit anim!"); 747 mFinishExitAnimation.cancel(); 748 mFinishExitAnimation = null; 749 mFinishExitTransformation.clear(); 750 } 751 } 752 if (mRotateExitAnimation != null) { 753 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing rotate exit anim!"); 754 mRotateExitAnimation.cancel(); 755 mRotateExitAnimation = null; 756 mRotateExitTransformation.clear(); 757 } 758 } 759 760 if (!mMoreRotateEnter && (!TWO_PHASE_ANIMATION || (!mMoreStartEnter && !mMoreFinishEnter))) { 761 if (TWO_PHASE_ANIMATION) { 762 if (mStartEnterAnimation != null) { 763 if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing start enter anim!"); 764 mStartEnterAnimation.cancel(); 765 mStartEnterAnimation = null; 766 mStartEnterTransformation.clear(); 767 } 768 if (mFinishEnterAnimation != null) { 769 if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing finish enter anim!"); 770 mFinishEnterAnimation.cancel(); 771 mFinishEnterAnimation = null; 772 mFinishEnterTransformation.clear(); 773 } 774 } 775 if (mRotateEnterAnimation != null) { 776 if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing rotate enter anim!"); 777 mRotateEnterAnimation.cancel(); 778 mRotateEnterAnimation = null; 779 mRotateEnterTransformation.clear(); 780 } 781 } 782 783 if (USE_CUSTOM_BLACK_FRAME && !mMoreStartFrame && !mMoreRotateFrame && !mMoreFinishFrame) { 784 if (mStartFrameAnimation != null) { 785 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing start frame anim!"); 786 mStartFrameAnimation.cancel(); 787 mStartFrameAnimation = null; 788 mStartFrameTransformation.clear(); 789 } 790 if (mFinishFrameAnimation != null) { 791 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing finish frame anim!"); 792 mFinishFrameAnimation.cancel(); 793 mFinishFrameAnimation = null; 794 mFinishFrameTransformation.clear(); 795 } 796 if (mRotateFrameAnimation != null) { 797 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing rotate frame anim!"); 798 mRotateFrameAnimation.cancel(); 799 mRotateFrameAnimation = null; 800 mRotateFrameTransformation.clear(); 801 } 802 } 803 804 mExitTransformation.set(mRotateExitTransformation); 805 mEnterTransformation.set(mRotateEnterTransformation); 806 if (TWO_PHASE_ANIMATION) { 807 mExitTransformation.compose(mStartExitTransformation); 808 mExitTransformation.compose(mFinishExitTransformation); 809 810 mEnterTransformation.compose(mStartEnterTransformation); 811 mEnterTransformation.compose(mFinishEnterTransformation); 812 } 813 814 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation); 815 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation); 816 817 if (USE_CUSTOM_BLACK_FRAME) { 818 //mFrameTransformation.set(mRotateExitTransformation); 819 //mFrameTransformation.compose(mStartExitTransformation); 820 //mFrameTransformation.compose(mFinishExitTransformation); 821 mFrameTransformation.set(mRotateFrameTransformation); 822 mFrameTransformation.compose(mStartFrameTransformation); 823 mFrameTransformation.compose(mFinishFrameTransformation); 824 mFrameTransformation.getMatrix().preConcat(mFrameInitialMatrix); 825 if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final frame: " + mFrameTransformation); 826 } 827 828 final boolean more = (TWO_PHASE_ANIMATION 829 && (mMoreStartEnter || mMoreStartExit || mMoreFinishEnter || mMoreFinishExit)) 830 || (USE_CUSTOM_BLACK_FRAME 831 && (mMoreStartFrame || mMoreRotateFrame || mMoreFinishFrame)) 832 || mMoreRotateEnter || mMoreRotateExit 833 || !mFinishAnimReady; 834 835 mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix); 836 837 if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more); 838 839 return more; 840 } 841 842 void updateSurfaces() { 843 if (!mStarted) { 844 return; 845 } 846 847 if (mSurface != null) { 848 if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) { 849 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface"); 850 mSurface.hide(); 851 } 852 } 853 854 if (mCustomBlackFrame != null) { 855 if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) { 856 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame"); 857 mCustomBlackFrame.hide(); 858 } else { 859 mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix()); 860 } 861 } 862 863 if (mExitingBlackFrame != null) { 864 if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) { 865 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame"); 866 mExitingBlackFrame.hide(); 867 } else { 868 mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix); 869 mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix); 870 } 871 } 872 873 if (mEnteringBlackFrame != null) { 874 if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) { 875 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame"); 876 mEnteringBlackFrame.hide(); 877 } else { 878 mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix()); 879 } 880 } 881 882 setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha()); 883 } 884 885 public boolean stepAnimationLocked(long now) { 886 if (!hasAnimations()) { 887 if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running"); 888 mFinishAnimReady = false; 889 return false; 890 } 891 892 if (!mAnimRunning) { 893 if (DEBUG_STATE) Slog.v(TAG, "Step: starting start, finish, rotate"); 894 if (TWO_PHASE_ANIMATION) { 895 if (mStartEnterAnimation != null) { 896 mStartEnterAnimation.setStartTime(now); 897 } 898 if (mStartExitAnimation != null) { 899 mStartExitAnimation.setStartTime(now); 900 } 901 if (mFinishEnterAnimation != null) { 902 mFinishEnterAnimation.setStartTime(0); 903 } 904 if (mFinishExitAnimation != null) { 905 mFinishExitAnimation.setStartTime(0); 906 } 907 } 908 if (USE_CUSTOM_BLACK_FRAME) { 909 if (mStartFrameAnimation != null) { 910 mStartFrameAnimation.setStartTime(now); 911 } 912 if (mFinishFrameAnimation != null) { 913 mFinishFrameAnimation.setStartTime(0); 914 } 915 if (mRotateFrameAnimation != null) { 916 mRotateFrameAnimation.setStartTime(now); 917 } 918 } 919 if (mRotateEnterAnimation != null) { 920 mRotateEnterAnimation.setStartTime(now); 921 } 922 if (mRotateExitAnimation != null) { 923 mRotateExitAnimation.setStartTime(now); 924 } 925 mAnimRunning = true; 926 mHalfwayPoint = now + mRotateEnterAnimation.getDuration() / 2; 927 } 928 929 return stepAnimation(now); 930 } 931 932 public Transformation getEnterTransformation() { 933 return mEnterTransformation; 934 } 935} 936