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