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