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 17package com.android.server.wm; 18 19import java.io.PrintWriter; 20 21import static com.android.server.wm.WindowStateAnimator.SurfaceTrace; 22 23import android.content.Context; 24import android.graphics.Matrix; 25import android.graphics.PixelFormat; 26import android.graphics.Rect; 27import android.util.Slog; 28import android.view.Display; 29import android.view.DisplayInfo; 30import android.view.Surface.OutOfResourcesException; 31import android.view.Surface; 32import android.view.SurfaceControl; 33import android.view.SurfaceSession; 34import android.view.animation.Animation; 35import android.view.animation.AnimationUtils; 36import android.view.animation.Transformation; 37 38class ScreenRotationAnimation { 39 static final String TAG = "ScreenRotationAnimation"; 40 static final boolean DEBUG_STATE = false; 41 static final boolean DEBUG_TRANSFORMS = false; 42 static final boolean TWO_PHASE_ANIMATION = false; 43 static final boolean USE_CUSTOM_BLACK_FRAME = false; 44 45 static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200; 46 47 final Context mContext; 48 final DisplayContent mDisplayContent; 49 SurfaceControl mSurfaceControl; 50 BlackFrame mCustomBlackFrame; 51 BlackFrame mExitingBlackFrame; 52 BlackFrame mEnteringBlackFrame; 53 int mWidth, mHeight; 54 55 int mOriginalRotation; 56 int mOriginalWidth, mOriginalHeight; 57 int mCurRotation; 58 Rect mOriginalDisplayRect = new Rect(); 59 Rect mCurrentDisplayRect = new Rect(); 60 61 // For all animations, "exit" is for the UI elements that are going 62 // away (that is the snapshot of the old screen), and "enter" is for 63 // the new UI elements that are appearing (that is the active windows 64 // in their final orientation). 65 66 // The starting animation for the exiting and entering elements. This 67 // animation applies a transformation while the rotation is in progress. 68 // It is started immediately, before the new entering UI is ready. 69 Animation mStartExitAnimation; 70 final Transformation mStartExitTransformation = new Transformation(); 71 Animation mStartEnterAnimation; 72 final Transformation mStartEnterTransformation = new Transformation(); 73 Animation mStartFrameAnimation; 74 final Transformation mStartFrameTransformation = new Transformation(); 75 76 // The finishing animation for the exiting and entering elements. This 77 // animation needs to undo the transformation of the starting animation. 78 // It starts running once the new rotation UI elements are ready to be 79 // displayed. 80 Animation mFinishExitAnimation; 81 final Transformation mFinishExitTransformation = new Transformation(); 82 Animation mFinishEnterAnimation; 83 final Transformation mFinishEnterTransformation = new Transformation(); 84 Animation mFinishFrameAnimation; 85 final Transformation mFinishFrameTransformation = new Transformation(); 86 87 // The current active animation to move from the old to the new rotated 88 // state. Which animation is run here will depend on the old and new 89 // rotations. 90 Animation mRotateExitAnimation; 91 final Transformation mRotateExitTransformation = new Transformation(); 92 Animation mRotateEnterAnimation; 93 final Transformation mRotateEnterTransformation = new Transformation(); 94 Animation mRotateFrameAnimation; 95 final Transformation mRotateFrameTransformation = new Transformation(); 96 97 // A previously running rotate animation. This will be used if we need 98 // to switch to a new rotation before finishing the previous one. 99 Animation mLastRotateExitAnimation; 100 final Transformation mLastRotateExitTransformation = new Transformation(); 101 Animation mLastRotateEnterAnimation; 102 final Transformation mLastRotateEnterTransformation = new Transformation(); 103 Animation mLastRotateFrameAnimation; 104 final Transformation mLastRotateFrameTransformation = new Transformation(); 105 106 // Complete transformations being applied. 107 final Transformation mExitTransformation = new Transformation(); 108 final Transformation mEnterTransformation = new Transformation(); 109 final Transformation mFrameTransformation = new Transformation(); 110 111 boolean mStarted; 112 boolean mAnimRunning; 113 boolean mFinishAnimReady; 114 long mFinishAnimStartTime; 115 boolean mForceDefaultOrientation; 116 117 final Matrix mFrameInitialMatrix = new Matrix(); 118 final Matrix mSnapshotInitialMatrix = new Matrix(); 119 final Matrix mSnapshotFinalMatrix = new Matrix(); 120 final Matrix mExitFrameFinalMatrix = new Matrix(); 121 final Matrix mTmpMatrix = new Matrix(); 122 final float[] mTmpFloats = new float[9]; 123 private boolean mMoreRotateEnter; 124 private boolean mMoreRotateExit; 125 private boolean mMoreRotateFrame; 126 private boolean mMoreFinishEnter; 127 private boolean mMoreFinishExit; 128 private boolean mMoreFinishFrame; 129 private boolean mMoreStartEnter; 130 private boolean mMoreStartExit; 131 private boolean mMoreStartFrame; 132 long mHalfwayPoint; 133 134 public void printTo(String prefix, PrintWriter pw) { 135 pw.print(prefix); pw.print("mSurface="); pw.print(mSurfaceControl); 136 pw.print(" mWidth="); pw.print(mWidth); 137 pw.print(" mHeight="); pw.println(mHeight); 138 if (USE_CUSTOM_BLACK_FRAME) { 139 pw.print(prefix); pw.print("mCustomBlackFrame="); pw.println(mCustomBlackFrame); 140 if (mCustomBlackFrame != null) { 141 mCustomBlackFrame.printTo(prefix + " ", pw); 142 } 143 } 144 pw.print(prefix); pw.print("mExitingBlackFrame="); pw.println(mExitingBlackFrame); 145 if (mExitingBlackFrame != null) { 146 mExitingBlackFrame.printTo(prefix + " ", pw); 147 } 148 pw.print(prefix); pw.print("mEnteringBlackFrame="); pw.println(mEnteringBlackFrame); 149 if (mEnteringBlackFrame != null) { 150 mEnteringBlackFrame.printTo(prefix + " ", pw); 151 } 152 pw.print(prefix); pw.print("mCurRotation="); pw.print(mCurRotation); 153 pw.print(" mOriginalRotation="); pw.println(mOriginalRotation); 154 pw.print(prefix); pw.print("mOriginalWidth="); pw.print(mOriginalWidth); 155 pw.print(" mOriginalHeight="); pw.println(mOriginalHeight); 156 pw.print(prefix); pw.print("mStarted="); pw.print(mStarted); 157 pw.print(" mAnimRunning="); pw.print(mAnimRunning); 158 pw.print(" mFinishAnimReady="); pw.print(mFinishAnimReady); 159 pw.print(" mFinishAnimStartTime="); pw.println(mFinishAnimStartTime); 160 pw.print(prefix); pw.print("mStartExitAnimation="); pw.print(mStartExitAnimation); 161 pw.print(" "); mStartExitTransformation.printShortString(pw); pw.println(); 162 pw.print(prefix); pw.print("mStartEnterAnimation="); pw.print(mStartEnterAnimation); 163 pw.print(" "); mStartEnterTransformation.printShortString(pw); pw.println(); 164 pw.print(prefix); pw.print("mStartFrameAnimation="); pw.print(mStartFrameAnimation); 165 pw.print(" "); mStartFrameTransformation.printShortString(pw); pw.println(); 166 pw.print(prefix); pw.print("mFinishExitAnimation="); pw.print(mFinishExitAnimation); 167 pw.print(" "); mFinishExitTransformation.printShortString(pw); pw.println(); 168 pw.print(prefix); pw.print("mFinishEnterAnimation="); pw.print(mFinishEnterAnimation); 169 pw.print(" "); mFinishEnterTransformation.printShortString(pw); pw.println(); 170 pw.print(prefix); pw.print("mFinishFrameAnimation="); pw.print(mFinishFrameAnimation); 171 pw.print(" "); mFinishFrameTransformation.printShortString(pw); pw.println(); 172 pw.print(prefix); pw.print("mRotateExitAnimation="); pw.print(mRotateExitAnimation); 173 pw.print(" "); mRotateExitTransformation.printShortString(pw); pw.println(); 174 pw.print(prefix); pw.print("mRotateEnterAnimation="); pw.print(mRotateEnterAnimation); 175 pw.print(" "); mRotateEnterTransformation.printShortString(pw); pw.println(); 176 pw.print(prefix); pw.print("mRotateFrameAnimation="); pw.print(mRotateFrameAnimation); 177 pw.print(" "); mRotateFrameTransformation.printShortString(pw); pw.println(); 178 pw.print(prefix); pw.print("mExitTransformation="); 179 mExitTransformation.printShortString(pw); pw.println(); 180 pw.print(prefix); pw.print("mEnterTransformation="); 181 mEnterTransformation.printShortString(pw); pw.println(); 182 pw.print(prefix); pw.print("mFrameTransformation="); 183 mEnterTransformation.printShortString(pw); pw.println(); 184 pw.print(prefix); pw.print("mFrameInitialMatrix="); 185 mFrameInitialMatrix.printShortString(pw); 186 pw.println(); 187 pw.print(prefix); pw.print("mSnapshotInitialMatrix="); 188 mSnapshotInitialMatrix.printShortString(pw); 189 pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw); 190 pw.println(); 191 pw.print(prefix); pw.print("mExitFrameFinalMatrix="); 192 mExitFrameFinalMatrix.printShortString(pw); 193 pw.println(); 194 pw.print(prefix); pw.print("mForceDefaultOrientation="); pw.print(mForceDefaultOrientation); 195 if (mForceDefaultOrientation) { 196 pw.print(" mOriginalDisplayRect="); pw.print(mOriginalDisplayRect.toShortString()); 197 pw.print(" mCurrentDisplayRect="); pw.println(mCurrentDisplayRect.toShortString()); 198 } 199 } 200 201 public ScreenRotationAnimation(Context context, DisplayContent displayContent, 202 SurfaceSession session, boolean inTransaction, boolean forceDefaultOrientation, 203 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 290 boolean hasScreenshot() { 291 return mSurfaceControl != null; 292 } 293 294 static int deltaRotation(int oldRotation, int newRotation) { 295 int delta = newRotation - oldRotation; 296 if (delta < 0) delta += 4; 297 return delta; 298 } 299 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 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. 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. 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 */ 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 */ 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 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 717 public boolean isAnimating() { 718 return hasAnimations() || (TWO_PHASE_ANIMATION && mFinishAnimReady); 719 } 720 721 public boolean isRotating() { 722 return mCurRotation != mOriginalRotation; 723 } 724 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 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 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 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 1007 public Transformation getEnterTransformation() { 1008 return mEnterTransformation; 1009 } 1010} 1011