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