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