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