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