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