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