• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 android.window;
18 
19 import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
20 import static android.app.ActivityOptions.ANIM_CUSTOM;
21 import static android.app.ActivityOptions.ANIM_FROM_STYLE;
22 import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
23 import static android.app.ActivityOptions.ANIM_SCALE_UP;
24 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
25 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
26 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
27 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
28 import static android.view.Display.INVALID_DISPLAY;
29 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
30 import static android.view.WindowManager.TRANSIT_CHANGE;
31 import static android.view.WindowManager.TRANSIT_CLOSE;
32 import static android.view.WindowManager.TRANSIT_FLAG_AOD_APPEARING;
33 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
34 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
35 import static android.view.WindowManager.TRANSIT_NONE;
36 import static android.view.WindowManager.TRANSIT_OPEN;
37 import static android.view.WindowManager.TRANSIT_TO_BACK;
38 import static android.view.WindowManager.TRANSIT_TO_FRONT;
39 import static android.view.WindowManager.TransitionFlags;
40 import static android.view.WindowManager.TransitionType;
41 import static android.view.WindowManager.transitTypeToString;
42 
43 import android.annotation.AnimRes;
44 import android.annotation.ColorInt;
45 import android.annotation.IntDef;
46 import android.annotation.NonNull;
47 import android.annotation.Nullable;
48 import android.app.ActivityManager;
49 import android.content.ComponentName;
50 import android.graphics.Point;
51 import android.graphics.Rect;
52 import android.hardware.HardwareBuffer;
53 import android.os.BinderProxy;
54 import android.os.IBinder;
55 import android.os.Parcel;
56 import android.os.Parcelable;
57 import android.view.Surface;
58 import android.view.SurfaceControl;
59 import android.view.WindowManager;
60 
61 import java.lang.annotation.Retention;
62 import java.lang.annotation.RetentionPolicy;
63 import java.util.ArrayList;
64 import java.util.List;
65 import java.util.Objects;
66 
67 /**
68  * Used to communicate information about what is changing during a transition to a TransitionPlayer.
69  * @hide
70  */
71 public final class TransitionInfo implements Parcelable {
72     private static final String TAG = "TransitionInfo";
73 
74     /**
75      * Modes are only a sub-set of all the transit-types since they are per-container
76      * @hide
77      */
78     @Retention(RetentionPolicy.SOURCE)
79     @IntDef(prefix = { "TRANSIT_" }, value = {
80             TRANSIT_NONE,
81             TRANSIT_OPEN,
82             TRANSIT_CLOSE,
83             // Note: to_front/to_back really mean show/hide respectively at the container level.
84             TRANSIT_TO_FRONT,
85             TRANSIT_TO_BACK,
86             TRANSIT_CHANGE
87     })
88     public @interface TransitionMode {}
89 
90     /** No flags */
91     public static final int FLAG_NONE = 0;
92 
93     /** The container shows the wallpaper behind it. */
94     public static final int FLAG_SHOW_WALLPAPER = 1;
95 
96     /** The container IS the wallpaper. */
97     public static final int FLAG_IS_WALLPAPER = 1 << 1;
98 
99     /** The container is translucent. */
100     public static final int FLAG_TRANSLUCENT = 1 << 2;
101 
102     // TODO: remove when starting-window is moved to Task
103     /** The container is the recipient of a transferred starting-window */
104     public static final int FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT = 1 << 3;
105 
106     /** The container has voice session. */
107     public static final int FLAG_IS_VOICE_INTERACTION = 1 << 4;
108 
109     /** The container is the display. */
110     public static final int FLAG_IS_DISPLAY = 1 << 5;
111 
112     // TODO(b/194540864): Once we can include all windows in transition, then replace this with
113     // something like FLAG_IS_SYSTEM_ALERT instead. Then we can do mixed rotations.
114     /**
115      * Only for IS_DISPLAY containers. Is set if the display has system alert windows. This is
116      * used to prevent seamless rotation.
117      */
118     public static final int FLAG_DISPLAY_HAS_ALERT_WINDOWS = 1 << 7;
119 
120     /** The container is an input-method window. */
121     public static final int FLAG_IS_INPUT_METHOD = 1 << 8;
122 
123     /** The container is in a Task with embedded activity. */
124     public static final int FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY = 1 << 9;
125 
126     /** The container fills its parent Task before and after the transition. */
127     public static final int FLAG_FILLS_TASK = 1 << 10;
128 
129     /** The container is going to show IME on its task after the transition. */
130     public static final int FLAG_WILL_IME_SHOWN = 1 << 11;
131 
132     /** The container attaches owner profile thumbnail for cross profile animation. */
133     public static final int FLAG_CROSS_PROFILE_OWNER_THUMBNAIL = 1 << 12;
134 
135     /** The container attaches work profile thumbnail for cross profile animation. */
136     public static final int FLAG_CROSS_PROFILE_WORK_THUMBNAIL = 1 << 13;
137 
138     /**
139      * Whether the window is covered by an app starting window. This is different from
140      * {@link #FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT} which is only set on the Activity window
141      * that contains the starting window.
142      */
143     public static final int FLAG_IS_BEHIND_STARTING_WINDOW = 1 << 14;
144 
145     /** This change happened underneath something else. */
146     public static final int FLAG_IS_OCCLUDED = 1 << 15;
147 
148     /** The container is a system window, excluding wallpaper and input-method. */
149     public static final int FLAG_IS_SYSTEM_WINDOW = 1 << 16;
150 
151     /** The window was animated by back gesture. */
152     public static final int FLAG_BACK_GESTURE_ANIMATED = 1 << 17;
153 
154     /** The window should have no animation (by policy). */
155     public static final int FLAG_NO_ANIMATION = 1 << 18;
156 
157     /** The task is launching behind home. */
158     public static final int FLAG_TASK_LAUNCHING_BEHIND = 1 << 19;
159 
160     /** The task became the top-most task even if it didn't change visibility. */
161     public static final int FLAG_MOVED_TO_TOP = 1 << 20;
162 
163     /**
164      * This transition must be the only transition when it starts (ie. it must wait for all other
165      * transition animations to finish).
166      */
167     public static final int FLAG_SYNC = 1 << 21;
168 
169     /** This change represents its start configuration for the duration of the animation. */
170     public static final int FLAG_CONFIG_AT_END = 1 << 22;
171 
172     /** This change represents one of a Task Display Area. */
173     public static final int FLAG_IS_TASK_DISPLAY_AREA = 1 << 23;
174 
175     /** The first unused bit. This can be used by remotes to attach custom flags to this change. */
176     public static final int FLAG_FIRST_CUSTOM = 1 << 24;
177 
178     /** The change belongs to a window that won't contain activities. */
179     public static final int FLAGS_IS_NON_APP_WINDOW =
180             FLAG_IS_WALLPAPER | FLAG_IS_INPUT_METHOD | FLAG_IS_SYSTEM_WINDOW;
181 
182     /** The change will not participate in the animation. */
183     public static final int FLAGS_IS_OCCLUDED_NO_ANIMATION = FLAG_IS_OCCLUDED | FLAG_NO_ANIMATION;
184 
185     /** @hide */
186     @Retention(RetentionPolicy.SOURCE)
187     @IntDef(prefix = { "FLAG_" }, value = {
188             FLAG_NONE,
189             FLAG_SHOW_WALLPAPER,
190             FLAG_IS_WALLPAPER,
191             FLAG_TRANSLUCENT,
192             FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT,
193             FLAG_IS_VOICE_INTERACTION,
194             FLAG_IS_DISPLAY,
195             FLAG_DISPLAY_HAS_ALERT_WINDOWS,
196             FLAG_IS_INPUT_METHOD,
197             FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY,
198             FLAG_FILLS_TASK,
199             FLAG_WILL_IME_SHOWN,
200             FLAG_CROSS_PROFILE_OWNER_THUMBNAIL,
201             FLAG_CROSS_PROFILE_WORK_THUMBNAIL,
202             FLAG_IS_BEHIND_STARTING_WINDOW,
203             FLAG_IS_OCCLUDED,
204             FLAG_IS_SYSTEM_WINDOW,
205             FLAG_BACK_GESTURE_ANIMATED,
206             FLAG_NO_ANIMATION,
207             FLAG_TASK_LAUNCHING_BEHIND,
208             FLAG_MOVED_TO_TOP,
209             FLAG_SYNC,
210             FLAG_CONFIG_AT_END,
211             FLAG_IS_TASK_DISPLAY_AREA,
212             FLAG_FIRST_CUSTOM
213     })
214     public @interface ChangeFlags {}
215 
216     private final @TransitionType int mType;
217     private @TransitionFlags int mFlags;
218     private int mTrack = 0;
219     private final ArrayList<Change> mChanges = new ArrayList<>();
220     private final ArrayList<Root> mRoots = new ArrayList<>();
221 
222     /** This is only a BEST-EFFORT id used for log correlation. DO NOT USE for any real work! */
223     private int mDebugId = -1;
224 
225     /** @hide */
TransitionInfo(@ransitionType int type, @TransitionFlags int flags)226     public TransitionInfo(@TransitionType int type, @TransitionFlags int flags) {
227         mType = type;
228         mFlags = flags;
229     }
230 
TransitionInfo(Parcel in)231     private TransitionInfo(Parcel in) {
232         mType = in.readInt();
233         mFlags = in.readInt();
234         in.readTypedList(mChanges, Change.CREATOR);
235         in.readTypedList(mRoots, Root.CREATOR);
236         mDebugId = in.readInt();
237         mTrack = in.readInt();
238     }
239 
240     @Override
241     /** @hide */
writeToParcel(@onNull Parcel dest, int flags)242     public void writeToParcel(@NonNull Parcel dest, int flags) {
243         dest.writeInt(mType);
244         dest.writeInt(mFlags);
245         dest.writeTypedList(mChanges);
246         dest.writeTypedList(mRoots, flags);
247         dest.writeInt(mDebugId);
248         dest.writeInt(mTrack);
249     }
250 
251     @NonNull
252     public static final Creator<TransitionInfo> CREATOR =
253             new Creator<TransitionInfo>() {
254                 @Override
255                 public TransitionInfo createFromParcel(Parcel in) {
256                     return new TransitionInfo(in);
257                 }
258 
259                 @Override
260                 public TransitionInfo[] newArray(int size) {
261                     return new TransitionInfo[size];
262                 }
263             };
264 
265     @Override
266     /** @hide */
describeContents()267     public int describeContents() {
268         return 0;
269     }
270 
271     /** @see #getRoot */
addRootLeash(int displayId, @NonNull SurfaceControl leash, int offsetLeft, int offsetTop)272     public void addRootLeash(int displayId, @NonNull SurfaceControl leash,
273             int offsetLeft, int offsetTop) {
274         mRoots.add(new Root(displayId, leash, offsetLeft, offsetTop));
275     }
276 
277     /** @see #getRoot */
addRoot(@onNull Root other)278     public void addRoot(@NonNull Root other) {
279         mRoots.add(other);
280     }
281 
getType()282     public @TransitionType int getType() {
283         return mType;
284     }
285 
setFlags(int flags)286     public void setFlags(int flags) {
287         mFlags = flags;
288     }
289 
getFlags()290     public int getFlags() {
291         return mFlags;
292     }
293 
294     /**
295      * @return The number of animation roots. Most transitions should have 1, but there may be more
296      *         in some cases (such as a transition spanning multiple displays).
297      */
getRootCount()298     public int getRootCount() {
299         return mRoots.size();
300     }
301 
302     /**
303      * @return the transition-root at a specific index.
304      */
305     @NonNull
getRoot(int idx)306     public Root getRoot(int idx) {
307         return mRoots.get(idx);
308     }
309 
310     /**
311      * @return the index of the transition-root associated with `displayId` or -1 if not found.
312      */
findRootIndex(int displayId)313     public int findRootIndex(int displayId) {
314         for (int i = 0; i < mRoots.size(); ++i) {
315             if (mRoots.get(i).mDisplayId == displayId) {
316                 return i;
317             }
318         }
319         return -1;
320     }
321 
322     /**
323      * @return a surfacecontrol that can serve as a parent surfacecontrol for all the changing
324      * participants to animate within. This will generally be placed at the highest-z-order
325      * shared ancestor of all participants. While this is non-null, it's possible for the rootleash
326      * to be invalid if the transition is a no-op.
327      *
328      * @deprecated Use {@link #getRoot} instead. This call assumes there is only one root.
329      */
330     @Deprecated
331     @NonNull
getRootLeash()332     public SurfaceControl getRootLeash() {
333         if (mRoots.isEmpty()) {
334             throw new IllegalStateException("Trying to get a root leash from a no-op transition.");
335         }
336         if (mRoots.size() > 1) {
337             android.util.Log.e(TAG, "Assuming one animation root when there are more.",
338                     new Throwable());
339         }
340         return mRoots.get(0).mLeash;
341     }
342 
343     /**
344      * @return the list of {@link Change}s in this transition. The list is sorted top-to-bottom
345      *         in Z (meaning index 0 is the top-most container).
346      */
347     @NonNull
getChanges()348     public List<Change> getChanges() {
349         return mChanges;
350     }
351 
352     /**
353      * @return the Change that a window is undergoing or {@code null} if not directly
354      * represented.
355      */
356     @Nullable
getChange(@onNull WindowContainerToken token)357     public Change getChange(@NonNull WindowContainerToken token) {
358         for (int i = mChanges.size() - 1; i >= 0; --i) {
359             if (token.equals(mChanges.get(i).mContainer)) {
360                 return mChanges.get(i);
361             }
362         }
363         return null;
364     }
365 
366     /**
367      * Add a {@link Change} to this transition.
368      */
addChange(@onNull Change change)369     public void addChange(@NonNull Change change) {
370         mChanges.add(change);
371     }
372 
373     /**
374      * Whether this transition contains any changes to the window hierarchy,
375      * including keyguard visibility.
376      */
hasChangesOrSideEffects()377     public boolean hasChangesOrSideEffects() {
378         return !mChanges.isEmpty() || isKeyguardGoingAway()
379                 || (mFlags & TRANSIT_FLAG_KEYGUARD_APPEARING) != 0
380                 || (mFlags & TRANSIT_FLAG_AOD_APPEARING) != 0;
381     }
382 
383     /**
384      * Whether this transition includes keyguard going away.
385      */
isKeyguardGoingAway()386     public boolean isKeyguardGoingAway() {
387         return (mFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0;
388     }
389 
390     /** Gets which animation track this transition should run on. */
getTrack()391     public int getTrack() {
392         return mTrack;
393     }
394 
395     /** Sets which animation track this transition should run on. */
setTrack(int track)396     public void setTrack(int track) {
397         mTrack = track;
398     }
399 
400     /**
401      * Set an arbitrary "debug" id for this info. This id will not be used for any "real work",
402      * it is just for debugging and logging.
403      */
setDebugId(int id)404     public void setDebugId(int id) {
405         mDebugId = id;
406     }
407 
408     /** Get the "debug" id of this info. Do NOT use this for real work, only use for debugging. */
getDebugId()409     public int getDebugId() {
410         return mDebugId;
411     }
412 
413     @Override
toString()414     public String toString() {
415         return toString("");
416     }
417 
418     /**
419      * Returns a string representation of this transition info.
420      * @hide
421      */
toString(@onNull String prefix)422     public String toString(@NonNull String prefix) {
423         final boolean shouldPrettyPrint = !prefix.isEmpty() && !mChanges.isEmpty();
424         final String innerPrefix = shouldPrettyPrint ? prefix + "    " : "";
425         final String changesLineStart = shouldPrettyPrint ? "\n" + prefix : "";
426         final String perChangeLineStart = shouldPrettyPrint ? "\n" + innerPrefix : "";
427         StringBuilder sb = new StringBuilder();
428         sb.append("{id=").append(mDebugId).append(" t=").append(transitTypeToString(mType))
429                 .append(" f=0x").append(Integer.toHexString(mFlags)).append(" trk=").append(mTrack);
430         sb.append(" r=[");
431         for (int i = 0; i < mRoots.size(); ++i) {
432             if (i > 0) {
433                 sb.append(',');
434             }
435             sb.append(mRoots.get(i).mDisplayId).append("@").append(mRoots.get(i).mOffset);
436         }
437         sb.append("] c=[");
438         sb.append(perChangeLineStart);
439         for (int i = 0; i < mChanges.size(); ++i) {
440             if (i > 0) {
441                 sb.append(',');
442                 sb.append(perChangeLineStart);
443             }
444             sb.append(mChanges.get(i));
445         }
446         sb.append(changesLineStart);
447         sb.append("]}");
448         return sb.toString();
449     }
450 
451     /** Converts a transition mode/action to its string representation. */
452     @NonNull
modeToString(@ransitionMode int mode)453     public static String modeToString(@TransitionMode int mode) {
454         switch(mode) {
455             case TRANSIT_NONE: return "NONE";
456             case TRANSIT_OPEN: return "OPEN";
457             case TRANSIT_CLOSE: return "CLOSE";
458             case TRANSIT_TO_FRONT: return "TO_FRONT";
459             case TRANSIT_TO_BACK: return "TO_BACK";
460             case TRANSIT_CHANGE: return "CHANGE";
461             default: return "<unknown:" + mode + ">";
462         }
463     }
464 
465     /** Converts change flags into a string representation. */
466     @NonNull
flagsToString(@hangeFlags int flags)467     public static String flagsToString(@ChangeFlags int flags) {
468         if (flags == 0) return "NONE";
469         final StringBuilder sb = new StringBuilder();
470         if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
471             sb.append("SHOW_WALLPAPER");
472         }
473         if ((flags & FLAG_IS_WALLPAPER) != 0) {
474             sb.append("IS_WALLPAPER");
475         }
476         if ((flags & FLAG_IS_INPUT_METHOD) != 0) {
477             sb.append("IS_INPUT_METHOD");
478         }
479         if ((flags & FLAG_TRANSLUCENT) != 0) {
480             sb.append(sb.length() == 0 ? "" : "|").append("TRANSLUCENT");
481         }
482         if ((flags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
483             sb.append(sb.length() == 0 ? "" : "|").append("STARTING_WINDOW_TRANSFER");
484         }
485         if ((flags & FLAG_IS_VOICE_INTERACTION) != 0) {
486             sb.append(sb.length() == 0 ? "" : "|").append("IS_VOICE_INTERACTION");
487         }
488         if ((flags & FLAG_IS_DISPLAY) != 0) {
489             sb.append(sb.length() == 0 ? "" : "|").append("IS_DISPLAY");
490         }
491         if ((flags & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) {
492             sb.append(sb.length() == 0 ? "" : "|").append("DISPLAY_HAS_ALERT_WINDOWS");
493         }
494         if ((flags & FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY) != 0) {
495             sb.append(sb.length() == 0 ? "" : "|").append("IN_TASK_WITH_EMBEDDED_ACTIVITY");
496         }
497         if ((flags & FLAG_FILLS_TASK) != 0) {
498             sb.append(sb.length() == 0 ? "" : "|").append("FILLS_TASK");
499         }
500         if ((flags & FLAG_IS_BEHIND_STARTING_WINDOW) != 0) {
501             sb.append(sb.length() == 0 ? "" : "|").append("IS_BEHIND_STARTING_WINDOW");
502         }
503         if ((flags & FLAG_IS_OCCLUDED) != 0) {
504             sb.append(sb.length() == 0 ? "" : "|").append("IS_OCCLUDED");
505         }
506         if ((flags & FLAG_IS_SYSTEM_WINDOW) != 0) {
507             sb.append(sb.length() == 0 ? "" : "|").append("FLAG_IS_SYSTEM_WINDOW");
508         }
509         if ((flags & FLAG_BACK_GESTURE_ANIMATED) != 0) {
510             sb.append(sb.length() == 0 ? "" : "|").append("FLAG_BACK_GESTURE_ANIMATED");
511         }
512         if ((flags & FLAG_NO_ANIMATION) != 0) {
513             sb.append(sb.length() == 0 ? "" : "|").append("NO_ANIMATION");
514         }
515         if ((flags & FLAG_TASK_LAUNCHING_BEHIND) != 0) {
516             sb.append((sb.length() == 0 ? "" : "|") + "TASK_LAUNCHING_BEHIND");
517         }
518         if ((flags & FLAG_SYNC) != 0) {
519             sb.append((sb.length() == 0 ? "" : "|") + "SYNC");
520         }
521         if ((flags & FLAG_FIRST_CUSTOM) != 0) {
522             sb.append(sb.length() == 0 ? "" : "|").append("FIRST_CUSTOM");
523         }
524         if ((flags & FLAG_CONFIG_AT_END) != 0) {
525             sb.append(sb.length() == 0 ? "" : "|").append("CONFIG_AT_END");
526         }
527         if ((flags & FLAG_MOVED_TO_TOP) != 0) {
528             sb.append(sb.length() == 0 ? "" : "|").append("MOVE_TO_TOP");
529         }
530         if ((flags & FLAG_IS_TASK_DISPLAY_AREA) != 0) {
531             sb.append(sb.length() == 0 ? "" : "|").append("FLAG_IS_TASK_DISPLAY_AREA");
532         }
533         return sb.toString();
534     }
535 
536     /**
537      * Indication that `change` is independent of parents (ie. it has a different type of
538      * transition vs. "going along for the ride")
539      */
isIndependent(@onNull TransitionInfo.Change change, @NonNull TransitionInfo info)540     public static boolean isIndependent(@NonNull TransitionInfo.Change change,
541             @NonNull TransitionInfo info) {
542         // If the change has no parent (it is root), then it is independent
543         if (change.getParent() == null) return true;
544 
545         if (change.getLastParent() != null && !change.getLastParent().equals(change.getParent())) {
546             // If the change has been reparented, then it's independent.
547             return true;
548         }
549 
550         // non-visibility changes will just be folded into the parent change, so they aren't
551         // independent either.
552         if (change.getMode() == TRANSIT_CHANGE) return false;
553 
554         // Always fold the activity embedding change into the parent change.
555         if (change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)) return false;
556 
557         TransitionInfo.Change parentChg = info.getChange(change.getParent());
558         while (parentChg != null) {
559             // If the parent is a visibility change, it will include the results of all child
560             // changes into itself, so none of its children can be independent.
561             if (parentChg.getMode() != TRANSIT_CHANGE) return false;
562 
563             // If there are no more parents left, then all the parents, so far, have not been
564             // visibility changes which means this change is independent.
565             if (parentChg.getParent() == null) return true;
566 
567             parentChg = info.getChange(parentChg.getParent());
568         }
569         return false;
570     }
571 
572     /**
573      * Releases temporary-for-animation surfaces referenced by this to potentially free up memory.
574      * This includes root-leash and snapshots.
575      */
releaseAnimSurfaces()576     public void releaseAnimSurfaces() {
577         for (int i = mChanges.size() - 1; i >= 0; --i) {
578             final Change c = mChanges.get(i);
579             if (c.mSnapshot != null) {
580                 c.mSnapshot.release();
581                 c.mSnapshot = null;
582             }
583         }
584         for (int i = 0; i < mRoots.size(); ++i) {
585             mRoots.get(i).mLeash.release();
586         }
587     }
588 
589     /**
590      * Releases ALL the surfaces referenced by this to potentially free up memory. Do NOT use this
591      * if the surface-controls get stored and used elsewhere in the process. To just release
592      * temporary-for-animation surfaces, use {@link #releaseAnimSurfaces}.
593      */
releaseAllSurfaces()594     public void releaseAllSurfaces() {
595         releaseAnimSurfaces();
596         for (int i = mChanges.size() - 1; i >= 0; --i) {
597             mChanges.get(i).getLeash().release();
598         }
599     }
600 
601     /**
602      * Updates the callsites of all the surfaces in this transition, which aids in the debugging of
603      * lingering surfaces.
604      */
setUnreleasedWarningCallSiteForAllSurfaces(@ullable String callsite)605     public void setUnreleasedWarningCallSiteForAllSurfaces(@Nullable String callsite) {
606         for (int i = mChanges.size() - 1; i >= 0; --i) {
607             mChanges.get(i).getLeash().setUnreleasedWarningCallSite(callsite);
608         }
609     }
610 
611     /**
612      * Makes a copy of this as if it were parcel'd and unparcel'd. This implies that surfacecontrol
613      * refcounts are incremented which allows the "remote" receiver to release them without breaking
614      * the caller's references. Use this only if you need to "send" this to a local function which
615      * assumes it is being called from a remote caller.
616      */
617     @NonNull
localRemoteCopy()618     public TransitionInfo localRemoteCopy() {
619         final TransitionInfo out = new TransitionInfo(mType, mFlags);
620         out.mTrack = mTrack;
621         out.mDebugId = mDebugId;
622         for (int i = 0; i < mChanges.size(); ++i) {
623             out.mChanges.add(mChanges.get(i).localRemoteCopy());
624         }
625         for (int i = 0; i < mRoots.size(); ++i) {
626             out.mRoots.add(mRoots.get(i).localRemoteCopy());
627         }
628         return out;
629     }
630 
631     /** Represents the change a WindowContainer undergoes during a transition */
632     public static final class Change implements Parcelable {
633         private final WindowContainerToken mContainer;
634         private WindowContainerToken mParent;
635         private WindowContainerToken mLastParent;
636         private SurfaceControl mLeash;
637         private @TransitionMode int mMode = TRANSIT_NONE;
638         private @ChangeFlags int mFlags = FLAG_NONE;
639         private final Rect mStartAbsBounds = new Rect();
640         private final Rect mEndAbsBounds = new Rect();
641         private final Point mEndRelOffset = new Point();
642         private final Point mEndParentSize = new Point();
643         private ActivityManager.RunningTaskInfo mTaskInfo = null;
644         private boolean mAllowEnterPip;
645         private int mStartDisplayId = INVALID_DISPLAY;
646         private int mEndDisplayId = INVALID_DISPLAY;
647         private @Surface.Rotation int mStartRotation = ROTATION_UNDEFINED;
648         private @Surface.Rotation int mEndRotation = ROTATION_UNDEFINED;
649         /**
650          * The end rotation of the top activity after fixed rotation is finished. If the top
651          * activity is not in fixed rotation, it will be {@link ROTATION_UNDEFINED}.
652          */
653         private @Surface.Rotation int mEndFixedRotation = ROTATION_UNDEFINED;
654         private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
655         private @ColorInt int mBackgroundColor;
656         private SurfaceControl mSnapshot = null;
657         private float mSnapshotLuma;
658         private ComponentName mActivityComponent = null;
659         private AnimationOptions mAnimationOptions = null;
660         private IBinder mTaskFragmentToken = null;
661 
Change(@ullable WindowContainerToken container, @NonNull SurfaceControl leash)662         public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) {
663             mContainer = container;
664             mLeash = leash;
665         }
666 
Change(Parcel in)667         private Change(Parcel in) {
668             mContainer = in.readTypedObject(WindowContainerToken.CREATOR);
669             mParent = in.readTypedObject(WindowContainerToken.CREATOR);
670             mLastParent = in.readTypedObject(WindowContainerToken.CREATOR);
671             mLeash = new SurfaceControl();
672             mLeash.readFromParcel(in);
673             mMode = in.readInt();
674             mFlags = in.readInt();
675             mStartAbsBounds.readFromParcel(in);
676             mEndAbsBounds.readFromParcel(in);
677             mEndRelOffset.readFromParcel(in);
678             mEndParentSize.readFromParcel(in);
679             mTaskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
680             mAllowEnterPip = in.readBoolean();
681             mStartDisplayId = in.readInt();
682             mEndDisplayId = in.readInt();
683             mStartRotation = in.readInt();
684             mEndRotation = in.readInt();
685             mEndFixedRotation = in.readInt();
686             mRotationAnimation = in.readInt();
687             mBackgroundColor = in.readInt();
688             mSnapshot = in.readTypedObject(SurfaceControl.CREATOR);
689             mSnapshotLuma = in.readFloat();
690             mActivityComponent = in.readTypedObject(ComponentName.CREATOR);
691             mAnimationOptions = in.readTypedObject(AnimationOptions.CREATOR);
692             mTaskFragmentToken = in.readStrongBinder();
693         }
694 
localRemoteCopy()695         private Change localRemoteCopy() {
696             final Change out = new Change(mContainer, new SurfaceControl(mLeash, "localRemote"));
697             out.mParent = mParent;
698             out.mLastParent = mLastParent;
699             out.mMode = mMode;
700             out.mFlags = mFlags;
701             out.mStartAbsBounds.set(mStartAbsBounds);
702             out.mEndAbsBounds.set(mEndAbsBounds);
703             out.mEndRelOffset.set(mEndRelOffset);
704             out.mEndParentSize.set(mEndParentSize);
705             out.mTaskInfo = mTaskInfo;
706             out.mAllowEnterPip = mAllowEnterPip;
707             out.mStartDisplayId = mStartDisplayId;
708             out.mEndDisplayId = mEndDisplayId;
709             out.mStartRotation = mStartRotation;
710             out.mEndRotation = mEndRotation;
711             out.mEndFixedRotation = mEndFixedRotation;
712             out.mRotationAnimation = mRotationAnimation;
713             out.mBackgroundColor = mBackgroundColor;
714             out.mSnapshot = mSnapshot != null ? new SurfaceControl(mSnapshot, "localRemote") : null;
715             out.mSnapshotLuma = mSnapshotLuma;
716             out.mActivityComponent = mActivityComponent;
717             out.mAnimationOptions = mAnimationOptions;
718             out.mTaskFragmentToken = mTaskFragmentToken;
719             return out;
720         }
721 
722         /** Sets the parent of this change's container. The parent must be a participant or null. */
setParent(@ullable WindowContainerToken parent)723         public void setParent(@Nullable WindowContainerToken parent) {
724             mParent = parent;
725         }
726 
727         /**
728          * Sets the parent of this change's container before the transition if this change's
729          * container is reparented in the transition.
730          */
setLastParent(@ullable WindowContainerToken lastParent)731         public void setLastParent(@Nullable WindowContainerToken lastParent) {
732             mLastParent = lastParent;
733         }
734 
735         /** Sets the animation leash for controlling this change's container */
setLeash(@onNull SurfaceControl leash)736         public void setLeash(@NonNull SurfaceControl leash) {
737             mLeash = Objects.requireNonNull(leash);
738         }
739 
740         /** Sets the transition mode for this change */
setMode(@ransitionMode int mode)741         public void setMode(@TransitionMode int mode) {
742             mMode = mode;
743         }
744 
745         /** Sets the flags for this change */
setFlags(@hangeFlags int flags)746         public void setFlags(@ChangeFlags int flags) {
747             mFlags = flags;
748         }
749 
750         /** Sets the bounds this container occupied before the change in screen space */
setStartAbsBounds(@ullable Rect rect)751         public void setStartAbsBounds(@Nullable Rect rect) {
752             mStartAbsBounds.set(rect);
753         }
754 
755         /** Sets the bounds this container will occupy after the change in screen space */
setEndAbsBounds(@ullable Rect rect)756         public void setEndAbsBounds(@Nullable Rect rect) {
757             mEndAbsBounds.set(rect);
758         }
759 
760         /** Sets the offset of this container from its parent surface */
setEndRelOffset(int left, int top)761         public void setEndRelOffset(int left, int top) {
762             mEndRelOffset.set(left, top);
763         }
764 
765         /**
766          * Sets the size of its parent container after the change.
767          */
setEndParentSize(int width, int height)768         public void setEndParentSize(int width, int height) {
769             mEndParentSize.set(width, height);
770         }
771 
772         /**
773          * Sets the taskinfo of this container if this is a task. WARNING: this takes the
774          * reference, so don't modify it afterwards.
775          */
setTaskInfo(@ullable ActivityManager.RunningTaskInfo taskInfo)776         public void setTaskInfo(@Nullable ActivityManager.RunningTaskInfo taskInfo) {
777             mTaskInfo = taskInfo;
778         }
779 
780         /** Sets the allowEnterPip flag which represents AppOpsManager check on PiP permission */
setAllowEnterPip(boolean allowEnterPip)781         public void setAllowEnterPip(boolean allowEnterPip) {
782             mAllowEnterPip = allowEnterPip;
783         }
784 
785         /** Sets the start and end rotation of this container. */
setDisplayId(int start, int end)786         public void setDisplayId(int start, int end) {
787             mStartDisplayId = start;
788             mEndDisplayId = end;
789         }
790 
791         /** Sets the start and end rotation of this container. */
setRotation(@urface.Rotation int start, @Surface.Rotation int end)792         public void setRotation(@Surface.Rotation int start, @Surface.Rotation int end) {
793             mStartRotation = start;
794             mEndRotation = end;
795         }
796 
797         /** Sets end rotation that top activity will be launched to after fixed rotation. */
setEndFixedRotation(@urface.Rotation int endFixedRotation)798         public void setEndFixedRotation(@Surface.Rotation int endFixedRotation) {
799             mEndFixedRotation = endFixedRotation;
800         }
801 
802         /**
803          * Sets the app-requested animation type for rotation. Will be one of the
804          * ROTATION_ANIMATION_ values in {@link android.view.WindowManager.LayoutParams};
805          */
setRotationAnimation(int anim)806         public void setRotationAnimation(int anim) {
807             mRotationAnimation = anim;
808         }
809 
810         /** Sets the background color of this change's container. */
setBackgroundColor(@olorInt int backgroundColor)811         public void setBackgroundColor(@ColorInt int backgroundColor) {
812             mBackgroundColor = backgroundColor;
813         }
814 
815         /** Sets a snapshot surface for the "start" state of the container. */
setSnapshot(@ullable SurfaceControl snapshot, float luma)816         public void setSnapshot(@Nullable SurfaceControl snapshot, float luma) {
817             mSnapshot = snapshot;
818             mSnapshotLuma = luma;
819         }
820 
821         /** Sets the component-name of the container. Container must be an Activity. */
setActivityComponent(@ullable ComponentName component)822         public void setActivityComponent(@Nullable ComponentName component) {
823             mActivityComponent = component;
824         }
825 
826         /**
827          * Sets {@link AnimationOptions} to override animation.
828          */
setAnimationOptions(@ullable AnimationOptions options)829         public void setAnimationOptions(@Nullable AnimationOptions options) {
830             mAnimationOptions = options;
831         }
832 
833         /**
834          * Sets the client-defined TaskFragment token. Only set this if the window is a
835          * client-organized TaskFragment.
836          */
setTaskFragmentToken(@ullable IBinder token)837         public void setTaskFragmentToken(@Nullable IBinder token) {
838             mTaskFragmentToken = token;
839         }
840 
841         /** @return the container that is changing. May be null if non-remotable (eg. activity) */
842         @Nullable
getContainer()843         public WindowContainerToken getContainer() {
844             return mContainer;
845         }
846 
847         /**
848          * @return the parent of the changing container. This is the parent within the participants,
849          * not necessarily the actual parent.
850          */
851         @Nullable
getParent()852         public WindowContainerToken getParent() {
853             return mParent;
854         }
855 
856         /**
857          * @return the parent of the changing container before the transition if it is reparented
858          * in the transition. The parent window may not be collected in the transition as a
859          * participant, and it may have been detached from the display. {@code null} if the changing
860          * container has not been reparented in the transition, or if the parent is not organizable.
861          */
862         @Nullable
getLastParent()863         public WindowContainerToken getLastParent() {
864             return mLastParent;
865         }
866 
867         /** @return which action this change represents. */
getMode()868         public @TransitionMode int getMode() {
869             return mMode;
870         }
871 
872         /** @return the flags for this change. */
getFlags()873         public @ChangeFlags int getFlags() {
874             return mFlags;
875         }
876 
877         /** Whether this change contains any of the given change flags. */
hasFlags(@hangeFlags int flags)878         public boolean hasFlags(@ChangeFlags int flags) {
879             return (mFlags & flags) != 0;
880         }
881 
882         /** Whether this change contains all of the given change flags. */
hasAllFlags(@hangeFlags int flags)883         public boolean hasAllFlags(@ChangeFlags int flags) {
884             return (mFlags & flags) == flags;
885         }
886 
887         /**
888          * @return the bounds of the container before the change. It may be empty if the container
889          * is coming into existence.
890          */
891         @NonNull
getStartAbsBounds()892         public Rect getStartAbsBounds() {
893             return mStartAbsBounds;
894         }
895 
896         /**
897          * @return the bounds of the container after the change. It may be empty if the container
898          * is disappearing.
899          */
900         @NonNull
getEndAbsBounds()901         public Rect getEndAbsBounds() {
902             return mEndAbsBounds;
903         }
904 
905         /**
906          * @return the offset of the container's surface from its parent surface after the change.
907          */
908         @NonNull
getEndRelOffset()909         public Point getEndRelOffset() {
910             return mEndRelOffset;
911         }
912 
913         /**
914          * Returns the size of parent container after the change.
915          */
916         @NonNull
getEndParentSize()917         public Point getEndParentSize() {
918             return mEndParentSize;
919         }
920 
921         /** @return the leash or surface to animate for this container */
922         @NonNull
getLeash()923         public SurfaceControl getLeash() {
924             return mLeash;
925         }
926 
927         /** @return the task info or null if this isn't a task */
928         @Nullable
getTaskInfo()929         public ActivityManager.RunningTaskInfo getTaskInfo() {
930             return mTaskInfo;
931         }
932 
isAllowEnterPip()933         public boolean isAllowEnterPip() {
934             return mAllowEnterPip;
935         }
936 
getStartDisplayId()937         public int getStartDisplayId() {
938             return mStartDisplayId;
939         }
940 
getEndDisplayId()941         public int getEndDisplayId() {
942             return mEndDisplayId;
943         }
944 
945         @Surface.Rotation
getStartRotation()946         public int getStartRotation() {
947             return mStartRotation;
948         }
949 
950         @Surface.Rotation
getEndRotation()951         public int getEndRotation() {
952             return mEndRotation;
953         }
954 
955         @Surface.Rotation
getEndFixedRotation()956         public int getEndFixedRotation() {
957             return mEndFixedRotation;
958         }
959 
960         /** @return the rotation animation. */
getRotationAnimation()961         public int getRotationAnimation() {
962             return mRotationAnimation;
963         }
964 
965         /** @return get the background color of this change's container. */
966         @ColorInt
getBackgroundColor()967         public int getBackgroundColor() {
968             return mBackgroundColor;
969         }
970 
971         /** @return a snapshot surface (if applicable). */
972         @Nullable
getSnapshot()973         public SurfaceControl getSnapshot() {
974             return mSnapshot;
975         }
976 
977         /** @return the luma calculated for the snapshot surface (if applicable). */
getSnapshotLuma()978         public float getSnapshotLuma() {
979             return mSnapshotLuma;
980         }
981 
982         /** @return the component-name of this container (if it is an activity). */
983         @Nullable
getActivityComponent()984         public ComponentName getActivityComponent() {
985             return mActivityComponent;
986         }
987 
988         /**
989          * Returns the {@link AnimationOptions}.
990          */
991         @Nullable
getAnimationOptions()992         public AnimationOptions getAnimationOptions() {
993             return mAnimationOptions;
994         }
995 
996         /**
997          * Returns the client-defined TaskFragment token. {@code null} if this window is not a
998          * client-organized TaskFragment.
999          */
1000         @Nullable
getTaskFragmentToken()1001         public IBinder getTaskFragmentToken() {
1002             return mTaskFragmentToken;
1003         }
1004 
1005         /** @hide */
1006         @Override
writeToParcel(@onNull Parcel dest, int flags)1007         public void writeToParcel(@NonNull Parcel dest, int flags) {
1008             dest.writeTypedObject(mContainer, flags);
1009             dest.writeTypedObject(mParent, flags);
1010             dest.writeTypedObject(mLastParent, flags);
1011             mLeash.writeToParcel(dest, flags);
1012             dest.writeInt(mMode);
1013             dest.writeInt(mFlags);
1014             mStartAbsBounds.writeToParcel(dest, flags);
1015             mEndAbsBounds.writeToParcel(dest, flags);
1016             mEndRelOffset.writeToParcel(dest, flags);
1017             mEndParentSize.writeToParcel(dest, flags);
1018             dest.writeTypedObject(mTaskInfo, flags);
1019             dest.writeBoolean(mAllowEnterPip);
1020             dest.writeInt(mStartDisplayId);
1021             dest.writeInt(mEndDisplayId);
1022             dest.writeInt(mStartRotation);
1023             dest.writeInt(mEndRotation);
1024             dest.writeInt(mEndFixedRotation);
1025             dest.writeInt(mRotationAnimation);
1026             dest.writeInt(mBackgroundColor);
1027             dest.writeTypedObject(mSnapshot, flags);
1028             dest.writeFloat(mSnapshotLuma);
1029             dest.writeTypedObject(mActivityComponent, flags);
1030             dest.writeTypedObject(mAnimationOptions, flags);
1031             dest.writeStrongBinder(mTaskFragmentToken);
1032         }
1033 
1034         @NonNull
1035         public static final Creator<Change> CREATOR =
1036                 new Creator<Change>() {
1037                     @Override
1038                     public Change createFromParcel(Parcel in) {
1039                         return new Change(in);
1040                     }
1041 
1042                     @Override
1043                     public Change[] newArray(int size) {
1044                         return new Change[size];
1045                     }
1046                 };
1047 
1048         /** @hide */
1049         @Override
describeContents()1050         public int describeContents() {
1051             return 0;
1052         }
1053 
1054         @Override
toString()1055         public String toString() {
1056             final StringBuilder sb = new StringBuilder();
1057             sb.append('{');
1058             if (mContainer != null && !(mContainer.asBinder() instanceof BinderProxy)) {
1059                 // Only log the token if it is not a binder proxy and has additional container info
1060                 sb.append(mContainer);
1061                 sb.append(" ");
1062             }
1063             sb.append("m="); sb.append(modeToString(mMode));
1064             sb.append(" f="); sb.append(flagsToString(mFlags));
1065             if (mParent != null) {
1066                 sb.append(" p="); sb.append(mParent);
1067             }
1068             if (mLeash != null) {
1069                 sb.append(" leash="); sb.append(mLeash);
1070             }
1071             sb.append(" sb="); sb.append(mStartAbsBounds);
1072             sb.append(" eb="); sb.append(mEndAbsBounds);
1073             if (mEndRelOffset.x != 0 || mEndRelOffset.y != 0) {
1074                 sb.append(" eo="); sb.append(mEndRelOffset);
1075             }
1076             if (!mEndParentSize.equals(0, 0)) {
1077                 sb.append(" epz=").append(mEndParentSize);
1078             }
1079             sb.append(" d=");
1080             if (mStartDisplayId != mEndDisplayId) {
1081                 sb.append(mStartDisplayId).append("->");
1082             }
1083             sb.append(mEndDisplayId);
1084             if (mStartRotation != mEndRotation) {
1085                 sb.append(" r="); sb.append(mStartRotation);
1086                 sb.append("->"); sb.append(mEndRotation);
1087                 sb.append(':'); sb.append(mRotationAnimation);
1088             }
1089             if (mEndFixedRotation != ROTATION_UNDEFINED) {
1090                 sb.append(" endFixedRotation="); sb.append(mEndFixedRotation);
1091             }
1092             if (mBackgroundColor != 0) {
1093                 sb.append(" bc=").append(Integer.toHexString(mBackgroundColor));
1094             }
1095             if (mSnapshot != null) {
1096                 sb.append(" snapshot="); sb.append(mSnapshot);
1097             }
1098             if (mLastParent != null) {
1099                 sb.append(" lastParent="); sb.append(mLastParent);
1100             }
1101             if (mActivityComponent != null) {
1102                 sb.append(" component=");
1103                 sb.append(mActivityComponent.flattenToShortString());
1104             }
1105             if (mTaskInfo != null) {
1106                 sb.append(" taskParent=");
1107                 sb.append(mTaskInfo.parentTaskId);
1108             }
1109             if (mAnimationOptions != null) {
1110                 sb.append(" opt=").append(mAnimationOptions);
1111             }
1112             if (mTaskFragmentToken != null) {
1113                 sb.append(" taskFragmentToken=").append(mTaskFragmentToken);
1114             }
1115             sb.append('}');
1116             return sb.toString();
1117         }
1118     }
1119 
1120     /** Represents animation options during a transition */
1121     @SuppressWarnings("UserHandleName")
1122     public static final class AnimationOptions implements Parcelable {
1123 
1124         /**
1125          * The default value for animation resources ID, which means to use the system default
1126          * animation.
1127          */
1128         @SuppressWarnings("ResourceType") // Use as a hint to use the system default animation.
1129         @AnimRes
1130         public static final int DEFAULT_ANIMATION_RESOURCES_ID = 0xFFFFFFFF;
1131 
1132         private int mType;
1133         private @AnimRes int mEnterResId = DEFAULT_ANIMATION_RESOURCES_ID;
1134         private @AnimRes int mChangeResId = DEFAULT_ANIMATION_RESOURCES_ID;
1135         private @AnimRes int mExitResId = DEFAULT_ANIMATION_RESOURCES_ID;
1136         private boolean mOverrideTaskTransition;
1137         private String mPackageName;
1138         private final Rect mTransitionBounds = new Rect();
1139         private HardwareBuffer mThumbnail;
1140         private int mAnimations;
1141         // TODO(b/295805497): Extract mBackgroundColor from AnimationOptions
1142         private @ColorInt int mBackgroundColor;
1143         // Customize activity transition animation
1144         private CustomActivityTransition mCustomActivityOpenTransition;
1145         private CustomActivityTransition mCustomActivityCloseTransition;
1146         private int mUserId;
1147 
AnimationOptions(int type)1148         private AnimationOptions(int type) {
1149             mType = type;
1150         }
1151 
AnimationOptions(Parcel in)1152         private AnimationOptions(Parcel in) {
1153             mType = in.readInt();
1154             mEnterResId = in.readInt();
1155             mChangeResId = in.readInt();
1156             mExitResId = in.readInt();
1157             mOverrideTaskTransition = in.readBoolean();
1158             mPackageName = in.readString();
1159             mTransitionBounds.readFromParcel(in);
1160             mThumbnail = in.readTypedObject(HardwareBuffer.CREATOR);
1161             mAnimations = in.readInt();
1162             mCustomActivityOpenTransition = in.readTypedObject(CustomActivityTransition.CREATOR);
1163             mCustomActivityCloseTransition = in.readTypedObject(CustomActivityTransition.CREATOR);
1164             mUserId = in.readInt();
1165         }
1166 
1167         /** Make basic customized animation for a package */
1168         @NonNull
makeCommonAnimOptions(@onNull String packageName)1169         public static AnimationOptions makeCommonAnimOptions(@NonNull String packageName) {
1170             AnimationOptions options = new AnimationOptions(ANIM_FROM_STYLE);
1171             options.mPackageName = packageName;
1172             return options;
1173         }
1174 
1175         /** Make custom animation from the content of LayoutParams */
1176         @NonNull
makeAnimOptionsFromLayoutParameters( @onNull WindowManager.LayoutParams lp)1177         public static AnimationOptions makeAnimOptionsFromLayoutParameters(
1178                 @NonNull WindowManager.LayoutParams lp) {
1179             AnimationOptions options = new AnimationOptions(ANIM_FROM_STYLE);
1180             options.mPackageName = lp.packageName;
1181             options.mAnimations = lp.windowAnimations;
1182             return options;
1183         }
1184 
1185         /** Add customized window animations */
addOptionsFromLayoutParameters(@onNull WindowManager.LayoutParams lp)1186         public void addOptionsFromLayoutParameters(@NonNull WindowManager.LayoutParams lp) {
1187             mAnimations = lp.windowAnimations;
1188         }
1189 
1190         /** Add customized activity animation attributes */
addCustomActivityTransition(boolean isOpen, int enterResId, int exitResId, int backgroundColor)1191         public void addCustomActivityTransition(boolean isOpen,
1192                 int enterResId, int exitResId, int backgroundColor) {
1193             CustomActivityTransition customTransition = isOpen
1194                     ? mCustomActivityOpenTransition : mCustomActivityCloseTransition;
1195             if (customTransition == null) {
1196                 customTransition = new CustomActivityTransition();
1197                 if (isOpen) {
1198                     mCustomActivityOpenTransition = customTransition;
1199                 } else {
1200                     mCustomActivityCloseTransition = customTransition;
1201                 }
1202             }
1203             customTransition.addCustomActivityTransition(enterResId, exitResId, backgroundColor);
1204         }
1205 
1206         /**
1207          * Creates a {@link android.app.ActivityOptions#ANIM_CUSTOM} {@link AnimationOptions}.
1208          *
1209          * @param packageName the package name that includes the animation resources.
1210          * @param enterResId the resources ID of open animation.
1211          * @param changeResId the resources ID of change animation.
1212          * @param exitResId the resources ID of close animation.
1213          * @param overrideTaskTransition indicates whether to override task transition.
1214          */
1215         @NonNull
makeCustomAnimOptions(@onNull String packageName, @AnimRes int enterResId, @AnimRes int changeResId, @AnimRes int exitResId, boolean overrideTaskTransition)1216         public static AnimationOptions makeCustomAnimOptions(@NonNull String packageName,
1217                 @AnimRes int enterResId, @AnimRes int changeResId, @AnimRes int exitResId,
1218                 boolean overrideTaskTransition) {
1219             AnimationOptions options = new AnimationOptions(ANIM_CUSTOM);
1220             options.mPackageName = packageName;
1221             options.mEnterResId = enterResId;
1222             options.mChangeResId = changeResId;
1223             options.mExitResId = exitResId;
1224             options.mOverrideTaskTransition = overrideTaskTransition;
1225             return options;
1226         }
1227 
1228         /** Make options for a clip-reveal animation. */
1229         @NonNull
makeClipRevealAnimOptions(int startX, int startY, int width, int height)1230         public static AnimationOptions makeClipRevealAnimOptions(int startX, int startY, int width,
1231                 int height) {
1232             AnimationOptions options = new AnimationOptions(ANIM_CLIP_REVEAL);
1233             options.mTransitionBounds.set(startX, startY, startX + width, startY + height);
1234             return options;
1235         }
1236 
1237         /** Make options for a scale-up animation with task override option */
1238         @NonNull
makeScaleUpAnimOptions(int startX, int startY, int width, int height, boolean overrideTaskTransition)1239         public static AnimationOptions makeScaleUpAnimOptions(int startX, int startY, int width,
1240                 int height, boolean overrideTaskTransition) {
1241             AnimationOptions options = new AnimationOptions(ANIM_SCALE_UP);
1242             options.mTransitionBounds.set(startX, startY, startX + width, startY + height);
1243             options.mOverrideTaskTransition = overrideTaskTransition;
1244             return options;
1245         }
1246 
1247         /** Make options for a thumbnail-scaling animation. */
1248         @NonNull
makeThumbnailAnimOptions(@onNull HardwareBuffer srcThumb, int startX, int startY, boolean scaleUp)1249         public static AnimationOptions makeThumbnailAnimOptions(@NonNull HardwareBuffer srcThumb,
1250                 int startX, int startY, boolean scaleUp) {
1251             AnimationOptions options = new AnimationOptions(
1252                     scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN);
1253             options.mTransitionBounds.set(startX, startY, startX, startY);
1254             options.mThumbnail = srcThumb;
1255             return options;
1256         }
1257 
1258         /** Make options for an animation that spans activities of different profiles. */
1259         @NonNull
makeCrossProfileAnimOptions()1260         public static AnimationOptions makeCrossProfileAnimOptions() {
1261             AnimationOptions options = new AnimationOptions(ANIM_OPEN_CROSS_PROFILE_APPS);
1262             return options;
1263         }
1264 
1265         /** Make options designating this as a scene-transition animation. */
1266         @NonNull
makeSceneTransitionAnimOptions()1267         public static AnimationOptions makeSceneTransitionAnimOptions() {
1268             AnimationOptions options = new AnimationOptions(ANIM_SCENE_TRANSITION);
1269             return options;
1270         }
1271 
setUserId(int userId)1272         public void setUserId(int userId) {
1273             mUserId = userId;
1274         }
1275 
getUserId()1276         public int getUserId() {
1277             return mUserId;
1278         }
1279 
getType()1280         public int getType() {
1281             return mType;
1282         }
1283 
1284         @AnimRes
getEnterResId()1285         public int getEnterResId() {
1286             return mEnterResId;
1287         }
1288 
1289         @AnimRes
getChangeResId()1290         public int getChangeResId() {
1291             return mChangeResId;
1292         }
1293 
1294         @AnimRes
getExitResId()1295         public int getExitResId() {
1296             return mExitResId;
1297         }
1298 
getOverrideTaskTransition()1299         public boolean getOverrideTaskTransition() {
1300             return mOverrideTaskTransition;
1301         }
1302 
1303         @Nullable
getPackageName()1304         public String getPackageName() {
1305             return mPackageName;
1306         }
1307 
1308         @NonNull
getTransitionBounds()1309         public Rect getTransitionBounds() {
1310             return mTransitionBounds;
1311         }
1312 
1313         @Nullable
getThumbnail()1314         public HardwareBuffer getThumbnail() {
1315             return mThumbnail;
1316         }
1317 
getAnimations()1318         public int getAnimations() {
1319             return mAnimations;
1320         }
1321 
1322         /** Return customized activity transition if existed. */
1323         @Nullable
getCustomActivityTransition(boolean open)1324         public CustomActivityTransition getCustomActivityTransition(boolean open) {
1325             return open ? mCustomActivityOpenTransition : mCustomActivityCloseTransition;
1326         }
1327 
1328         @Override
writeToParcel(@onNull Parcel dest, int flags)1329         public void writeToParcel(@NonNull Parcel dest, int flags) {
1330             dest.writeInt(mType);
1331             dest.writeInt(mEnterResId);
1332             dest.writeInt(mChangeResId);
1333             dest.writeInt(mExitResId);
1334             dest.writeBoolean(mOverrideTaskTransition);
1335             dest.writeString(mPackageName);
1336             mTransitionBounds.writeToParcel(dest, flags);
1337             dest.writeTypedObject(mThumbnail, flags);
1338             dest.writeInt(mAnimations);
1339             dest.writeTypedObject(mCustomActivityOpenTransition, flags);
1340             dest.writeTypedObject(mCustomActivityCloseTransition, flags);
1341             dest.writeInt(mUserId);
1342         }
1343 
1344         @NonNull
1345         public static final Creator<AnimationOptions> CREATOR =
1346                 new Creator<AnimationOptions>() {
1347                     @Override
1348                     public AnimationOptions createFromParcel(Parcel in) {
1349                         return new AnimationOptions(in);
1350                     }
1351 
1352                     @Override
1353                     public AnimationOptions[] newArray(int size) {
1354                         return new AnimationOptions[size];
1355                     }
1356                 };
1357 
1358         /** @hide */
1359         @Override
describeContents()1360         public int describeContents() {
1361             return 0;
1362         }
1363 
1364         @NonNull
typeToString(int mode)1365         private static String typeToString(int mode) {
1366             return switch (mode) {
1367                 case ANIM_CUSTOM -> "CUSTOM";
1368                 case ANIM_SCALE_UP -> "SCALE_UP";
1369                 case ANIM_THUMBNAIL_SCALE_UP -> "THUMBNAIL_SCALE_UP";
1370                 case ANIM_THUMBNAIL_SCALE_DOWN -> "THUMBNAIL_SCALE_DOWN";
1371                 case ANIM_SCENE_TRANSITION -> "SCENE_TRANSITION";
1372                 case ANIM_CLIP_REVEAL -> "CLIP_REVEAL";
1373                 case ANIM_OPEN_CROSS_PROFILE_APPS -> "OPEN_CROSS_PROFILE_APPS";
1374                 case ANIM_FROM_STYLE -> "FROM_STYLE";
1375                 default -> "<" + mode + ">";
1376             };
1377         }
1378 
1379         @Override
1380         @NonNull
toString()1381         public String toString() {
1382             final StringBuilder sb = new StringBuilder(32);
1383             sb.append("{t=").append(typeToString(mType));
1384             if (mOverrideTaskTransition) {
1385                 sb.append(" overrideTask=true");
1386             }
1387             if (!mTransitionBounds.isEmpty()) {
1388                 sb.append(" bounds=").append(mTransitionBounds);
1389             }
1390             if (mEnterResId != DEFAULT_ANIMATION_RESOURCES_ID) {
1391                 sb.append(" enterResId=").append(mEnterResId);
1392             }
1393             if (mChangeResId != DEFAULT_ANIMATION_RESOURCES_ID) {
1394                 sb.append(" changeResId=").append(mChangeResId);
1395             }
1396             if (mExitResId != DEFAULT_ANIMATION_RESOURCES_ID) {
1397                 sb.append(" exitResId=").append(mExitResId);
1398             }
1399             sb.append(" mUserId=").append(mUserId);
1400             sb.append('}');
1401             return sb.toString();
1402         }
1403 
1404         /** Customized activity transition. */
1405         public static final class CustomActivityTransition implements Parcelable {
1406             private int mCustomEnterResId;
1407             private int mCustomExitResId;
1408             private int mCustomBackgroundColor;
1409 
1410             /** Returns customize activity animation enter resource id */
getCustomEnterResId()1411             public int getCustomEnterResId() {
1412                 return mCustomEnterResId;
1413             }
1414 
1415             /** Returns customize activity animation exit resource id */
getCustomExitResId()1416             public int getCustomExitResId() {
1417                 return mCustomExitResId;
1418             }
1419 
1420             /** Returns customize activity animation background color */
getCustomBackgroundColor()1421             public int getCustomBackgroundColor() {
1422                 return mCustomBackgroundColor;
1423             }
CustomActivityTransition()1424             CustomActivityTransition() {}
1425 
CustomActivityTransition(Parcel in)1426             CustomActivityTransition(Parcel in) {
1427                 mCustomEnterResId = in.readInt();
1428                 mCustomExitResId = in.readInt();
1429                 mCustomBackgroundColor = in.readInt();
1430             }
1431 
1432             /** Add customized activity animation attributes */
addCustomActivityTransition( int enterResId, int exitResId, int backgroundColor)1433             public void addCustomActivityTransition(
1434                     int enterResId, int exitResId, int backgroundColor) {
1435                 mCustomEnterResId = enterResId;
1436                 mCustomExitResId = exitResId;
1437                 mCustomBackgroundColor = backgroundColor;
1438             }
1439 
1440             @Override
describeContents()1441             public int describeContents() {
1442                 return 0;
1443             }
1444 
1445             @Override
writeToParcel(@onNull Parcel dest, int flags)1446             public void writeToParcel(@NonNull Parcel dest, int flags) {
1447                 dest.writeInt(mCustomEnterResId);
1448                 dest.writeInt(mCustomExitResId);
1449                 dest.writeInt(mCustomBackgroundColor);
1450             }
1451 
1452             @NonNull
1453             public static final Creator<CustomActivityTransition> CREATOR =
1454                     new Creator<CustomActivityTransition>() {
1455                         @Override
1456                         public CustomActivityTransition createFromParcel(Parcel in) {
1457                             return new CustomActivityTransition(in);
1458                         }
1459 
1460                         @Override
1461                         public CustomActivityTransition[] newArray(int size) {
1462                             return new CustomActivityTransition[size];
1463                         }
1464                     };
1465         }
1466     }
1467 
1468     /**
1469      * An animation root in a transition. There is one of these for each display that contains
1470      * participants. It will be placed, in z-order, right above the top-most participant and at the
1471      * same position in the hierarchy. As a result, if all participants are animating within a
1472      * part of the screen, the root-leash will only be in that part of the screen. In these cases,
1473      * it's relative position (from the screen) is stored in {@link Root#getOffset}.
1474      */
1475     public static final class Root implements Parcelable {
1476         private final int mDisplayId;
1477         private final SurfaceControl mLeash;
1478         private final Point mOffset = new Point();
1479 
Root(int displayId, @NonNull SurfaceControl leash, int offsetLeft, int offsetTop)1480         public Root(int displayId, @NonNull SurfaceControl leash, int offsetLeft, int offsetTop) {
1481             mDisplayId = displayId;
1482             mLeash = leash;
1483             mOffset.set(offsetLeft, offsetTop);
1484         }
1485 
Root(Parcel in)1486         private Root(Parcel in) {
1487             mDisplayId = in.readInt();
1488             mLeash = new SurfaceControl();
1489             mLeash.readFromParcel(in);
1490             mLeash.setUnreleasedWarningCallSite("TransitionInfo.Root");
1491             mOffset.readFromParcel(in);
1492         }
1493 
localRemoteCopy()1494         private Root localRemoteCopy() {
1495             return new Root(mDisplayId, new SurfaceControl(mLeash, "localRemote"),
1496                     mOffset.x, mOffset.y);
1497         }
1498 
1499         /** @return the id of the display this root is on. */
getDisplayId()1500         public int getDisplayId() {
1501             return mDisplayId;
1502         }
1503 
1504         /** @return the root's leash. Surfaces should be parented to this while animating. */
1505         @NonNull
getLeash()1506         public SurfaceControl getLeash() {
1507             return mLeash;
1508         }
1509 
1510         /** @return the offset (relative to its screen) of the root leash. */
1511         @NonNull
getOffset()1512         public Point getOffset() {
1513             return mOffset;
1514         }
1515 
1516         /** @hide */
1517         @Override
writeToParcel(@onNull Parcel dest, int flags)1518         public void writeToParcel(@NonNull Parcel dest, int flags) {
1519             dest.writeInt(mDisplayId);
1520             mLeash.writeToParcel(dest, flags);
1521             mOffset.writeToParcel(dest, flags);
1522         }
1523 
1524         @NonNull
1525         public static final Creator<Root> CREATOR =
1526                 new Creator<Root>() {
1527                     @Override
1528                     public Root createFromParcel(Parcel in) {
1529                         return new Root(in);
1530                     }
1531 
1532                     @Override
1533                     public Root[] newArray(int size) {
1534                         return new Root[size];
1535                     }
1536                 };
1537 
1538         /** @hide */
1539         @Override
describeContents()1540         public int describeContents() {
1541             return 0;
1542         }
1543 
1544         @Override
toString()1545         public String toString() {
1546             return mDisplayId + "@" + mOffset + ":" + mLeash;
1547         }
1548     }
1549 }
1550