1 /*
2  * Copyright (C) 2023 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 android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.os.IBinder;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.util.Objects;
31 
32 /**
33  * Data object of params for TaskFragment related {@link WindowContainerTransaction} operation.
34  *
35  * @see WindowContainerTransaction#addTaskFragmentOperation(IBinder, TaskFragmentOperation).
36  * @hide
37  */
38 public final class TaskFragmentOperation implements Parcelable {
39 
40     /**
41      * Type for tracking other unknown TaskFragment operation that is not set through
42      * {@link TaskFragmentOperation}, such as invalid request.
43      */
44     public static final int OP_TYPE_UNKNOWN = -1;
45 
46     /** Creates a new TaskFragment. */
47     public static final int OP_TYPE_CREATE_TASK_FRAGMENT = 0;
48 
49     /** Deletes the given TaskFragment. */
50     public static final int OP_TYPE_DELETE_TASK_FRAGMENT = 1;
51 
52     /** Starts an Activity in the given TaskFragment. */
53     public static final int OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT = 2;
54 
55     /** Reparents the given Activity to the given TaskFragment. */
56     public static final int OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT = 3;
57 
58     /** Sets two TaskFragments adjacent to each other. */
59     public static final int OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS = 4;
60 
61     /** Clears the adjacent TaskFragments relationship. */
62     public static final int OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS = 5;
63 
64     /** Requests focus on the top running Activity in the given TaskFragment. */
65     public static final int OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT = 6;
66 
67     /** Sets a given TaskFragment to have a companion TaskFragment. */
68     public static final int OP_TYPE_SET_COMPANION_TASK_FRAGMENT = 7;
69 
70     /** Sets the {@link TaskFragmentAnimationParams} for the given TaskFragment. */
71     public static final int OP_TYPE_SET_ANIMATION_PARAMS = 8;
72 
73     /** Sets the relative bounds with {@link WindowContainerTransaction#setRelativeBounds}. */
74     public static final int OP_TYPE_SET_RELATIVE_BOUNDS = 9;
75 
76     /**
77      * Reorders the TaskFragment to be the front-most TaskFragment in the Task.
78      * Note that there could still have other WindowContainer on top of the front-most
79      * TaskFragment, such as a non-embedded Activity.
80      */
81     public static final int OP_TYPE_REORDER_TO_FRONT = 10;
82 
83     /**
84      * Sets the activity navigation to be isolated, where the activity navigation on the
85      * TaskFragment is separated from the rest activities in the Task. Activities cannot be
86      * started on an isolated TaskFragment unless the activities are launched from the same
87      * TaskFragment or explicitly requested to.
88      */
89     public static final int OP_TYPE_SET_ISOLATED_NAVIGATION = 11;
90 
91     @IntDef(prefix = { "OP_TYPE_" }, value = {
92             OP_TYPE_UNKNOWN,
93             OP_TYPE_CREATE_TASK_FRAGMENT,
94             OP_TYPE_DELETE_TASK_FRAGMENT,
95             OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT,
96             OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT,
97             OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS,
98             OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS,
99             OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT,
100             OP_TYPE_SET_COMPANION_TASK_FRAGMENT,
101             OP_TYPE_SET_ANIMATION_PARAMS,
102             OP_TYPE_SET_RELATIVE_BOUNDS,
103             OP_TYPE_REORDER_TO_FRONT,
104             OP_TYPE_SET_ISOLATED_NAVIGATION
105     })
106     @Retention(RetentionPolicy.SOURCE)
107     public @interface OperationType {}
108 
109     @OperationType
110     private final int mOpType;
111 
112     @Nullable
113     private final TaskFragmentCreationParams mTaskFragmentCreationParams;
114 
115     @Nullable
116     private final IBinder mActivityToken;
117 
118     @Nullable
119     private final Intent mActivityIntent;
120 
121     @Nullable
122     private final Bundle mBundle;
123 
124     @Nullable
125     private final IBinder mSecondaryFragmentToken;
126 
127     @Nullable
128     private final TaskFragmentAnimationParams mAnimationParams;
129 
130     private final boolean mIsolatedNav;
131 
TaskFragmentOperation(@perationType int opType, @Nullable TaskFragmentCreationParams taskFragmentCreationParams, @Nullable IBinder activityToken, @Nullable Intent activityIntent, @Nullable Bundle bundle, @Nullable IBinder secondaryFragmentToken, @Nullable TaskFragmentAnimationParams animationParams, boolean isolatedNav)132     private TaskFragmentOperation(@OperationType int opType,
133             @Nullable TaskFragmentCreationParams taskFragmentCreationParams,
134             @Nullable IBinder activityToken, @Nullable Intent activityIntent,
135             @Nullable Bundle bundle, @Nullable IBinder secondaryFragmentToken,
136             @Nullable TaskFragmentAnimationParams animationParams,
137             boolean isolatedNav) {
138         mOpType = opType;
139         mTaskFragmentCreationParams = taskFragmentCreationParams;
140         mActivityToken = activityToken;
141         mActivityIntent = activityIntent;
142         mBundle = bundle;
143         mSecondaryFragmentToken = secondaryFragmentToken;
144         mAnimationParams = animationParams;
145         mIsolatedNav = isolatedNav;
146     }
147 
TaskFragmentOperation(Parcel in)148     private TaskFragmentOperation(Parcel in) {
149         mOpType = in.readInt();
150         mTaskFragmentCreationParams = in.readTypedObject(TaskFragmentCreationParams.CREATOR);
151         mActivityToken = in.readStrongBinder();
152         mActivityIntent = in.readTypedObject(Intent.CREATOR);
153         mBundle = in.readBundle(getClass().getClassLoader());
154         mSecondaryFragmentToken = in.readStrongBinder();
155         mAnimationParams = in.readTypedObject(TaskFragmentAnimationParams.CREATOR);
156         mIsolatedNav = in.readBoolean();
157     }
158 
159     @Override
writeToParcel(@onNull Parcel dest, int flags)160     public void writeToParcel(@NonNull Parcel dest, int flags) {
161         dest.writeInt(mOpType);
162         dest.writeTypedObject(mTaskFragmentCreationParams, flags);
163         dest.writeStrongBinder(mActivityToken);
164         dest.writeTypedObject(mActivityIntent, flags);
165         dest.writeBundle(mBundle);
166         dest.writeStrongBinder(mSecondaryFragmentToken);
167         dest.writeTypedObject(mAnimationParams, flags);
168         dest.writeBoolean(mIsolatedNav);
169     }
170 
171     @NonNull
172     public static final Creator<TaskFragmentOperation> CREATOR =
173             new Creator<TaskFragmentOperation>() {
174                 @Override
175                 public TaskFragmentOperation createFromParcel(Parcel in) {
176                     return new TaskFragmentOperation(in);
177                 }
178 
179                 @Override
180                 public TaskFragmentOperation[] newArray(int size) {
181                     return new TaskFragmentOperation[size];
182                 }
183             };
184 
185     /**
186      * Gets the {@link OperationType} of this {@link TaskFragmentOperation}.
187      */
188     @OperationType
getOpType()189     public int getOpType() {
190         return mOpType;
191     }
192 
193     /**
194      * Gets the options to create a new TaskFragment.
195      */
196     @Nullable
getTaskFragmentCreationParams()197     public TaskFragmentCreationParams getTaskFragmentCreationParams() {
198         return mTaskFragmentCreationParams;
199     }
200 
201     /**
202      * Gets the Activity token set in this operation.
203      */
204     @Nullable
getActivityToken()205     public IBinder getActivityToken() {
206         return mActivityToken;
207     }
208 
209     /**
210      * Gets the Intent to start a new Activity.
211      */
212     @Nullable
getActivityIntent()213     public Intent getActivityIntent() {
214         return mActivityIntent;
215     }
216 
217     /**
218      * Gets the Bundle set in this operation.
219      */
220     @Nullable
getBundle()221     public Bundle getBundle() {
222         return mBundle;
223     }
224 
225     /**
226      * Gets the fragment token of the secondary TaskFragment set in this operation.
227      */
228     @Nullable
getSecondaryFragmentToken()229     public IBinder getSecondaryFragmentToken() {
230         return mSecondaryFragmentToken;
231     }
232 
233     /**
234      * Gets the animation related override of TaskFragment.
235      */
236     @Nullable
getAnimationParams()237     public TaskFragmentAnimationParams getAnimationParams() {
238         return mAnimationParams;
239     }
240 
241     /**
242      * Returns whether the activity navigation on this TaskFragment is isolated. This is only
243      * useful when the op type is {@link OP_TYPE_SET_ISOLATED_NAVIGATION}.
244      */
isIsolatedNav()245     public boolean isIsolatedNav() {
246         return mIsolatedNav;
247     }
248 
249     @Override
toString()250     public String toString() {
251         final StringBuilder sb = new StringBuilder();
252         sb.append("TaskFragmentOperation{ opType=").append(mOpType);
253         if (mTaskFragmentCreationParams != null) {
254             sb.append(", taskFragmentCreationParams=").append(mTaskFragmentCreationParams);
255         }
256         if (mActivityToken != null) {
257             sb.append(", activityToken=").append(mActivityToken);
258         }
259         if (mActivityIntent != null) {
260             sb.append(", activityIntent=").append(mActivityIntent);
261         }
262         if (mBundle != null) {
263             sb.append(", bundle=").append(mBundle);
264         }
265         if (mSecondaryFragmentToken != null) {
266             sb.append(", secondaryFragmentToken=").append(mSecondaryFragmentToken);
267         }
268         if (mAnimationParams != null) {
269             sb.append(", animationParams=").append(mAnimationParams);
270         }
271         sb.append(", isolatedNav=").append(mIsolatedNav);
272 
273         sb.append('}');
274         return sb.toString();
275     }
276 
277     @Override
hashCode()278     public int hashCode() {
279         return Objects.hash(mOpType, mTaskFragmentCreationParams, mActivityToken, mActivityIntent,
280                 mBundle, mSecondaryFragmentToken, mAnimationParams, mIsolatedNav);
281     }
282 
283     @Override
equals(@ullable Object obj)284     public boolean equals(@Nullable Object obj) {
285         if (!(obj instanceof TaskFragmentOperation)) {
286             return false;
287         }
288         final TaskFragmentOperation other = (TaskFragmentOperation) obj;
289         return mOpType == other.mOpType
290                 && Objects.equals(mTaskFragmentCreationParams, other.mTaskFragmentCreationParams)
291                 && Objects.equals(mActivityToken, other.mActivityToken)
292                 && Objects.equals(mActivityIntent, other.mActivityIntent)
293                 && Objects.equals(mBundle, other.mBundle)
294                 && Objects.equals(mSecondaryFragmentToken, other.mSecondaryFragmentToken)
295                 && Objects.equals(mAnimationParams, other.mAnimationParams)
296                 && mIsolatedNav == other.mIsolatedNav;
297     }
298 
299     @Override
describeContents()300     public int describeContents() {
301         return 0;
302     }
303 
304     /** Builder to construct the {@link TaskFragmentOperation}. */
305     public static final class Builder {
306 
307         @OperationType
308         private final int mOpType;
309 
310         @Nullable
311         private TaskFragmentCreationParams mTaskFragmentCreationParams;
312 
313         @Nullable
314         private IBinder mActivityToken;
315 
316         @Nullable
317         private Intent mActivityIntent;
318 
319         @Nullable
320         private Bundle mBundle;
321 
322         @Nullable
323         private IBinder mSecondaryFragmentToken;
324 
325         @Nullable
326         private TaskFragmentAnimationParams mAnimationParams;
327 
328         private boolean mIsolatedNav;
329 
330         /**
331          * @param opType the {@link OperationType} of this {@link TaskFragmentOperation}.
332          */
Builder(@perationType int opType)333         public Builder(@OperationType int opType) {
334             mOpType = opType;
335         }
336 
337         /**
338          * Sets the {@link TaskFragmentCreationParams} for creating a new TaskFragment.
339          */
340         @NonNull
setTaskFragmentCreationParams( @ullable TaskFragmentCreationParams taskFragmentCreationParams)341         public Builder setTaskFragmentCreationParams(
342                 @Nullable TaskFragmentCreationParams taskFragmentCreationParams) {
343             mTaskFragmentCreationParams = taskFragmentCreationParams;
344             return this;
345         }
346 
347         /**
348          * Sets an Activity token to this operation.
349          */
350         @NonNull
setActivityToken(@ullable IBinder activityToken)351         public Builder setActivityToken(@Nullable IBinder activityToken) {
352             mActivityToken = activityToken;
353             return this;
354         }
355 
356         /**
357          * Sets the Intent to start a new Activity.
358          */
359         @NonNull
setActivityIntent(@ullable Intent activityIntent)360         public Builder setActivityIntent(@Nullable Intent activityIntent) {
361             mActivityIntent = activityIntent;
362             return this;
363         }
364 
365         /**
366          * Sets a Bundle to this operation.
367          */
368         @NonNull
setBundle(@ullable Bundle bundle)369         public Builder setBundle(@Nullable Bundle bundle) {
370             mBundle = bundle;
371             return this;
372         }
373 
374         /**
375          * Sets the secondary fragment token to this operation.
376          */
377         @NonNull
setSecondaryFragmentToken(@ullable IBinder secondaryFragmentToken)378         public Builder setSecondaryFragmentToken(@Nullable IBinder secondaryFragmentToken) {
379             mSecondaryFragmentToken = secondaryFragmentToken;
380             return this;
381         }
382 
383         /**
384          * Sets the {@link TaskFragmentAnimationParams} for the given TaskFragment.
385          */
386         @NonNull
setAnimationParams(@ullable TaskFragmentAnimationParams animationParams)387         public Builder setAnimationParams(@Nullable TaskFragmentAnimationParams animationParams) {
388             mAnimationParams = animationParams;
389             return this;
390         }
391 
392         /**
393          * Sets the activity navigation of this TaskFragment to be isolated.
394          */
395         @NonNull
setIsolatedNav(boolean isolatedNav)396         public Builder setIsolatedNav(boolean isolatedNav) {
397             mIsolatedNav = isolatedNav;
398             return this;
399         }
400 
401         /**
402          * Constructs the {@link TaskFragmentOperation}.
403          */
404         @NonNull
build()405         public TaskFragmentOperation build() {
406             return new TaskFragmentOperation(mOpType, mTaskFragmentCreationParams, mActivityToken,
407                     mActivityIntent, mBundle, mSecondaryFragmentToken, mAnimationParams,
408                     mIsolatedNav);
409         }
410     }
411 }
412