1 /* 2 * Copyright (C) 2017 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.SurfaceAnimatorProto.ANIMATION_ADAPTER; 20 import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_START_DELAYED; 21 import static com.android.server.wm.SurfaceAnimatorProto.LEASH; 22 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 23 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 24 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 25 26 import android.annotation.IntDef; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.util.Slog; 30 import android.util.proto.ProtoOutputStream; 31 import android.view.SurfaceControl; 32 import android.view.SurfaceControl.Transaction; 33 34 import com.android.internal.annotations.VisibleForTesting; 35 36 import java.io.PrintWriter; 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 import java.util.function.Supplier; 40 41 /** 42 * A class that can run animations on objects that have a set of child surfaces. We do this by 43 * reparenting all child surfaces of an object onto a new surface, called the "Leash". The Leash 44 * gets attached in the surface hierarchy where the the children were attached to. We then hand off 45 * the Leash to the component handling the animation, which is specified by the 46 * {@link AnimationAdapter}. When the animation is done animating, our callback to finish the 47 * animation will be invoked, at which we reparent the children back to the original parent. 48 */ 49 class SurfaceAnimator { 50 51 private static final String TAG = TAG_WITH_CLASS_NAME ? "SurfaceAnimator" : TAG_WM; 52 53 private final WindowManagerService mService; 54 private AnimationAdapter mAnimation; 55 private @AnimationType int mAnimationType; 56 57 @VisibleForTesting 58 SurfaceControl mLeash; 59 @VisibleForTesting 60 SurfaceFreezer.Snapshot mSnapshot; 61 @VisibleForTesting 62 final Animatable mAnimatable; 63 @VisibleForTesting 64 final OnAnimationFinishedCallback mInnerAnimationFinishedCallback; 65 66 /** 67 * Static callback to run on all animations started through this SurfaceAnimator 68 * when an animation on a Surface is finished or cancelled without restart. 69 */ 70 @VisibleForTesting 71 @Nullable 72 final OnAnimationFinishedCallback mStaticAnimationFinishedCallback; 73 74 /** 75 * Callback unique to each animation (i.e. AnimationAdapter). To be run when an animation on a 76 * Surface is finished or cancelled without restart. 77 */ 78 @Nullable 79 private OnAnimationFinishedCallback mSurfaceAnimationFinishedCallback; 80 81 /** 82 * The callback is triggered after the SurfaceAnimator sends a cancel call to the underlying 83 * AnimationAdapter. 84 * NOTE: Must be called wherever we call onAnimationCancelled on mAnimation. 85 */ 86 @Nullable 87 private Runnable mAnimationCancelledCallback; 88 89 private boolean mAnimationStartDelayed; 90 91 /** 92 * @param animatable The object to animate. 93 * @param staticAnimationFinishedCallback Callback to invoke when an animation has finished 94 * running. 95 */ SurfaceAnimator(Animatable animatable, @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback, WindowManagerService service)96 SurfaceAnimator(Animatable animatable, 97 @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback, 98 WindowManagerService service) { 99 mAnimatable = animatable; 100 mService = service; 101 mStaticAnimationFinishedCallback = staticAnimationFinishedCallback; 102 mInnerAnimationFinishedCallback = getFinishedCallback(staticAnimationFinishedCallback); 103 } 104 getFinishedCallback( @ullable OnAnimationFinishedCallback staticAnimationFinishedCallback)105 private OnAnimationFinishedCallback getFinishedCallback( 106 @Nullable OnAnimationFinishedCallback staticAnimationFinishedCallback) { 107 return (type, anim) -> { 108 synchronized (mService.mGlobalLock) { 109 final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim); 110 if (target != null) { 111 target.mInnerAnimationFinishedCallback.onAnimationFinished(type, anim); 112 return; 113 } 114 115 if (anim != mAnimation) { 116 return; 117 } 118 final Runnable resetAndInvokeFinish = () -> { 119 // We need to check again if the animation has been replaced with a new 120 // animation because the animatable may defer to finish. 121 if (anim != mAnimation) { 122 return; 123 } 124 final OnAnimationFinishedCallback animationFinishCallback = 125 mSurfaceAnimationFinishedCallback; 126 reset(mAnimatable.getPendingTransaction(), true /* destroyLeash */); 127 if (staticAnimationFinishedCallback != null) { 128 staticAnimationFinishedCallback.onAnimationFinished(type, anim); 129 } 130 if (animationFinishCallback != null) { 131 animationFinishCallback.onAnimationFinished(type, anim); 132 } 133 }; 134 // If both the Animatable and AnimationAdapter requests to be deferred, only the 135 // first one will be called. 136 if (!(mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish) 137 || anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) { 138 resetAndInvokeFinish.run(); 139 } 140 } 141 }; 142 } 143 144 /** 145 * Starts an animation. 146 * 147 * @param anim The object that bridges the controller, {@link SurfaceAnimator}, with the 148 * component responsible for running the animation. It runs the animation with 149 * {@link AnimationAdapter#startAnimation} once the hierarchy with 150 * the Leash has been set up. 151 * @param hidden Whether the container holding the child surfaces is currently visible or not. 152 * This is important as it will start with the leash hidden or visible before 153 * handing it to the component that is responsible to run the animation. 154 * @param animationFinishedCallback The callback being triggered when the animation finishes. 155 * @param animationCancelledCallback The callback is triggered after the SurfaceAnimator sends a 156 * cancel call to the underlying AnimationAdapter. 157 * @param snapshotAnim The animation to run for the snapshot. {@code null} if there is no 158 * snapshot. 159 */ 160 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, 161 @AnimationType int type, 162 @Nullable OnAnimationFinishedCallback animationFinishedCallback, 163 @Nullable Runnable animationCancelledCallback, 164 @Nullable AnimationAdapter snapshotAnim, @Nullable SurfaceFreezer freezer) { 165 cancelAnimation(t, true /* restarting */, true /* forwardCancel */); 166 mAnimation = anim; 167 mAnimationType = type; 168 mSurfaceAnimationFinishedCallback = animationFinishedCallback; 169 mAnimationCancelledCallback = animationCancelledCallback; 170 final SurfaceControl surface = mAnimatable.getSurfaceControl(); 171 if (surface == null) { 172 Slog.w(TAG, "Unable to start animation, surface is null or no children."); 173 cancelAnimation(); 174 return; 175 } 176 mLeash = freezer != null ? freezer.takeLeashForAnimation() : null; 177 if (mLeash == null) { 178 mLeash = createAnimationLeash(mAnimatable, surface, t, type, 179 mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */, 180 0 /* y */, hidden, mService.mTransactionFactory); 181 mAnimatable.onAnimationLeashCreated(t, mLeash); 182 } 183 mAnimatable.onLeashAnimationStarting(t, mLeash); 184 if (mAnimationStartDelayed) { 185 if (DEBUG_ANIM) Slog.i(TAG, "Animation start delayed"); 186 return; 187 } 188 mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback); 189 if (snapshotAnim != null) { 190 mSnapshot = freezer.takeSnapshotForAnimation(); 191 if (mSnapshot == null) { 192 Slog.e(TAG, "No snapshot target to start animation on for " + mAnimatable); 193 return; 194 } 195 mSnapshot.startAnimation(t, snapshotAnim, type); 196 } 197 } 198 199 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, 200 @AnimationType int type) { 201 startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */, 202 null /* animationCancelledCallback */, null /* snapshotAnim */, null /* freezer */); 203 } 204 205 /** 206 * Begins with delaying all animations to start. Any subsequent call to {@link #startAnimation} 207 * will not start the animation until {@link #endDelayingAnimationStart} is called. When an 208 * animation start is being delayed, the animator is considered animating already. 209 */ 210 void startDelayingAnimationStart() { 211 212 // We only allow delaying animation start we are not currently animating 213 if (!isAnimating()) { 214 mAnimationStartDelayed = true; 215 } 216 } 217 218 /** 219 * See {@link #startDelayingAnimationStart}. 220 */ 221 void endDelayingAnimationStart() { 222 final boolean delayed = mAnimationStartDelayed; 223 mAnimationStartDelayed = false; 224 if (delayed && mAnimation != null) { 225 mAnimation.startAnimation(mLeash, mAnimatable.getPendingTransaction(), 226 mAnimationType, mInnerAnimationFinishedCallback); 227 mAnimatable.commitPendingTransaction(); 228 } 229 } 230 231 /** 232 * @return Whether we are currently running an animation, or we have a pending animation that 233 * is waiting to be started with {@link #endDelayingAnimationStart} 234 */ 235 boolean isAnimating() { 236 return mAnimation != null; 237 } 238 239 @AnimationType 240 int getAnimationType() { 241 return mAnimationType; 242 } 243 244 /** 245 * @return The current animation spec if we are running an animation, or {@code null} otherwise. 246 */ 247 AnimationAdapter getAnimation() { 248 return mAnimation; 249 } 250 251 /** 252 * Cancels any currently running animation. 253 */ 254 void cancelAnimation() { 255 cancelAnimation(mAnimatable.getPendingTransaction(), false /* restarting */, 256 true /* forwardCancel */); 257 mAnimatable.commitPendingTransaction(); 258 } 259 260 /** 261 * Sets the layer of the surface. 262 * <p> 263 * When the layer of the surface needs to be adjusted, we need to set it on the leash if the 264 * surface is reparented to the leash. This method takes care of that. 265 */ 266 void setLayer(Transaction t, int layer) { 267 t.setLayer(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), layer); 268 } 269 270 /** 271 * Sets the surface to be relatively layered. 272 * 273 * @see #setLayer 274 */ 275 void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) { 276 t.setRelativeLayer(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), relativeTo, layer); 277 } 278 279 /** 280 * Reparents the surface. 281 * 282 * @see #setLayer 283 */ 284 void reparent(Transaction t, SurfaceControl newParent) { 285 t.reparent(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), newParent); 286 } 287 288 /** 289 * @return True if the surface is attached to the leash; false otherwise. 290 */ 291 boolean hasLeash() { 292 return mLeash != null; 293 } 294 295 void transferAnimation(SurfaceAnimator from) { 296 if (from.mLeash == null) { 297 return; 298 } 299 final SurfaceControl surface = mAnimatable.getSurfaceControl(); 300 final SurfaceControl parent = mAnimatable.getAnimationLeashParent(); 301 if (surface == null || parent == null) { 302 Slog.w(TAG, "Unable to transfer animation, surface or parent is null"); 303 cancelAnimation(); 304 return; 305 } 306 endDelayingAnimationStart(); 307 final Transaction t = mAnimatable.getPendingTransaction(); 308 cancelAnimation(t, true /* restarting */, true /* forwardCancel */); 309 mLeash = from.mLeash; 310 mAnimation = from.mAnimation; 311 mAnimationType = from.mAnimationType; 312 mSurfaceAnimationFinishedCallback = from.mSurfaceAnimationFinishedCallback; 313 mAnimationCancelledCallback = from.mAnimationCancelledCallback; 314 315 // Cancel source animation, but don't let animation runner cancel the animation. 316 from.cancelAnimation(t, false /* restarting */, false /* forwardCancel */); 317 t.reparent(surface, mLeash); 318 t.reparent(mLeash, parent); 319 mAnimatable.onAnimationLeashCreated(t, mLeash); 320 mService.mAnimationTransferMap.put(mAnimation, this); 321 } 322 323 boolean isAnimationStartDelayed() { 324 return mAnimationStartDelayed; 325 } 326 327 /** 328 * Cancels the animation, and resets the leash. 329 * 330 * @param t The transaction to use for all cancelling surface operations. 331 * @param restarting Whether we are restarting the animation. 332 * @param forwardCancel Whether to forward the cancel signal to the adapter executing the 333 * animation. This will be set to false when just transferring an animation 334 * to another animator. 335 */ 336 private void cancelAnimation(Transaction t, boolean restarting, boolean forwardCancel) { 337 if (DEBUG_ANIM) Slog.i(TAG, "Cancelling animation restarting=" + restarting); 338 final SurfaceControl leash = mLeash; 339 final AnimationAdapter animation = mAnimation; 340 final @AnimationType int animationType = mAnimationType; 341 final OnAnimationFinishedCallback animationFinishedCallback = 342 mSurfaceAnimationFinishedCallback; 343 final Runnable animationCancelledCallback = mAnimationCancelledCallback; 344 final SurfaceFreezer.Snapshot snapshot = mSnapshot; 345 reset(t, false); 346 if (animation != null) { 347 if (!mAnimationStartDelayed && forwardCancel) { 348 animation.onAnimationCancelled(leash); 349 if (animationCancelledCallback != null) { 350 animationCancelledCallback.run(); 351 } 352 } 353 if (!restarting) { 354 if (mStaticAnimationFinishedCallback != null) { 355 mStaticAnimationFinishedCallback.onAnimationFinished(animationType, animation); 356 } 357 if (animationFinishedCallback != null) { 358 animationFinishedCallback.onAnimationFinished(animationType, animation); 359 } 360 } 361 } 362 363 if (forwardCancel) { 364 if (snapshot != null) { 365 snapshot.cancelAnimation(t, false /* restarting */); 366 } 367 if (leash != null) { 368 t.remove(leash); 369 mService.scheduleAnimationLocked(); 370 } 371 } 372 373 if (!restarting) { 374 mAnimationStartDelayed = false; 375 } 376 } 377 378 private void reset(Transaction t, boolean destroyLeash) { 379 mService.mAnimationTransferMap.remove(mAnimation); 380 mAnimation = null; 381 mSurfaceAnimationFinishedCallback = null; 382 mAnimationType = ANIMATION_TYPE_NONE; 383 final SurfaceFreezer.Snapshot snapshot = mSnapshot; 384 mSnapshot = null; 385 if (snapshot != null) { 386 // Reset the mSnapshot reference before calling the callback to prevent circular reset. 387 snapshot.cancelAnimation(t, !destroyLeash); 388 } 389 if (mLeash == null) { 390 return; 391 } 392 SurfaceControl leash = mLeash; 393 mLeash = null; 394 final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash); 395 if (scheduleAnim) { 396 mService.scheduleAnimationLocked(); 397 } 398 } 399 400 static boolean removeLeash(Transaction t, Animatable animatable, @NonNull SurfaceControl leash, 401 boolean destroy) { 402 boolean scheduleAnim = false; 403 final SurfaceControl surface = animatable.getSurfaceControl(); 404 final SurfaceControl parent = animatable.getParentSurfaceControl(); 405 final SurfaceControl curAnimationLeash = animatable.getAnimationLeash(); 406 407 // If the surface was destroyed or the leash is invalid, we don't care to reparent it back. 408 // Note that we also set this variable to true even if the parent isn't valid anymore, in 409 // order to ensure onAnimationLeashLost still gets called in this case. 410 // If the animation leash is set, and it is different from the removing leash, it means the 411 // surface now has a new animation surface. We don't want to reparent for that. 412 final boolean reparent = surface != null && (curAnimationLeash == null 413 || curAnimationLeash.equals(leash)); 414 if (reparent) { 415 if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent: " + parent); 416 // We shouldn't really need these isValid checks but we do 417 // b/130364451 418 if (surface.isValid() && parent != null && parent.isValid()) { 419 t.reparent(surface, parent); 420 scheduleAnim = true; 421 } 422 } 423 if (destroy) { 424 t.remove(leash); 425 scheduleAnim = true; 426 } 427 428 if (reparent) { 429 // Make sure to inform the animatable after the surface was reparented (or reparent 430 // wasn't possible, but we still need to invoke the callback) 431 animatable.onAnimationLeashLost(t); 432 scheduleAnim = true; 433 } 434 return scheduleAnim; 435 } 436 437 static SurfaceControl createAnimationLeash(Animatable animatable, SurfaceControl surface, 438 Transaction t, @AnimationType int type, int width, int height, int x, int y, 439 boolean hidden, Supplier<Transaction> transactionFactory) { 440 if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash"); 441 final SurfaceControl.Builder builder = animatable.makeAnimationLeash() 442 .setParent(animatable.getAnimationLeashParent()) 443 .setName(surface + " - animation-leash of " + animationTypeToString(type)) 444 // TODO(b/151665759) Defer reparent calls 445 // We want the leash to be visible immediately because the transaction which shows 446 // the leash may be deferred but the reparent will not. This will cause the leashed 447 // surface to be invisible until the deferred transaction is applied. If this 448 // doesn't work, you will can see the 2/3 button nav bar flicker during seamless 449 // rotation. 450 .setHidden(hidden) 451 .setEffectLayer() 452 .setCallsite("SurfaceAnimator.createAnimationLeash"); 453 final SurfaceControl leash = builder.build(); 454 t.setWindowCrop(leash, width, height); 455 t.setPosition(leash, x, y); 456 t.show(leash); 457 t.setAlpha(leash, hidden ? 0 : 1); 458 459 t.reparent(surface, leash); 460 return leash; 461 } 462 463 /** 464 * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link 465 * com.android.server.wm.SurfaceAnimatorProto}. 466 * 467 * @param proto Stream to write the SurfaceAnimator object to. 468 * @param fieldId Field Id of the SurfaceAnimator as defined in the parent message. 469 * @hide 470 */ 471 void dumpDebug(ProtoOutputStream proto, long fieldId) { 472 final long token = proto.start(fieldId); 473 if (mAnimation != null) { 474 mAnimation.dumpDebug(proto, ANIMATION_ADAPTER); 475 } 476 if (mLeash != null) { 477 mLeash.dumpDebug(proto, LEASH); 478 } 479 proto.write(ANIMATION_START_DELAYED, mAnimationStartDelayed); 480 proto.end(token); 481 } 482 483 void dump(PrintWriter pw, String prefix) { 484 pw.print(prefix); pw.print("mLeash="); pw.print(mLeash); 485 pw.print(" mAnimationType=" + animationTypeToString(mAnimationType)); 486 pw.println(mAnimationStartDelayed ? " mAnimationStartDelayed=true" : ""); 487 pw.print(prefix); pw.print("Animation: "); pw.println(mAnimation); 488 if (mAnimation != null) { 489 mAnimation.dump(pw, prefix + " "); 490 } 491 } 492 493 494 /** 495 * No animation is specified. 496 * @hide 497 */ 498 public static final int ANIMATION_TYPE_NONE = 0; 499 500 /** 501 * Animation for an app transition. 502 * @hide 503 */ 504 public static final int ANIMATION_TYPE_APP_TRANSITION = 1; 505 506 /** 507 * Animation for screen rotation. 508 * @hide 509 */ 510 public static final int ANIMATION_TYPE_SCREEN_ROTATION = 1 << 1; 511 512 /** 513 * Animation for dimming. 514 * @hide 515 */ 516 public static final int ANIMATION_TYPE_DIMMER = 1 << 2; 517 518 /** 519 * Animation for recent apps. 520 * @hide 521 */ 522 public static final int ANIMATION_TYPE_RECENTS = 1 << 3; 523 524 /** 525 * Animation for a {@link WindowState} without animating the activity. 526 * @hide 527 */ 528 public static final int ANIMATION_TYPE_WINDOW_ANIMATION = 1 << 4; 529 530 /** 531 * Animation to control insets. This is actually not an animation, but is used to give the 532 * client a leash over the system window causing insets. 533 * @hide 534 */ 535 public static final int ANIMATION_TYPE_INSETS_CONTROL = 1 << 5; 536 537 /** 538 * Animation when a fixed rotation transform is applied to a window token. 539 * @hide 540 */ 541 public static final int ANIMATION_TYPE_FIXED_TRANSFORM = 1 << 6; 542 543 /** 544 * Animation when a reveal starting window animation is applied to app window. 545 * @hide 546 */ 547 public static final int ANIMATION_TYPE_STARTING_REVEAL = 1 << 7; 548 549 /** 550 * Bitmask to include all animation types. This is NOT an {@link AnimationType} 551 * @hide 552 */ 553 public static final int ANIMATION_TYPE_ALL = -1; 554 555 /** 556 * The type of the animation. 557 * @hide 558 */ 559 @IntDef(flag = true, prefix = { "ANIMATION_TYPE_" }, value = { 560 ANIMATION_TYPE_NONE, 561 ANIMATION_TYPE_APP_TRANSITION, 562 ANIMATION_TYPE_SCREEN_ROTATION, 563 ANIMATION_TYPE_DIMMER, 564 ANIMATION_TYPE_RECENTS, 565 ANIMATION_TYPE_WINDOW_ANIMATION, 566 ANIMATION_TYPE_INSETS_CONTROL, 567 ANIMATION_TYPE_FIXED_TRANSFORM, 568 ANIMATION_TYPE_STARTING_REVEAL 569 }) 570 @Retention(RetentionPolicy.SOURCE) 571 @interface AnimationType {} 572 573 /** 574 * Converts {@link AnimationType} to String. 575 */ 576 static String animationTypeToString(@AnimationType int type) { 577 switch (type) { 578 case ANIMATION_TYPE_NONE: return "none"; 579 case ANIMATION_TYPE_APP_TRANSITION: return "app_transition"; 580 case ANIMATION_TYPE_SCREEN_ROTATION: return "screen_rotation"; 581 case ANIMATION_TYPE_DIMMER: return "dimmer"; 582 case ANIMATION_TYPE_RECENTS: return "recents_animation"; 583 case ANIMATION_TYPE_WINDOW_ANIMATION: return "window_animation"; 584 case ANIMATION_TYPE_INSETS_CONTROL: return "insets_animation"; 585 case ANIMATION_TYPE_FIXED_TRANSFORM: return "fixed_rotation"; 586 case ANIMATION_TYPE_STARTING_REVEAL: return "starting_reveal"; 587 default: return "unknown type:" + type; 588 } 589 } 590 591 /** 592 * Callback to be passed into {@link AnimationAdapter#startAnimation} to be invoked by the 593 * component that is running the animation when the animation is finished. 594 */ 595 interface OnAnimationFinishedCallback { 596 void onAnimationFinished(@AnimationType int type, AnimationAdapter anim); 597 } 598 599 /** 600 * Interface to be animated by {@link SurfaceAnimator}. 601 */ 602 interface Animatable { 603 604 /** 605 * @return The pending transaction that will be committed in the next frame. 606 */ 607 @NonNull Transaction getPendingTransaction(); 608 609 /** 610 * Schedules a commit of the pending transaction. 611 */ 612 void commitPendingTransaction(); 613 614 /** 615 * Called when the animation leash is created. Note that this is also called by 616 * {@link SurfaceFreezer}, so this doesn't mean we're about to start animating. 617 * 618 * @param t The transaction to use to apply any necessary changes. 619 * @param leash The leash that was created. 620 */ 621 void onAnimationLeashCreated(Transaction t, SurfaceControl leash); 622 623 /** 624 * Called when the animator is about to start animating the leash. 625 * 626 * @param t The transaction to use to apply any necessary changes. 627 * @param leash The leash that was created. 628 */ 629 default void onLeashAnimationStarting(Transaction t, SurfaceControl leash) { } 630 631 /** 632 * Called when the leash is being destroyed, or when the leash is being transferred to 633 * another SurfaceAnimator. 634 * 635 * @param t The transaction to use to apply any necessary changes. 636 */ 637 void onAnimationLeashLost(Transaction t); 638 639 /** 640 * Gets the last created animation leash that has not lost yet. 641 */ 642 @Nullable 643 default SurfaceControl getAnimationLeash() { 644 return null; 645 } 646 647 /** 648 * @return A new surface to be used for the animation leash, inserted at the correct 649 * position in the hierarchy. 650 */ 651 SurfaceControl.Builder makeAnimationLeash(); 652 653 /** 654 * @return The parent that should be used for the animation leash. 655 */ 656 @Nullable SurfaceControl getAnimationLeashParent(); 657 658 /** 659 * @return The surface of the object to be animated. 660 * This SurfaceControl must be valid if non-null. 661 */ 662 @Nullable SurfaceControl getSurfaceControl(); 663 664 /** 665 * @return The parent of the surface object to be animated. 666 * This SurfaceControl must be valid if non-null. 667 */ 668 @Nullable SurfaceControl getParentSurfaceControl(); 669 670 /** 671 * @return The width of the surface to be animated. 672 */ 673 int getSurfaceWidth(); 674 675 /** 676 * @return The height of the surface to be animated. 677 */ 678 int getSurfaceHeight(); 679 680 /** 681 * Gets called when the animation is about to finish and gives the client the opportunity to 682 * defer finishing the animation, i.e. it keeps the leash around until the client calls 683 * {@link #cancelAnimation}. 684 * <p> 685 * {@link AnimationAdapter} has a similar method which is called only if this method returns 686 * false. This mean that if both this {@link Animatable} and the {@link AnimationAdapter} 687 * request to be deferred, this method is the sole responsible to call 688 * endDeferFinishCallback. On the other hand, the animation finish might still be deferred 689 * if this method return false and the one from the {@link AnimationAdapter} returns true. 690 * 691 * @param endDeferFinishCallback The callback to call when defer finishing should be ended. 692 * @return Whether the client would like to defer the animation finish. 693 */ 694 default boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) { 695 return false; 696 } 697 } 698 } 699