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