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