• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
20 import static android.app.WindowConfiguration.WindowingMode;
21 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.RequiresPermission;
26 import android.annotation.TestApi;
27 import android.content.pm.ActivityInfo;
28 import android.content.pm.ActivityInfo.ScreenOrientation;
29 import android.graphics.Rect;
30 import android.os.IBinder;
31 import android.os.Parcel;
32 import android.os.Parcelable;
33 
34 /**
35  * Data object for options to create TaskFragment with.
36  * @hide
37  */
38 @TestApi
39 public final class TaskFragmentCreationParams implements Parcelable {
40 
41     /** The organizer that will organize this TaskFragment. */
42     @NonNull
43     private final TaskFragmentOrganizerToken mOrganizer;
44 
45     /**
46      * Unique token assigned from the client organizer to identify the {@link TaskFragmentInfo} when
47      * a new TaskFragment is created with this option.
48      */
49     @NonNull
50     private final IBinder mFragmentToken;
51 
52     /**
53      * Activity token used to identify the leaf Task to create the TaskFragment in. It has to belong
54      * to the same app as the root Activity of the target Task.
55      */
56     @NonNull
57     private final IBinder mOwnerToken;
58 
59     /**
60      * The initial relative bounds of the TaskFragment in parent coordinate.
61      * Fills parent if empty.
62      */
63     @NonNull
64     private final Rect mInitialRelativeBounds = new Rect();
65 
66     /** The initial windowing mode of the TaskFragment. Inherits from parent if not set. */
67     @WindowingMode
68     private final int mWindowingMode;
69 
70     /**
71      * The fragment token of the paired primary TaskFragment.
72      * When it is set, the new TaskFragment will be positioned right above the paired TaskFragment.
73      * Otherwise, the new TaskFragment will be positioned on the top of the Task by default.
74      *
75      * This is different from {@link WindowContainerTransaction#setAdjacentTaskFragments} as we may
76      * set this when the pair of TaskFragments are stacked, while adjacent is only set on the pair
77      * of TaskFragments that are in split.
78      *
79      * This is needed in case we need to launch a placeholder Activity to split below a transparent
80      * always-expand Activity.
81      *
82      * This should not be used with {@link #mPairedActivityToken}.
83      */
84     @Nullable
85     private final IBinder mPairedPrimaryFragmentToken;
86 
87     /**
88      * The Activity token to place the new TaskFragment on top of.
89      * When it is set, the new TaskFragment will be positioned right above the target Activity.
90      * Otherwise, the new TaskFragment will be positioned on the top of the Task by default.
91      *
92      * This is needed in case we need to place an Activity into TaskFragment to launch placeholder
93      * below a transparent always-expand Activity, or when there is another Intent being started in
94      * a TaskFragment above.
95      *
96      * This should not be used with {@link #mPairedPrimaryFragmentToken}.
97      */
98     @Nullable
99     private final IBinder mPairedActivityToken;
100 
101     /**
102      * If {@code true}, transitions are allowed even if the TaskFragment is empty. If
103      * {@code false}, transitions will wait until the TaskFragment becomes non-empty or other
104      * conditions are met. Default to {@code false}.
105      */
106     private final boolean mAllowTransitionWhenEmpty;
107 
108     /**
109      * The override orientation for the TaskFragment. This is effective only for a system organizer.
110      * The value is ignored otherwise. Default to {@code SCREEN_ORIENTATION_UNSPECIFIED}.
111      *
112      * @see TaskFragmentOrganizer#registerOrganizer(boolean)
113      */
114     private final @ScreenOrientation int mOverrideOrientation;
115 
116     /**
117      * {@link android.content.pm.ActivityInfo.Config} mask that specifies which
118      * configuration changes should trigger TaskFragment info change callbacks.
119      *
120      * @see android.content.pm.ActivityInfo.Config
121      */
122     private final @ActivityInfo.Config int mConfigurationChangeMask;
123 
TaskFragmentCreationParams( @onNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken, @NonNull Rect initialRelativeBounds, @WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken, @Nullable IBinder pairedActivityToken, boolean allowTransitionWhenEmpty, @ScreenOrientation int overrideOrientation, @ActivityInfo.Config int configurationChangeMask)124     private TaskFragmentCreationParams(
125             @NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken,
126             @NonNull IBinder ownerToken, @NonNull Rect initialRelativeBounds,
127             @WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken,
128             @Nullable IBinder pairedActivityToken, boolean allowTransitionWhenEmpty,
129             @ScreenOrientation int overrideOrientation,
130             @ActivityInfo.Config int configurationChangeMask) {
131         if (pairedPrimaryFragmentToken != null && pairedActivityToken != null) {
132             throw new IllegalArgumentException("pairedPrimaryFragmentToken and"
133                     + " pairedActivityToken should not be set at the same time.");
134         }
135         mOrganizer = organizer;
136         mFragmentToken = fragmentToken;
137         mOwnerToken = ownerToken;
138         mInitialRelativeBounds.set(initialRelativeBounds);
139         mWindowingMode = windowingMode;
140         mPairedPrimaryFragmentToken = pairedPrimaryFragmentToken;
141         mPairedActivityToken = pairedActivityToken;
142         mAllowTransitionWhenEmpty = allowTransitionWhenEmpty;
143         mOverrideOrientation = overrideOrientation;
144         mConfigurationChangeMask = configurationChangeMask;
145     }
146 
147     @NonNull
getOrganizer()148     public TaskFragmentOrganizerToken getOrganizer() {
149         return mOrganizer;
150     }
151 
152     @NonNull
getFragmentToken()153     public IBinder getFragmentToken() {
154         return mFragmentToken;
155     }
156 
157     @NonNull
getOwnerToken()158     public IBinder getOwnerToken() {
159         return mOwnerToken;
160     }
161 
162     @NonNull
getInitialRelativeBounds()163     public Rect getInitialRelativeBounds() {
164         return mInitialRelativeBounds;
165     }
166 
167     @WindowingMode
getWindowingMode()168     public int getWindowingMode() {
169         return mWindowingMode;
170     }
171 
172     /**
173      * TODO(b/232476698): remove the hide with adding CTS for this in next release.
174      * @hide
175      */
176     @Nullable
getPairedPrimaryFragmentToken()177     public IBinder getPairedPrimaryFragmentToken() {
178         return mPairedPrimaryFragmentToken;
179     }
180 
181     /**
182      * TODO(b/232476698): remove the hide with adding CTS for this in next release.
183      * @hide
184      */
185     @Nullable
getPairedActivityToken()186     public IBinder getPairedActivityToken() {
187         return mPairedActivityToken;
188     }
189 
190     /** @hide */
getAllowTransitionWhenEmpty()191     public boolean getAllowTransitionWhenEmpty() {
192         return mAllowTransitionWhenEmpty;
193     }
194 
195     /** @hide */
getOverrideOrientation()196     public @ScreenOrientation int getOverrideOrientation() {
197         return mOverrideOrientation;
198     }
199 
200     /** @hide */
getConfigurationChangeMask()201     public @ActivityInfo.Config int getConfigurationChangeMask() {
202         return mConfigurationChangeMask;
203     }
204 
TaskFragmentCreationParams(Parcel in)205     private TaskFragmentCreationParams(Parcel in) {
206         mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in);
207         mFragmentToken = in.readStrongBinder();
208         mOwnerToken = in.readStrongBinder();
209         mInitialRelativeBounds.readFromParcel(in);
210         mWindowingMode = in.readInt();
211         mPairedPrimaryFragmentToken = in.readStrongBinder();
212         mPairedActivityToken = in.readStrongBinder();
213         mAllowTransitionWhenEmpty = in.readBoolean();
214         mOverrideOrientation = in.readInt();
215         mConfigurationChangeMask = in.readInt();
216     }
217 
218     /** @hide */
219     @Override
writeToParcel(@onNull Parcel dest, int flags)220     public void writeToParcel(@NonNull Parcel dest, int flags) {
221         mOrganizer.writeToParcel(dest, flags);
222         dest.writeStrongBinder(mFragmentToken);
223         dest.writeStrongBinder(mOwnerToken);
224         mInitialRelativeBounds.writeToParcel(dest, flags);
225         dest.writeInt(mWindowingMode);
226         dest.writeStrongBinder(mPairedPrimaryFragmentToken);
227         dest.writeStrongBinder(mPairedActivityToken);
228         dest.writeBoolean(mAllowTransitionWhenEmpty);
229         dest.writeInt(mOverrideOrientation);
230         dest.writeInt(mConfigurationChangeMask);
231     }
232 
233     @NonNull
234     public static final Creator<TaskFragmentCreationParams> CREATOR =
235             new Creator<TaskFragmentCreationParams>() {
236                 @Override
237                 public TaskFragmentCreationParams createFromParcel(Parcel in) {
238                     return new TaskFragmentCreationParams(in);
239                 }
240 
241                 @Override
242                 public TaskFragmentCreationParams[] newArray(int size) {
243                     return new TaskFragmentCreationParams[size];
244                 }
245             };
246 
247     @Override
toString()248     public String toString() {
249         return "TaskFragmentCreationParams{"
250                 + " organizer=" + mOrganizer
251                 + " fragmentToken=" + mFragmentToken
252                 + " ownerToken=" + mOwnerToken
253                 + " initialRelativeBounds=" + mInitialRelativeBounds
254                 + " windowingMode=" + mWindowingMode
255                 + " pairedFragmentToken=" + mPairedPrimaryFragmentToken
256                 + " pairedActivityToken=" + mPairedActivityToken
257                 + " allowTransitionWhenEmpty=" + mAllowTransitionWhenEmpty
258                 + " overrideOrientation=" + mOverrideOrientation
259                 + " configurationChangeMask=" + mConfigurationChangeMask
260                 + "}";
261     }
262 
263     /** @hide */
264     @Override
describeContents()265     public int describeContents() {
266         return 0;
267     }
268 
269     /** Builder to construct the options to create TaskFragment with. */
270     public static final class Builder {
271 
272         @NonNull
273         private final TaskFragmentOrganizerToken mOrganizer;
274 
275         @NonNull
276         private final IBinder mFragmentToken;
277 
278         @NonNull
279         private final IBinder mOwnerToken;
280 
281         @NonNull
282         private final Rect mInitialRelativeBounds = new Rect();
283 
284         @WindowingMode
285         private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
286 
287         @Nullable
288         private IBinder mPairedPrimaryFragmentToken;
289 
290         @Nullable
291         private IBinder mPairedActivityToken;
292 
293         private boolean mAllowTransitionWhenEmpty;
294 
295         private @ScreenOrientation int mOverrideOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
296 
297         private @ActivityInfo.Config int mConfigurationChangeMask = 0;
298 
Builder(@onNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken)299         public Builder(@NonNull TaskFragmentOrganizerToken organizer,
300                 @NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
301             mOrganizer = organizer;
302             mFragmentToken = fragmentToken;
303             mOwnerToken = ownerToken;
304         }
305 
306         /**
307          * Sets the initial relative bounds for the TaskFragment in parent coordinate.
308          * Set to empty to fill parent.
309          */
310         @NonNull
setInitialRelativeBounds(@onNull Rect bounds)311         public Builder setInitialRelativeBounds(@NonNull Rect bounds) {
312             mInitialRelativeBounds.set(bounds);
313             return this;
314         }
315 
316         /** Sets the initial windowing mode for the TaskFragment. */
317         @NonNull
setWindowingMode(@indowingMode int windowingMode)318         public Builder setWindowingMode(@WindowingMode int windowingMode) {
319             mWindowingMode = windowingMode;
320             return this;
321         }
322 
323         /**
324          * Sets the fragment token of the paired primary TaskFragment.
325          * When it is set, the new TaskFragment will be positioned right above the paired
326          * TaskFragment. Otherwise, the new TaskFragment will be positioned on the top of the Task
327          * by default.
328          *
329          * This is needed in case we need to launch a placeholder Activity to split below a
330          * transparent always-expand Activity.
331          *
332          * This should not be used with {@link #setPairedActivityToken}.
333          *
334          * TODO(b/232476698): remove the hide with adding CTS for this in next release.
335          * @hide
336          */
337         @NonNull
setPairedPrimaryFragmentToken(@ullable IBinder fragmentToken)338         public Builder setPairedPrimaryFragmentToken(@Nullable IBinder fragmentToken) {
339             mPairedPrimaryFragmentToken = fragmentToken;
340             return this;
341         }
342 
343         /**
344          * Sets the Activity token to place the new TaskFragment on top of.
345          * When it is set, the new TaskFragment will be positioned right above the target Activity.
346          * Otherwise, the new TaskFragment will be positioned on the top of the Task by default.
347          *
348          * This is needed in case we need to place an Activity into TaskFragment to launch
349          * placeholder below a transparent always-expand Activity, or when there is another Intent
350          * being started in a TaskFragment above.
351          *
352          * This should not be used with {@link #setPairedPrimaryFragmentToken}.
353          *
354          * TODO(b/232476698): remove the hide with adding CTS for this in next release.
355          * @hide
356          */
357         @NonNull
setPairedActivityToken(@ullable IBinder activityToken)358         public Builder setPairedActivityToken(@Nullable IBinder activityToken) {
359             mPairedActivityToken = activityToken;
360             return this;
361         }
362 
363         /**
364          * Sets whether transitions are allowed when the TaskFragment is empty. If {@code true},
365          * transitions are allowed when the TaskFragment is empty. If {@code false}, transitions
366          * will wait until the TaskFragment becomes non-empty or other conditions are met. Default
367          * to {@code false}.
368          *
369          * @hide
370          */
371         @NonNull
setAllowTransitionWhenEmpty(boolean allowTransitionWhenEmpty)372         public Builder setAllowTransitionWhenEmpty(boolean allowTransitionWhenEmpty) {
373             mAllowTransitionWhenEmpty = allowTransitionWhenEmpty;
374             return this;
375         }
376 
377         /**
378          * Sets the override orientation for the TaskFragment. This is effective only for a system
379          * organizer. The value is ignored otherwise. Default to
380          * {@code SCREEN_ORIENTATION_UNSPECIFIED}.
381          *
382          * @see TaskFragmentOrganizer#registerOrganizer(boolean)
383          *
384          * @hide
385          */
386         @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
387         @NonNull
setOverrideOrientation(@creenOrientation int overrideOrientation)388         public Builder setOverrideOrientation(@ScreenOrientation int overrideOrientation) {
389             mOverrideOrientation = overrideOrientation;
390             return this;
391         }
392 
393         /**
394          * Sets {@link android.content.pm.ActivityInfo.Config} mask that specifies which
395          * configuration changes should trigger TaskFragment info change callbacks.
396          *
397          * Only system organizers are allowed to configure this value. This value is ignored for
398          * non-system organizers.
399          *
400          * @see android.content.pm.ActivityInfo.Config
401          * @hide
402          */
403         @NonNull
setConfigurationChangeMask( @ctivityInfo.Config int configurationChangeMask)404         public Builder setConfigurationChangeMask(
405                 @ActivityInfo.Config int configurationChangeMask) {
406             mConfigurationChangeMask = configurationChangeMask;
407             return this;
408         }
409 
410         /** Constructs the options to create TaskFragment with. */
411         @NonNull
build()412         public TaskFragmentCreationParams build() {
413             return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken,
414                     mInitialRelativeBounds, mWindowingMode, mPairedPrimaryFragmentToken,
415                     mPairedActivityToken, mAllowTransitionWhenEmpty, mOverrideOrientation,
416                     mConfigurationChangeMask);
417         }
418     }
419 }
420