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