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