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