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