1 /*
2  * Copyright (C) 2018 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.view;
18 
19 import static android.view.RemoteAnimationTargetProto.CLIP_RECT;
20 import static android.view.RemoteAnimationTargetProto.CONTENT_INSETS;
21 import static android.view.RemoteAnimationTargetProto.IS_TRANSLUCENT;
22 import static android.view.RemoteAnimationTargetProto.LEASH;
23 import static android.view.RemoteAnimationTargetProto.MODE;
24 import static android.view.RemoteAnimationTargetProto.POSITION;
25 import static android.view.RemoteAnimationTargetProto.PREFIX_ORDER_INDEX;
26 import static android.view.RemoteAnimationTargetProto.SOURCE_CONTAINER_BOUNDS;
27 import static android.view.RemoteAnimationTargetProto.START_BOUNDS;
28 import static android.view.RemoteAnimationTargetProto.START_LEASH;
29 import static android.view.RemoteAnimationTargetProto.TASK_ID;
30 import static android.view.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;
31 
32 import android.annotation.IntDef;
33 import android.app.WindowConfiguration;
34 import android.compat.annotation.UnsupportedAppUsage;
35 import android.graphics.Point;
36 import android.graphics.Rect;
37 import android.os.Parcel;
38 import android.os.Parcelable;
39 import android.util.proto.ProtoOutputStream;
40 
41 import java.io.PrintWriter;
42 import java.lang.annotation.Retention;
43 import java.lang.annotation.RetentionPolicy;
44 
45 /**
46  * Describes an activity to be animated as part of a remote animation.
47  *
48  * @hide
49  */
50 public class RemoteAnimationTarget implements Parcelable {
51 
52     /**
53      * The app is in the set of opening apps of this transition.
54      */
55     public static final int MODE_OPENING = 0;
56 
57     /**
58      * The app is in the set of closing apps of this transition.
59      */
60     public static final int MODE_CLOSING = 1;
61 
62     /**
63      * The app is in the set of resizing apps (eg. mode change) of this transition.
64      */
65     public static final int MODE_CHANGING = 2;
66 
67     @IntDef(prefix = { "MODE_" }, value = {
68             MODE_OPENING,
69             MODE_CLOSING,
70             MODE_CHANGING
71     })
72     @Retention(RetentionPolicy.SOURCE)
73     public @interface Mode {}
74 
75     /**
76      * The {@link Mode} to describe whether this app is opening or closing.
77      */
78     @UnsupportedAppUsage
79     public final @Mode int mode;
80 
81     /**
82      * The id of the task this app belongs to.
83      */
84     @UnsupportedAppUsage
85     public final int taskId;
86 
87     /**
88      * The {@link SurfaceControl} object to actually control the transform of the app.
89      */
90     @UnsupportedAppUsage
91     public final SurfaceControl leash;
92 
93     /**
94      * The {@link SurfaceControl} for the starting state of a target if this transition is
95      * MODE_CHANGING, {@code null)} otherwise. This is relative to the app window.
96      */
97     @UnsupportedAppUsage
98     public final SurfaceControl startLeash;
99 
100     /**
101      * Whether the app is translucent and may reveal apps behind.
102      */
103     @UnsupportedAppUsage
104     public final boolean isTranslucent;
105 
106     /**
107      * The clip rect window manager applies when clipping the app's main surface in screen space
108      * coordinates. This is just a hint to the animation runner: If running a clip-rect animation,
109      * anything that extends beyond these bounds will not have any effect. This implies that any
110      * clip-rect animation should likely stop at these bounds.
111      */
112     @UnsupportedAppUsage
113     public final Rect clipRect;
114 
115     /**
116      * The insets of the main app window.
117      */
118     @UnsupportedAppUsage
119     public final Rect contentInsets;
120 
121     /**
122      * The index of the element in the tree in prefix order. This should be used for z-layering
123      * to preserve original z-layer order in the hierarchy tree assuming no "boosting" needs to
124      * happen.
125      */
126     @UnsupportedAppUsage
127     public final int prefixOrderIndex;
128 
129     /**
130      * The source position of the app, in screen spaces coordinates. If the position of the leash
131      * is modified from the controlling app, any animation transform needs to be offset by this
132      * amount.
133      */
134     @UnsupportedAppUsage
135     public final Point position;
136 
137     /**
138      * The bounds of the source container the app lives in, in screen space coordinates. If the crop
139      * of the leash is modified from the controlling app, it needs to take the source container
140      * bounds into account when calculating the crop.
141      */
142     @UnsupportedAppUsage
143     public final Rect sourceContainerBounds;
144 
145     /**
146      * The starting bounds of the source container in screen space coordinates. This is {@code null}
147      * if the animation target isn't MODE_CHANGING. Since this is the starting bounds, it's size
148      * should be equivalent to the size of the starting thumbnail. Note that sourceContainerBounds
149      * is the end bounds of a change transition.
150      */
151     @UnsupportedAppUsage
152     public final Rect startBounds;
153 
154     /**
155      * The window configuration for the target.
156      */
157     @UnsupportedAppUsage
158     public final WindowConfiguration windowConfiguration;
159 
160     /**
161      * Whether the task is not presented in Recents UI.
162      */
163     @UnsupportedAppUsage
164     public boolean isNotInRecents;
165 
RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent, Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position, Rect sourceContainerBounds, WindowConfiguration windowConfig, boolean isNotInRecents, SurfaceControl startLeash, Rect startBounds)166     public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
167             Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
168             Rect sourceContainerBounds, WindowConfiguration windowConfig, boolean isNotInRecents,
169             SurfaceControl startLeash, Rect startBounds) {
170         this.mode = mode;
171         this.taskId = taskId;
172         this.leash = leash;
173         this.isTranslucent = isTranslucent;
174         this.clipRect = new Rect(clipRect);
175         this.contentInsets = new Rect(contentInsets);
176         this.prefixOrderIndex = prefixOrderIndex;
177         this.position = new Point(position);
178         this.sourceContainerBounds = new Rect(sourceContainerBounds);
179         this.windowConfiguration = windowConfig;
180         this.isNotInRecents = isNotInRecents;
181         this.startLeash = startLeash;
182         this.startBounds = startBounds == null ? null : new Rect(startBounds);
183     }
184 
RemoteAnimationTarget(Parcel in)185     public RemoteAnimationTarget(Parcel in) {
186         taskId = in.readInt();
187         mode = in.readInt();
188         leash = in.readParcelable(null);
189         isTranslucent = in.readBoolean();
190         clipRect = in.readParcelable(null);
191         contentInsets = in.readParcelable(null);
192         prefixOrderIndex = in.readInt();
193         position = in.readParcelable(null);
194         sourceContainerBounds = in.readParcelable(null);
195         windowConfiguration = in.readParcelable(null);
196         isNotInRecents = in.readBoolean();
197         startLeash = in.readParcelable(null);
198         startBounds = in.readParcelable(null);
199     }
200 
201     @Override
describeContents()202     public int describeContents() {
203         return 0;
204     }
205 
206     @Override
writeToParcel(Parcel dest, int flags)207     public void writeToParcel(Parcel dest, int flags) {
208         dest.writeInt(taskId);
209         dest.writeInt(mode);
210         dest.writeParcelable(leash, 0 /* flags */);
211         dest.writeBoolean(isTranslucent);
212         dest.writeParcelable(clipRect, 0 /* flags */);
213         dest.writeParcelable(contentInsets, 0 /* flags */);
214         dest.writeInt(prefixOrderIndex);
215         dest.writeParcelable(position, 0 /* flags */);
216         dest.writeParcelable(sourceContainerBounds, 0 /* flags */);
217         dest.writeParcelable(windowConfiguration, 0 /* flags */);
218         dest.writeBoolean(isNotInRecents);
219         dest.writeParcelable(startLeash, 0 /* flags */);
220         dest.writeParcelable(startBounds, 0 /* flags */);
221     }
222 
dump(PrintWriter pw, String prefix)223     public void dump(PrintWriter pw, String prefix) {
224         pw.print(prefix); pw.print("mode="); pw.print(mode);
225         pw.print(" taskId="); pw.print(taskId);
226         pw.print(" isTranslucent="); pw.print(isTranslucent);
227         pw.print(" clipRect="); clipRect.printShortString(pw);
228         pw.print(" contentInsets="); contentInsets.printShortString(pw);
229         pw.print(" prefixOrderIndex="); pw.print(prefixOrderIndex);
230         pw.print(" position="); position.printShortString(pw);
231         pw.print(" sourceContainerBounds="); sourceContainerBounds.printShortString(pw);
232         pw.println();
233         pw.print(prefix); pw.print("windowConfiguration="); pw.println(windowConfiguration);
234         pw.print(prefix); pw.print("leash="); pw.println(leash);
235     }
236 
writeToProto(ProtoOutputStream proto, long fieldId)237     public void writeToProto(ProtoOutputStream proto, long fieldId) {
238         final long token = proto.start(fieldId);
239         proto.write(TASK_ID, taskId);
240         proto.write(MODE, mode);
241         leash.writeToProto(proto, LEASH);
242         proto.write(IS_TRANSLUCENT, isTranslucent);
243         clipRect.writeToProto(proto, CLIP_RECT);
244         contentInsets.writeToProto(proto, CONTENT_INSETS);
245         proto.write(PREFIX_ORDER_INDEX, prefixOrderIndex);
246         position.writeToProto(proto, POSITION);
247         sourceContainerBounds.writeToProto(proto, SOURCE_CONTAINER_BOUNDS);
248         windowConfiguration.writeToProto(proto, WINDOW_CONFIGURATION);
249         if (startLeash != null) {
250             startLeash.writeToProto(proto, START_LEASH);
251         }
252         if (startBounds != null) {
253             startBounds.writeToProto(proto, START_BOUNDS);
254         }
255         proto.end(token);
256     }
257 
258     public static final @android.annotation.NonNull Creator<RemoteAnimationTarget> CREATOR
259             = new Creator<RemoteAnimationTarget>() {
260         public RemoteAnimationTarget createFromParcel(Parcel in) {
261             return new RemoteAnimationTarget(in);
262         }
263 
264         public RemoteAnimationTarget[] newArray(int size) {
265             return new RemoteAnimationTarget[size];
266         }
267     };
268 }
269