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 printTo(String prefix, PrintWriter pw)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 ScreenRotationAnimation(Context context, DisplayContent displayContent, SurfaceSession session, boolean inTransaction, boolean forceDefaultOrientation, boolean isSecure)201 public ScreenRotationAnimation(Context context, DisplayContent displayContent, 202 SurfaceSession session, boolean inTransaction, boolean forceDefaultOrientation, 203 boolean isSecure) { 204 mContext = context; 205 mDisplayContent = displayContent; 206 displayContent.getLogicalDisplayRect(mOriginalDisplayRect); 207 208 // Screenshot does NOT include rotation! 209 final Display display = displayContent.getDisplay(); 210 int originalRotation = display.getRotation(); 211 final int originalWidth; 212 final int originalHeight; 213 DisplayInfo displayInfo = displayContent.getDisplayInfo(); 214 if (forceDefaultOrientation) { 215 // Emulated orientation. 216 mForceDefaultOrientation = true; 217 originalWidth = displayContent.mBaseDisplayWidth; 218 originalHeight = displayContent.mBaseDisplayHeight; 219 } else { 220 // Normal situation 221 originalWidth = displayInfo.logicalWidth; 222 originalHeight = displayInfo.logicalHeight; 223 } 224 if (originalRotation == Surface.ROTATION_90 225 || originalRotation == Surface.ROTATION_270) { 226 mWidth = originalHeight; 227 mHeight = originalWidth; 228 } else { 229 mWidth = originalWidth; 230 mHeight = originalHeight; 231 } 232 233 mOriginalRotation = originalRotation; 234 mOriginalWidth = originalWidth; 235 mOriginalHeight = originalHeight; 236 237 if (!inTransaction) { 238 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG, 239 ">>> OPEN TRANSACTION ScreenRotationAnimation"); 240 SurfaceControl.openTransaction(); 241 } 242 243 try { 244 try { 245 int flags = SurfaceControl.HIDDEN; 246 if (isSecure) { 247 flags |= SurfaceControl.SECURE; 248 } 249 250 if (WindowManagerService.DEBUG_SURFACE_TRACE) { 251 mSurfaceControl = new SurfaceTrace(session, "ScreenshotSurface", 252 mWidth, mHeight, 253 PixelFormat.OPAQUE, flags); 254 Slog.w(TAG, "ScreenRotationAnimation ctor: displayOffset=" 255 + mOriginalDisplayRect.toShortString()); 256 } else { 257 mSurfaceControl = new SurfaceControl(session, "ScreenshotSurface", 258 mWidth, mHeight, 259 PixelFormat.OPAQUE, flags); 260 } 261 // capture a screenshot into the surface we just created 262 Surface sur = new Surface(); 263 sur.copyFrom(mSurfaceControl); 264 // FIXME: we should use the proper display 265 SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay( 266 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur); 267 mSurfaceControl.setLayerStack(display.getLayerStack()); 268 mSurfaceControl.setLayer(FREEZE_LAYER + 1); 269 mSurfaceControl.setAlpha(0); 270 mSurfaceControl.show(); 271 sur.destroy(); 272 } catch (OutOfResourcesException e) { 273 Slog.w(TAG, "Unable to allocate freeze surface", e); 274 } 275 276 if (WindowManagerService.SHOW_TRANSACTIONS || 277 WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, 278 " FREEZE " + mSurfaceControl + ": CREATE"); 279 280 setRotationInTransaction(originalRotation); 281 } finally { 282 if (!inTransaction) { 283 SurfaceControl.closeTransaction(); 284 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG, 285 "<<< CLOSE TRANSACTION ScreenRotationAnimation"); 286 } 287 } 288 } 289 hasScreenshot()290 boolean hasScreenshot() { 291 return mSurfaceControl != null; 292 } 293 setSnapshotTransformInTransaction(Matrix matrix, float alpha)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 createRotationMatrix(int rotation, int width, int height, Matrix outMatrix)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. setRotationInTransaction(int rotation)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 = DisplayContent.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. setRotationInTransaction(int rotation, SurfaceSession session, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight)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 */ startAnimation(SurfaceSession session, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight, boolean dismissing, int exitAnim, int enterAnim)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 = DisplayContent.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 */ dismiss(SurfaceSession session, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight, int exitAnim, int enterAnim)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 kill()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 isAnimating()711 public boolean isAnimating() { 712 return hasAnimations() || (TWO_PHASE_ANIMATION && mFinishAnimReady); 713 } 714 isRotating()715 public boolean isRotating() { 716 return mCurRotation != mOriginalRotation; 717 } 718 hasAnimations()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 stepAnimation(long now)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 updateSurfacesInTransaction()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 stepAnimationLocked(long now)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 getEnterTransformation()1001 public Transformation getEnterTransformation() { 1002 return mEnterTransformation; 1003 } 1004 } 1005