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.Instrumentation.DEBUG_START_ACTIVITY; 20 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 21 import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS; 22 import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT; 23 import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT; 24 import static android.window.TaskFragmentOperation.OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT; 25 import static android.window.TaskFragmentOperation.OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT; 26 import static android.window.TaskFragmentOperation.OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS; 27 import static android.window.TaskFragmentOperation.OP_TYPE_SET_COMPANION_TASK_FRAGMENT; 28 import static android.window.TaskFragmentOperation.OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT; 29 30 import android.annotation.FlaggedApi; 31 import android.annotation.IntDef; 32 import android.annotation.NonNull; 33 import android.annotation.Nullable; 34 import android.annotation.SuppressLint; 35 import android.annotation.TestApi; 36 import android.app.Instrumentation; 37 import android.app.PendingIntent; 38 import android.app.WindowConfiguration; 39 import android.app.WindowConfiguration.WindowingMode; 40 import android.content.Intent; 41 import android.content.pm.ActivityInfo; 42 import android.content.pm.ShortcutInfo; 43 import android.content.res.Configuration; 44 import android.graphics.Rect; 45 import android.os.Bundle; 46 import android.os.IBinder; 47 import android.os.Parcel; 48 import android.os.Parcelable; 49 import android.util.ArrayMap; 50 import android.util.Log; 51 import android.view.InsetsFrameProvider; 52 import android.view.InsetsSource; 53 import android.view.SurfaceControl; 54 import android.view.WindowInsets; 55 import android.view.WindowInsets.Type.InsetsType; 56 57 import com.android.window.flags.Flags; 58 59 import java.lang.annotation.Retention; 60 import java.lang.annotation.RetentionPolicy; 61 import java.util.ArrayList; 62 import java.util.Arrays; 63 import java.util.List; 64 import java.util.Map; 65 import java.util.Objects; 66 67 /** 68 * Represents a collection of operations on some WindowContainers that should be applied all at 69 * once. 70 * 71 * @hide 72 */ 73 @TestApi 74 public final class WindowContainerTransaction implements Parcelable { 75 private final ArrayMap<IBinder, Change> mChanges = new ArrayMap<>(); 76 77 // Flat list because re-order operations are order-dependent 78 private final ArrayList<HierarchyOp> mHierarchyOps = new ArrayList<>(); 79 80 @Nullable 81 private IBinder mErrorCallbackToken; 82 83 @Nullable 84 private ITaskFragmentOrganizer mTaskFragmentOrganizer; 85 WindowContainerTransaction()86 public WindowContainerTransaction() {} 87 WindowContainerTransaction(@onNull Parcel in)88 private WindowContainerTransaction(@NonNull Parcel in) { 89 in.readMap(mChanges, null /* loader */); 90 in.readTypedList(mHierarchyOps, HierarchyOp.CREATOR); 91 mErrorCallbackToken = in.readStrongBinder(); 92 mTaskFragmentOrganizer = ITaskFragmentOrganizer.Stub.asInterface(in.readStrongBinder()); 93 } 94 95 @NonNull getOrCreateChange(IBinder token)96 private Change getOrCreateChange(IBinder token) { 97 Change out = mChanges.get(token); 98 if (out == null) { 99 out = new Change(); 100 mChanges.put(token, out); 101 } 102 return out; 103 } 104 105 /** 106 * Clear the transaction object. 107 * This is equivalent to a new empty {@link WindowContainerTransaction} in content. 108 * 109 * @hide 110 */ clear()111 public void clear() { 112 mChanges.clear(); 113 mHierarchyOps.clear(); 114 mErrorCallbackToken = null; 115 mTaskFragmentOrganizer = null; 116 } 117 118 /* 119 * =========================================================================================== 120 * Window container properties 121 * =========================================================================================== 122 */ 123 124 /** 125 * Resize a container. 126 */ 127 @NonNull setBounds( @onNull WindowContainerToken container, @NonNull Rect bounds)128 public WindowContainerTransaction setBounds( 129 @NonNull WindowContainerToken container, @NonNull Rect bounds) { 130 final Change chg = getOrCreateChange(container.asBinder()); 131 chg.mConfiguration.windowConfiguration.setBounds(bounds); 132 chg.mConfigSetMask |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION; 133 chg.mWindowSetMask |= WindowConfiguration.WINDOW_CONFIG_BOUNDS; 134 return this; 135 } 136 137 /** 138 * Resize a container's app bounds. This is the bounds used to report appWidth/Height to an 139 * app's DisplayInfo. It is derived by subtracting the overlapping portion of the navbar from 140 * the full bounds. 141 */ 142 @NonNull setAppBounds( @onNull WindowContainerToken container, @NonNull Rect appBounds)143 public WindowContainerTransaction setAppBounds( 144 @NonNull WindowContainerToken container, @NonNull Rect appBounds) { 145 final Change chg = getOrCreateChange(container.asBinder()); 146 chg.mConfiguration.windowConfiguration.setAppBounds(appBounds); 147 chg.mConfigSetMask |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION; 148 chg.mWindowSetMask |= WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; 149 return this; 150 } 151 152 /** 153 * Resize a container's configuration size. The configuration size is what gets reported to the 154 * app via screenWidth/HeightDp and influences which resources get loaded. This size is 155 * derived by subtracting the overlapping portions of both the statusbar and the navbar from 156 * the full bounds. 157 */ 158 @NonNull setScreenSizeDp( @onNull WindowContainerToken container, int w, int h)159 public WindowContainerTransaction setScreenSizeDp( 160 @NonNull WindowContainerToken container, int w, int h) { 161 final Change chg = getOrCreateChange(container.asBinder()); 162 chg.mConfiguration.screenWidthDp = w; 163 chg.mConfiguration.screenHeightDp = h; 164 chg.mConfigSetMask |= ActivityInfo.CONFIG_SCREEN_SIZE; 165 return this; 166 } 167 168 /** 169 * Sets the densityDpi value in the configuration for the given container. 170 * @hide 171 */ 172 @NonNull setDensityDpi(@onNull WindowContainerToken container, int densityDpi)173 public WindowContainerTransaction setDensityDpi(@NonNull WindowContainerToken container, 174 int densityDpi) { 175 final Change chg = getOrCreateChange(container.asBinder()); 176 chg.mConfiguration.densityDpi = densityDpi; 177 chg.mConfigSetMask |= ActivityInfo.CONFIG_DENSITY; 178 return this; 179 } 180 181 /** 182 * Send a SurfaceControl transaction to the server, which the server will apply in sync with 183 * the next bounds change. As this uses deferred transaction and not BLAST it is only 184 * able to sync with a single window, and the first visible window in this hierarchy of type 185 * BASE_APPLICATION to resize will be used. If there are bound changes included in this 186 * WindowContainer transaction (from setBounds or scheduleFinishEnterPip), the SurfaceControl 187 * transaction will be synced with those bounds. If there are no changes, then 188 * the SurfaceControl transaction will be synced with the next bounds change. This means 189 * that you can call this, apply the WindowContainer transaction, and then later call 190 * dismissPip() to achieve synchronization. 191 */ 192 @NonNull setBoundsChangeTransaction( @onNull WindowContainerToken container, @NonNull SurfaceControl.Transaction t)193 public WindowContainerTransaction setBoundsChangeTransaction( 194 @NonNull WindowContainerToken container, @NonNull SurfaceControl.Transaction t) { 195 final Change chg = getOrCreateChange(container.asBinder()); 196 chg.mBoundsChangeTransaction = t; 197 chg.mChangeMask |= Change.CHANGE_BOUNDS_TRANSACTION; 198 return this; 199 } 200 201 /** 202 * Set the windowing mode of children of a given root task, without changing 203 * the windowing mode of the Task itself. This can be used during transitions 204 * for example to make the activity render it's fullscreen configuration 205 * while the Task is still in PIP, so you can complete the animation. 206 * 207 * TODO(b/134365562): Can be removed once TaskOrg drives full-screen 208 */ 209 @NonNull setActivityWindowingMode( @onNull WindowContainerToken container, @WindowingMode int windowingMode)210 public WindowContainerTransaction setActivityWindowingMode( 211 @NonNull WindowContainerToken container, @WindowingMode int windowingMode) { 212 final Change chg = getOrCreateChange(container.asBinder()); 213 chg.mActivityWindowingMode = windowingMode; 214 return this; 215 } 216 217 /** 218 * Sets the windowing mode of the given container. 219 */ 220 @NonNull setWindowingMode( @onNull WindowContainerToken container, @WindowingMode int windowingMode)221 public WindowContainerTransaction setWindowingMode( 222 @NonNull WindowContainerToken container, @WindowingMode int windowingMode) { 223 final Change chg = getOrCreateChange(container.asBinder()); 224 chg.mWindowingMode = windowingMode; 225 return this; 226 } 227 228 /** 229 * Sets whether a container or any of its children can be focusable. When {@code false}, no 230 * child can be focused; however, when {@code true}, it is still possible for children to be 231 * non-focusable due to WM policy. 232 */ 233 @NonNull setFocusable( @onNull WindowContainerToken container, boolean focusable)234 public WindowContainerTransaction setFocusable( 235 @NonNull WindowContainerToken container, boolean focusable) { 236 final Change chg = getOrCreateChange(container.asBinder()); 237 chg.mFocusable = focusable; 238 chg.mChangeMask |= Change.CHANGE_FOCUSABLE; 239 return this; 240 } 241 242 /** 243 * Sets whether the IME insets should be excluded by {@link com.android.server.wm.InsetsPolicy}. 244 * @hide 245 */ 246 @SuppressLint("UnflaggedApi") 247 @NonNull setExcludeImeInsets( @onNull WindowContainerToken container, boolean exclude)248 public WindowContainerTransaction setExcludeImeInsets( 249 @NonNull WindowContainerToken container, boolean exclude) { 250 final HierarchyOp hierarchyOp = 251 new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES) 252 .setContainer(container.asBinder()) 253 .setExcludeInsetsTypes(exclude ? WindowInsets.Type.ime() : 0) 254 .build(); 255 mHierarchyOps.add(hierarchyOp); 256 return this; 257 } 258 259 /** 260 * Sets whether a container or its children should be hidden. When {@code false}, the existing 261 * visibility of the container applies, but when {@code true} the container will be forced 262 * to be hidden. 263 */ 264 @NonNull setHidden( @onNull WindowContainerToken container, boolean hidden)265 public WindowContainerTransaction setHidden( 266 @NonNull WindowContainerToken container, boolean hidden) { 267 final Change chg = getOrCreateChange(container.asBinder()); 268 chg.mHidden = hidden; 269 chg.mChangeMask |= Change.CHANGE_HIDDEN; 270 return this; 271 } 272 273 /** 274 * Set the smallestScreenWidth of a container. 275 */ 276 @NonNull setSmallestScreenWidthDp( @onNull WindowContainerToken container, int widthDp)277 public WindowContainerTransaction setSmallestScreenWidthDp( 278 @NonNull WindowContainerToken container, int widthDp) { 279 final Change cfg = getOrCreateChange(container.asBinder()); 280 cfg.mConfiguration.smallestScreenWidthDp = widthDp; 281 cfg.mConfigSetMask |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 282 return this; 283 } 284 285 /** 286 * Sets whether a container should ignore the orientation request from apps and windows below 287 * it. It currently only applies to {@link com.android.server.wm.DisplayArea}. When 288 * {@code false}, it may rotate based on the orientation request; When {@code true}, it can 289 * never specify orientation, but shows the fixed-orientation apps below it in the letterbox. 290 * @hide 291 */ 292 @NonNull setIgnoreOrientationRequest( @onNull WindowContainerToken container, boolean ignoreOrientationRequest)293 public WindowContainerTransaction setIgnoreOrientationRequest( 294 @NonNull WindowContainerToken container, boolean ignoreOrientationRequest) { 295 final Change chg = getOrCreateChange(container.asBinder()); 296 chg.mIgnoreOrientationRequest = ignoreOrientationRequest; 297 chg.mChangeMask |= Change.CHANGE_IGNORE_ORIENTATION_REQUEST; 298 return this; 299 } 300 301 /** 302 * Sets whether a task should be translucent. When {@code false}, the existing translucent of 303 * the task applies, but when {@code true} the task will be forced to be translucent. 304 * @hide 305 */ 306 @NonNull setForceTranslucent( @onNull WindowContainerToken container, boolean forceTranslucent)307 public WindowContainerTransaction setForceTranslucent( 308 @NonNull WindowContainerToken container, boolean forceTranslucent) { 309 final Change chg = getOrCreateChange(container.asBinder()); 310 chg.mForceTranslucent = forceTranslucent; 311 chg.mChangeMask |= Change.CHANGE_FORCE_TRANSLUCENT; 312 return this; 313 } 314 315 /** 316 * Used in conjunction with a shell-transition call (usually finishTransition). This is 317 * basically a message to the transition system that a particular task should NOT go into 318 * PIP even though it normally would. This is to deal with some edge-case situations where 319 * Recents will "commit" the transition to go home, but then not actually go-home. 320 * @hide 321 */ 322 @NonNull setDoNotPip(@onNull WindowContainerToken container)323 public WindowContainerTransaction setDoNotPip(@NonNull WindowContainerToken container) { 324 final Change chg = getOrCreateChange(container.asBinder()); 325 chg.mChangeMask |= Change.CHANGE_FORCE_NO_PIP; 326 return this; 327 } 328 329 /** 330 * Resizes a container by providing a bounds in its parent coordinate. 331 * This is only used by {@link TaskFragmentOrganizer}. 332 */ 333 @NonNull setRelativeBounds( @onNull WindowContainerToken container, @NonNull Rect relBounds)334 public WindowContainerTransaction setRelativeBounds( 335 @NonNull WindowContainerToken container, @NonNull Rect relBounds) { 336 final Change chg = getOrCreateChange(container.asBinder()); 337 if (chg.mRelativeBounds == null) { 338 chg.mRelativeBounds = new Rect(); 339 } 340 chg.mRelativeBounds.set(relBounds); 341 chg.mChangeMask |= Change.CHANGE_RELATIVE_BOUNDS; 342 // Bounds will be overridden. 343 chg.mConfigSetMask |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION; 344 chg.mWindowSetMask |= WindowConfiguration.WINDOW_CONFIG_BOUNDS; 345 return this; 346 } 347 348 /** 349 * Sets whether a container is being drag-resized. 350 * When {@code true}, the client will reuse a single (larger) surface size to avoid 351 * continuous allocations on every size change. 352 * 353 * @param container WindowContainerToken of the task that changed its drag resizing state 354 * @hide 355 */ 356 @NonNull setDragResizing(@onNull WindowContainerToken container, boolean dragResizing)357 public WindowContainerTransaction setDragResizing(@NonNull WindowContainerToken container, 358 boolean dragResizing) { 359 final Change change = getOrCreateChange(container.asBinder()); 360 change.mChangeMask |= Change.CHANGE_DRAG_RESIZING; 361 change.mDragResizing = dragResizing; 362 return this; 363 } 364 365 /** 366 * Sets/removes the always on top flag for this {@code windowContainer}. See 367 * {@link com.android.server.wm.ConfigurationContainer#setAlwaysOnTop(boolean)}. 368 * Please note that this method is only intended to be used for a 369 * {@link com.android.server.wm.Task} or {@link com.android.server.wm.DisplayArea}. 370 * 371 * <p> 372 * Setting always on top to {@code True} will also make the {@code windowContainer} to move 373 * to the top. 374 * </p> 375 * <p> 376 * Setting always on top to {@code False} will make this {@code windowContainer} to move 377 * below the other always on top sibling containers. 378 * </p> 379 * 380 * @param windowContainer the container which the flag need to be updated for. 381 * @param alwaysOnTop denotes whether or not always on top flag should be set. 382 * @hide 383 */ 384 @NonNull setAlwaysOnTop( @onNull WindowContainerToken windowContainer, boolean alwaysOnTop)385 public WindowContainerTransaction setAlwaysOnTop( 386 @NonNull WindowContainerToken windowContainer, boolean alwaysOnTop) { 387 final HierarchyOp hierarchyOp = 388 new HierarchyOp.Builder( 389 HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP) 390 .setContainer(windowContainer.asBinder()) 391 .setAlwaysOnTop(alwaysOnTop) 392 .build(); 393 mHierarchyOps.add(hierarchyOp); 394 return this; 395 } 396 397 /** 398 * Sets/removes the reparent leaf task flag for this {@code windowContainer}. 399 * When this is set, the server side will try to reparent the leaf task to task display area 400 * if there is an existing activity in history during the activity launch. This operation only 401 * support on the organized root task. 402 * @hide 403 */ 404 @NonNull setReparentLeafTaskIfRelaunch( @onNull WindowContainerToken windowContainer, boolean reparentLeafTaskIfRelaunch)405 public WindowContainerTransaction setReparentLeafTaskIfRelaunch( 406 @NonNull WindowContainerToken windowContainer, boolean reparentLeafTaskIfRelaunch) { 407 final HierarchyOp hierarchyOp = 408 new HierarchyOp.Builder( 409 HierarchyOp.HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH) 410 .setContainer(windowContainer.asBinder()) 411 .setReparentLeafTaskIfRelaunch(reparentLeafTaskIfRelaunch) 412 .build(); 413 mHierarchyOps.add(hierarchyOp); 414 return this; 415 } 416 417 /** 418 * Defers client-facing configuration changes for activities in `container` until the end of 419 * the transition animation. The configuration will still be applied to the WMCore hierarchy 420 * at the normal time (beginning); so, special consideration must be made for this in the 421 * animation. 422 * 423 * @param container WindowContainerToken who's children should defer config notification. 424 * @hide 425 */ 426 @NonNull deferConfigToTransitionEnd( @onNull WindowContainerToken container)427 public WindowContainerTransaction deferConfigToTransitionEnd( 428 @NonNull WindowContainerToken container) { 429 final Change change = getOrCreateChange(container.asBinder()); 430 change.mConfigAtTransitionEnd = true; 431 return this; 432 } 433 434 /** 435 * Sets the task as trimmable or not. This can be used to prevent the task from being trimmed by 436 * recents. This attribute is set to true on task creation by default. 437 * 438 * @param isTrimmableFromRecents When {@code true}, task is set as trimmable from recents. 439 * @hide 440 */ 441 @NonNull setTaskTrimmableFromRecents( @onNull WindowContainerToken container, boolean isTrimmableFromRecents)442 public WindowContainerTransaction setTaskTrimmableFromRecents( 443 @NonNull WindowContainerToken container, 444 boolean isTrimmableFromRecents) { 445 mHierarchyOps.add( 446 HierarchyOp.createForSetTaskTrimmableFromRecents(container.asBinder(), 447 isTrimmableFromRecents)); 448 return this; 449 } 450 451 /** 452 * Sets a given safe region {@code Rect} on the {@code container}. Set {@code null} to reset 453 * safe region bounds. When a safe region is set on a WindowContainer, the activities which 454 * need to be within a safe region will be letterboxed within the set safe region bounds. 455 * <p>Note that if the position of the WindowContainer changes, the caller needs to update the 456 * safe region bounds. 457 * 458 * @param container The window container that the safe region bounds are set on 459 * @param safeRegionBounds The rect for the safe region bounds which are absolute in nature. 460 * @hide 461 */ 462 @NonNull 463 @FlaggedApi(Flags.FLAG_SAFE_REGION_LETTERBOXING) setSafeRegionBounds( @onNull WindowContainerToken container, @Nullable Rect safeRegionBounds)464 public WindowContainerTransaction setSafeRegionBounds( 465 @NonNull WindowContainerToken container, 466 @Nullable Rect safeRegionBounds) { 467 mHierarchyOps.add( 468 HierarchyOp.createForSetSafeRegionBounds(container.asBinder(), safeRegionBounds)); 469 return this; 470 } 471 472 /* 473 * =========================================================================================== 474 * Hierarchy updates (create/destroy/reorder/reparent containers) 475 * =========================================================================================== 476 */ 477 478 /** 479 * Reorders a container within its parent. 480 * 481 * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to 482 * the bottom. 483 */ 484 @NonNull reorder(@onNull WindowContainerToken child, boolean onTop)485 public WindowContainerTransaction reorder(@NonNull WindowContainerToken child, boolean onTop) { 486 return reorder(child, onTop, false /* includingParents */); 487 } 488 489 /** 490 * Reorders a container within its parent with an option to reorder all the parents in the 491 * hierarchy above among their respective siblings. 492 * 493 * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to 494 * the bottom. 495 * @param includingParents When {@code true}, all the parents in the hierarchy above are also 496 * reordered among their respective siblings. 497 * @hide 498 */ 499 @NonNull reorder(@onNull WindowContainerToken child, boolean onTop, boolean includingParents)500 public WindowContainerTransaction reorder(@NonNull WindowContainerToken child, boolean onTop, 501 boolean includingParents) { 502 mHierarchyOps.add(HierarchyOp.createForReorder(child.asBinder(), onTop, includingParents)); 503 return this; 504 } 505 506 /** 507 * Reparents a container into another one. The effect of a {@code null} parent can vary. For 508 * example, reparenting a stack to {@code null} will reparent it to its display. 509 * 510 * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to 511 * the bottom. 512 */ 513 @NonNull reparent(@onNull WindowContainerToken child, @Nullable WindowContainerToken parent, boolean onTop)514 public WindowContainerTransaction reparent(@NonNull WindowContainerToken child, 515 @Nullable WindowContainerToken parent, boolean onTop) { 516 mHierarchyOps.add(HierarchyOp.createForReparent(child.asBinder(), 517 parent == null ? null : parent.asBinder(), 518 onTop)); 519 return this; 520 } 521 522 /** 523 * Reparent's all children tasks or the top task of {@param currentParent} in the specified 524 * {@param windowingMode} and {@param activityType} to {@param newParent} in their current 525 * z-order. 526 * 527 * @param currentParent of the tasks to perform the operation no. 528 * {@code null} will perform the operation on the display. 529 * @param newParent for the tasks. {@code null} will perform the operation on the display. 530 * @param windowingModes of the tasks to reparent. 531 * @param activityTypes of the tasks to reparent. 532 * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to 533 * the bottom. 534 * @param reparentTopOnly When {@code true}, only reparent the top task which fit windowingModes 535 * and activityTypes. 536 * @hide 537 */ 538 @NonNull reparentTasks(@ullable WindowContainerToken currentParent, @Nullable WindowContainerToken newParent, @Nullable int[] windowingModes, @Nullable int[] activityTypes, boolean onTop, boolean reparentTopOnly)539 public WindowContainerTransaction reparentTasks(@Nullable WindowContainerToken currentParent, 540 @Nullable WindowContainerToken newParent, @Nullable int[] windowingModes, 541 @Nullable int[] activityTypes, boolean onTop, boolean reparentTopOnly) { 542 mHierarchyOps.add(HierarchyOp.createForChildrenTasksReparent( 543 currentParent != null ? currentParent.asBinder() : null, 544 newParent != null ? newParent.asBinder() : null, 545 windowingModes, 546 activityTypes, 547 onTop, 548 reparentTopOnly)); 549 return this; 550 } 551 552 /** 553 * Reparent's all children tasks of {@param currentParent} in the specified 554 * {@param windowingMode} and {@param activityType} to {@param newParent} in their current 555 * z-order. 556 * 557 * @param currentParent of the tasks to perform the operation no. 558 * {@code null} will perform the operation on the display. 559 * @param newParent for the tasks. {@code null} will perform the operation on the display. 560 * @param windowingModes of the tasks to reparent. {@code null} ignore this attribute when 561 * perform the operation. 562 * @param activityTypes of the tasks to reparent. {@code null} ignore this attribute when 563 * perform the operation. 564 * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to 565 * the bottom. 566 */ 567 @NonNull reparentTasks(@ullable WindowContainerToken currentParent, @Nullable WindowContainerToken newParent, @Nullable int[] windowingModes, @Nullable int[] activityTypes, boolean onTop)568 public WindowContainerTransaction reparentTasks(@Nullable WindowContainerToken currentParent, 569 @Nullable WindowContainerToken newParent, @Nullable int[] windowingModes, 570 @Nullable int[] activityTypes, boolean onTop) { 571 return reparentTasks(currentParent, newParent, windowingModes, activityTypes, onTop, 572 false /* reparentTopOnly */); 573 } 574 575 /** 576 * Finds and removes a task and its children using its container token. The task is removed 577 * from recents. 578 * 579 * If the task is a root task, its leaves are removed but the root task is not. Use 580 * {@link #removeRootTask(WindowContainerToken)} to remove the root task. 581 * 582 * @param containerToken ContainerToken of Task to be removed 583 */ 584 @NonNull removeTask(@onNull WindowContainerToken containerToken)585 public WindowContainerTransaction removeTask(@NonNull WindowContainerToken containerToken) { 586 mHierarchyOps.add(HierarchyOp.createForRemoveTask(containerToken.asBinder())); 587 return this; 588 } 589 590 /** 591 * Finds and removes a root task created by an organizer and its leaves using its container 592 * token. 593 * 594 * @param containerToken ContainerToken of the root task to be removed 595 * @hide 596 */ 597 @NonNull removeRootTask(@onNull WindowContainerToken containerToken)598 public WindowContainerTransaction removeRootTask(@NonNull WindowContainerToken containerToken) { 599 mHierarchyOps.add(HierarchyOp.createForRemoveRootTask(containerToken.asBinder())); 600 return this; 601 } 602 603 /** 604 * If `container` was brought to front as a transient-launch (eg. recents), this will reorder 605 * the container back to where it was prior to the transient-launch. This way if a transient 606 * launch is "aborted", the z-ordering of containers in WM should be restored to before the 607 * launch. 608 * @hide 609 */ 610 @NonNull restoreTransientOrder( @onNull WindowContainerToken container)611 public WindowContainerTransaction restoreTransientOrder( 612 @NonNull WindowContainerToken container) { 613 final HierarchyOp hierarchyOp = 614 new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER) 615 .setContainer(container.asBinder()) 616 .build(); 617 mHierarchyOps.add(hierarchyOp); 618 return this; 619 } 620 621 /** 622 * Restore the back navigation target from visible to invisible for canceling gesture animation. 623 * @hide 624 */ 625 @NonNull restoreBackNavi()626 public WindowContainerTransaction restoreBackNavi() { 627 final HierarchyOp hierarchyOp = 628 new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION) 629 .build(); 630 mHierarchyOps.add(hierarchyOp); 631 return this; 632 } 633 634 /* 635 * =========================================================================================== 636 * Activity launch 637 * =========================================================================================== 638 */ 639 640 /** 641 * Starts a task by id. The task is expected to already exist (eg. as a recent task). 642 * @param taskId Id of task to start. 643 * @param options bundle containing ActivityOptions for the task's top activity. 644 * @hide 645 */ 646 @NonNull startTask(int taskId, @Nullable Bundle options)647 public WindowContainerTransaction startTask(int taskId, @Nullable Bundle options) { 648 if (DEBUG_START_ACTIVITY) { 649 Log.d(Instrumentation.TAG, "WCT.startTask: taskId=" + taskId 650 + " options=" + options, new Throwable()); 651 } 652 mHierarchyOps.add(HierarchyOp.createForTaskLaunch(taskId, options)); 653 return this; 654 } 655 656 /** 657 * Sends a pending intent in sync. 658 * @param sender The PendingIntent sender. 659 * @param intent The fillIn intent to patch over the sender's base intent. 660 * @param options bundle containing ActivityOptions for the task's top activity. 661 * @hide 662 */ 663 @NonNull sendPendingIntent(@ullable PendingIntent sender, @Nullable Intent fillInIntent, @Nullable Bundle options)664 public WindowContainerTransaction sendPendingIntent(@Nullable PendingIntent sender, 665 @Nullable Intent fillInIntent, @Nullable Bundle options) { 666 if (DEBUG_START_ACTIVITY) { 667 Log.d(Instrumentation.TAG, "WCT.sendPendingIntent: sender=" + sender.getIntent() 668 + " fillInIntent=" + fillInIntent + " options=" + options, new Throwable()); 669 } 670 mHierarchyOps.add(new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_PENDING_INTENT) 671 .setLaunchOptions(options) 672 .setPendingIntent(sender) 673 .setActivityIntent(fillInIntent) 674 .build()); 675 return this; 676 } 677 678 /** 679 * Starts activity(s) from a shortcut. 680 * @param callingPackage The package launching the shortcut. 681 * @param shortcutInfo Information about the shortcut to start 682 * @param options bundle containing ActivityOptions for the task's top activity. 683 * @hide 684 */ 685 @NonNull startShortcut(@onNull String callingPackage, @NonNull ShortcutInfo shortcutInfo, @Nullable Bundle options)686 public WindowContainerTransaction startShortcut(@NonNull String callingPackage, 687 @NonNull ShortcutInfo shortcutInfo, @Nullable Bundle options) { 688 if (DEBUG_START_ACTIVITY) { 689 Log.d(Instrumentation.TAG, "WCT.startShortcut: shortcutInfo=" + shortcutInfo 690 + " options=" + options, new Throwable()); 691 } 692 mHierarchyOps.add(HierarchyOp.createForStartShortcut( 693 callingPackage, shortcutInfo, options)); 694 return this; 695 } 696 697 /** 698 * Sets whether a container should be the launch root for the specified windowing mode and 699 * activity type. This currently only applies to Task containers created by organizer. 700 */ 701 @NonNull setLaunchRoot(@onNull WindowContainerToken container, @Nullable int[] windowingModes, @Nullable int[] activityTypes)702 public WindowContainerTransaction setLaunchRoot(@NonNull WindowContainerToken container, 703 @Nullable int[] windowingModes, @Nullable int[] activityTypes) { 704 mHierarchyOps.add(HierarchyOp.createForSetLaunchRoot( 705 container.asBinder(), 706 windowingModes, 707 activityTypes)); 708 return this; 709 } 710 711 /* 712 * =========================================================================================== 713 * Multitasking 714 * =========================================================================================== 715 */ 716 717 /** 718 * Sets two containers adjacent to each other. Containers below two visible adjacent roots will 719 * be made invisible. This currently only applies to TaskFragment containers created by 720 * organizer. 721 * @param root1 the first root. 722 * @param root2 the second root. 723 * @deprecated replace with {@link #setAdjacentRootSet} 724 */ 725 @SuppressWarnings("UnflaggedApi") // @TestApi without associated feature. 726 @Deprecated 727 @NonNull setAdjacentRoots( @onNull WindowContainerToken root1, @NonNull WindowContainerToken root2)728 public WindowContainerTransaction setAdjacentRoots( 729 @NonNull WindowContainerToken root1, @NonNull WindowContainerToken root2) { 730 return setAdjacentRootSet(root1, root2); 731 } 732 733 /** 734 * Sets multiple containers adjacent to each other. Containers below the visible adjacent roots 735 * will be made invisible. This currently only applies to Task containers created by organizer. 736 * 737 * To remove one container from the adjacent roots, one can call {@link #clearAdjacentRoots} 738 * with the target container. 739 * To remove all containers from the adjacent roots, one much call {@link #clearAdjacentRoots} 740 * on each container if there were more than two containers in the set. 741 * 742 * For non-Task TaskFragment, use {@link #setAdjacentTaskFragments} instead. 743 * 744 * @param roots the Tasks that should be adjacent to each other. 745 * @throws IllegalArgumentException if roots have size < 2. 746 * @hide // TODO(b/373709676) Rename to setAdjacentRoots and update CTS in 25Q4. 747 */ 748 @NonNull setAdjacentRootSet(@onNull WindowContainerToken... roots)749 public WindowContainerTransaction setAdjacentRootSet(@NonNull WindowContainerToken... roots) { 750 if (roots.length < 2) { 751 throw new IllegalArgumentException("setAdjacentRootSet must have size >= 2"); 752 } 753 final IBinder[] rootTokens = new IBinder[roots.length]; 754 for (int i = 0; i < roots.length; i++) { 755 rootTokens[i] = roots[i].asBinder(); 756 } 757 mHierarchyOps.add( 758 new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS) 759 .setContainers(rootTokens) 760 .build()); 761 return this; 762 } 763 764 /** 765 * Clears container adjacent. 766 * If {@link #setAdjacentRootSet} is called with more than 2 roots, calling this will only 767 * remove the given root from the adjacent set. The rest of roots will stay adjacent to each 768 * other. 769 * 770 * @param root the root container to clear the adjacent roots for. 771 * @hide 772 */ 773 @NonNull clearAdjacentRoots(@onNull WindowContainerToken root)774 public WindowContainerTransaction clearAdjacentRoots(@NonNull WindowContainerToken root) { 775 mHierarchyOps.add(HierarchyOp.createForClearAdjacentRoots(root.asBinder())); 776 return this; 777 } 778 779 /** 780 * Sets the container as launch adjacent flag root. Task starting with 781 * {@link FLAG_ACTIVITY_LAUNCH_ADJACENT} will be launching to. 782 */ 783 @NonNull setLaunchAdjacentFlagRoot( @onNull WindowContainerToken container)784 public WindowContainerTransaction setLaunchAdjacentFlagRoot( 785 @NonNull WindowContainerToken container) { 786 mHierarchyOps.add(HierarchyOp.createForSetLaunchAdjacentFlagRoot(container.asBinder(), 787 false /* clearRoot */)); 788 return this; 789 } 790 791 /** 792 * Clears launch adjacent flag root for the display area of passing container. 793 */ 794 @NonNull clearLaunchAdjacentFlagRoot( @onNull WindowContainerToken container)795 public WindowContainerTransaction clearLaunchAdjacentFlagRoot( 796 @NonNull WindowContainerToken container) { 797 mHierarchyOps.add(HierarchyOp.createForSetLaunchAdjacentFlagRoot(container.asBinder(), 798 true /* clearRoot */)); 799 return this; 800 } 801 802 /** 803 * Disables or enables activities to be started in adjacent tasks (see 804 * {@link FLAG_ACTIVITY_LAUNCH_ADJACENT}) for the specified root of any child tasks. This 805 * differs from {@link #setLaunchAdjacentFlagRoot(WindowContainerToken)} which controls the 806 * preferred launch-adjacent target and allows for selectively setting which root tasks can 807 * support launch-adjacent. 808 * @hide 809 */ 810 @NonNull setDisableLaunchAdjacent( @onNull WindowContainerToken container, boolean disabled)811 public WindowContainerTransaction setDisableLaunchAdjacent( 812 @NonNull WindowContainerToken container, boolean disabled) { 813 mHierarchyOps.add(HierarchyOp.createForSetDisableLaunchAdjacent(container.asBinder(), 814 disabled)); 815 return this; 816 } 817 818 /* 819 * =========================================================================================== 820 * PIP 821 * =========================================================================================== 822 */ 823 824 /** 825 * Moves the PiP activity of a parent task to a pinned root task. 826 * @param parentToken the parent task of the PiP activity 827 * @param bounds the entry bounds 828 * @hide 829 */ 830 @NonNull movePipActivityToPinnedRootTask( @onNull WindowContainerToken parentToken, @NonNull Rect bounds)831 public WindowContainerTransaction movePipActivityToPinnedRootTask( 832 @NonNull WindowContainerToken parentToken, @NonNull Rect bounds) { 833 mHierarchyOps.add(new HierarchyOp 834 .Builder(HierarchyOp.HIERARCHY_OP_TYPE_MOVE_PIP_ACTIVITY_TO_PINNED_TASK) 835 .setContainer(parentToken.asBinder()) 836 .setBounds(bounds) 837 .build()); 838 return this; 839 } 840 841 /** 842 * Notify {@link com.android.server.wm.PinnedTaskController} that the picture-in-picture task 843 * has finished the enter animation with the given bounds. 844 */ 845 @NonNull scheduleFinishEnterPip( @onNull WindowContainerToken container, @NonNull Rect bounds)846 public WindowContainerTransaction scheduleFinishEnterPip( 847 @NonNull WindowContainerToken container, @NonNull Rect bounds) { 848 final Change chg = getOrCreateChange(container.asBinder()); 849 chg.mPinnedBounds = new Rect(bounds); 850 chg.mChangeMask |= Change.CHANGE_PIP_CALLBACK; 851 852 return this; 853 } 854 855 /* 856 * =========================================================================================== 857 * Insets 858 * =========================================================================================== 859 */ 860 861 /** 862 * Adds a given {@code Rect} as an insets source frame on the {@code receiver}. 863 * 864 * @param receiver The window container that the insets source is added to. 865 * @param owner The owner of the insets source. An insets source can only be modified by its 866 * owner. 867 * @param index An owner might add multiple insets sources with the same type. 868 * This identifies them. 869 * @param type The {@link InsetsType} of the insets source. 870 * @param frame The rectangle area of the insets source. 871 * @param boundingRects The bounding rects within this inset, relative to the |frame|. 872 * @hide 873 */ 874 @NonNull addInsetsSource( @onNull WindowContainerToken receiver, @Nullable IBinder owner, int index, @InsetsType int type, @Nullable Rect frame, @Nullable Rect[] boundingRects, @InsetsSource.Flags int flags)875 public WindowContainerTransaction addInsetsSource( 876 @NonNull WindowContainerToken receiver, 877 @Nullable IBinder owner, int index, @InsetsType int type, @Nullable Rect frame, 878 @Nullable Rect[] boundingRects, @InsetsSource.Flags int flags) { 879 final HierarchyOp hierarchyOp = 880 new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER) 881 .setContainer(receiver.asBinder()) 882 .setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type) 883 .setSource(InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE) 884 .setArbitraryRectangle(frame) 885 .setBoundingRects(boundingRects) 886 .setFlags(flags)) 887 .setInsetsFrameOwner(owner) 888 .build(); 889 mHierarchyOps.add(hierarchyOp); 890 return this; 891 } 892 893 /** 894 * Removes the insets source from the {@code receiver}. 895 * 896 * @param receiver The window container that the insets source was added to. 897 * @param owner The owner of the insets source. An insets source can only be modified by its 898 * owner. 899 * @param index An owner might add multiple insets sources with the same type. 900 * This identifies them. 901 * @param type The {@link InsetsType} of the insets source. 902 * @hide 903 */ 904 @NonNull removeInsetsSource(@onNull WindowContainerToken receiver, @Nullable IBinder owner, int index, @InsetsType int type)905 public WindowContainerTransaction removeInsetsSource(@NonNull WindowContainerToken receiver, 906 @Nullable IBinder owner, int index, @InsetsType int type) { 907 final HierarchyOp hierarchyOp = 908 new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER) 909 .setContainer(receiver.asBinder()) 910 .setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type)) 911 .setInsetsFrameOwner(owner) 912 .build(); 913 mHierarchyOps.add(hierarchyOp); 914 return this; 915 } 916 917 /* 918 * =========================================================================================== 919 * Keyguard 920 * =========================================================================================== 921 */ 922 923 /** 924 * Adds a {@link KeyguardState} to apply to the given displays. 925 * 926 * @hide 927 */ 928 @NonNull addKeyguardState(@onNull KeyguardState keyguardState)929 public WindowContainerTransaction addKeyguardState(@NonNull KeyguardState keyguardState) { 930 Objects.requireNonNull(keyguardState); 931 final HierarchyOp hierarchyOp = 932 new HierarchyOp.Builder( 933 HierarchyOp.HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE) 934 .setKeyguardState(keyguardState) 935 .build(); 936 mHierarchyOps.add(hierarchyOp); 937 return this; 938 } 939 940 /* 941 * =========================================================================================== 942 * Task fragments 943 * =========================================================================================== 944 */ 945 946 /** 947 * Sets the {@link TaskFragmentOrganizer} that applies this {@link WindowContainerTransaction}. 948 * When this is set, the server side will not check for the permission of 949 * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, but will ensure this WCT only 950 * contains operations that are allowed for this organizer, such as modifying TaskFragments that 951 * are organized by this organizer. 952 * @hide 953 */ 954 @NonNull setTaskFragmentOrganizer( @onNull ITaskFragmentOrganizer organizer)955 public WindowContainerTransaction setTaskFragmentOrganizer( 956 @NonNull ITaskFragmentOrganizer organizer) { 957 mTaskFragmentOrganizer = organizer; 958 return this; 959 } 960 961 /** 962 * When this {@link WindowContainerTransaction} failed to finish on the server side, it will 963 * trigger callback with this {@param errorCallbackToken}. 964 * @param errorCallbackToken client provided token that will be passed back as parameter in 965 * the callback if there is an error on the server side. 966 * @see ITaskFragmentOrganizer#onTaskFragmentError 967 */ 968 @NonNull setErrorCallbackToken(@onNull IBinder errorCallbackToken)969 public WindowContainerTransaction setErrorCallbackToken(@NonNull IBinder errorCallbackToken) { 970 if (mErrorCallbackToken != null) { 971 throw new IllegalStateException("Can't set multiple error token for one transaction."); 972 } 973 mErrorCallbackToken = errorCallbackToken; 974 return this; 975 } 976 977 /** 978 * Creates a new TaskFragment with the given options. 979 * @param taskFragmentCreationParams the options used to create the TaskFragment. 980 */ 981 @NonNull createTaskFragment( @onNull TaskFragmentCreationParams taskFragmentCreationParams)982 public WindowContainerTransaction createTaskFragment( 983 @NonNull TaskFragmentCreationParams taskFragmentCreationParams) { 984 final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( 985 OP_TYPE_CREATE_TASK_FRAGMENT) 986 .setTaskFragmentCreationParams(taskFragmentCreationParams) 987 .build(); 988 return addTaskFragmentOperation(taskFragmentCreationParams.getFragmentToken(), operation); 989 } 990 991 /** 992 * Deletes an existing TaskFragment. Any remaining activities below it will be destroyed. 993 * @param fragmentToken client assigned unique token to create TaskFragment with specified in 994 * {@link TaskFragmentCreationParams#getFragmentToken()}. 995 */ 996 @NonNull deleteTaskFragment(@onNull IBinder fragmentToken)997 public WindowContainerTransaction deleteTaskFragment(@NonNull IBinder fragmentToken) { 998 final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( 999 OP_TYPE_DELETE_TASK_FRAGMENT) 1000 .build(); 1001 return addTaskFragmentOperation(fragmentToken, operation); 1002 } 1003 1004 /** 1005 * Starts an activity in the TaskFragment. 1006 * @param fragmentToken client assigned unique token to create TaskFragment with specified in 1007 * {@link TaskFragmentCreationParams#getFragmentToken()}. 1008 * @param callerToken the activity token that initialized the activity launch. 1009 * @param activityIntent intent to start the activity. 1010 * @param activityOptions ActivityOptions to start the activity with. 1011 * @see android.content.Context#startActivity(Intent, Bundle). 1012 */ 1013 @NonNull startActivityInTaskFragment( @onNull IBinder fragmentToken, @NonNull IBinder callerToken, @NonNull Intent activityIntent, @Nullable Bundle activityOptions)1014 public WindowContainerTransaction startActivityInTaskFragment( 1015 @NonNull IBinder fragmentToken, @NonNull IBinder callerToken, 1016 @NonNull Intent activityIntent, @Nullable Bundle activityOptions) { 1017 final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( 1018 OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT) 1019 .setActivityToken(callerToken) 1020 .setActivityIntent(activityIntent) 1021 .setBundle(activityOptions) 1022 .build(); 1023 return addTaskFragmentOperation(fragmentToken, operation); 1024 } 1025 1026 /** 1027 * Moves an activity into the TaskFragment. 1028 * @param fragmentToken client assigned unique token to create TaskFragment with specified in 1029 * {@link TaskFragmentCreationParams#getFragmentToken()}. 1030 * @param activityToken activity to be reparented. 1031 */ 1032 @NonNull reparentActivityToTaskFragment( @onNull IBinder fragmentToken, @NonNull IBinder activityToken)1033 public WindowContainerTransaction reparentActivityToTaskFragment( 1034 @NonNull IBinder fragmentToken, @NonNull IBinder activityToken) { 1035 final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( 1036 OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT) 1037 .setActivityToken(activityToken) 1038 .build(); 1039 return addTaskFragmentOperation(fragmentToken, operation); 1040 } 1041 1042 /** 1043 * Sets to TaskFragments adjacent to each other. Containers below two visible adjacent 1044 * TaskFragments will be made invisible. This is similar to 1045 * {@link #setAdjacentRootSet(WindowContainerToken...)}, but can be used with 1046 * fragmentTokens when that TaskFragments haven't been created (but will be created in the same 1047 * {@link WindowContainerTransaction}). 1048 * @param fragmentToken1 client assigned unique token to create TaskFragment with specified 1049 * in {@link TaskFragmentCreationParams#getFragmentToken()}. 1050 * @param fragmentToken2 client assigned unique token to create TaskFragment with specified 1051 * in {@link TaskFragmentCreationParams#getFragmentToken()}. 1052 */ 1053 @NonNull setAdjacentTaskFragments( @onNull IBinder fragmentToken1, @NonNull IBinder fragmentToken2, @Nullable TaskFragmentAdjacentParams params)1054 public WindowContainerTransaction setAdjacentTaskFragments( 1055 @NonNull IBinder fragmentToken1, @NonNull IBinder fragmentToken2, 1056 @Nullable TaskFragmentAdjacentParams params) { 1057 final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( 1058 OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS) 1059 .setSecondaryFragmentToken(fragmentToken2) 1060 .setBundle(params != null ? params.toBundle() : null) 1061 .build(); 1062 return addTaskFragmentOperation(fragmentToken1, operation); 1063 } 1064 1065 /** 1066 * Clears the adjacent TaskFragments relationship that is previously set through 1067 * {@link #setAdjacentTaskFragments}. Clear operation on one TaskFragment will also clear its 1068 * current adjacent TaskFragment's. 1069 * @param fragmentToken client assigned unique token to create TaskFragment with specified 1070 * in {@link TaskFragmentCreationParams#getFragmentToken()}. 1071 */ 1072 @NonNull clearAdjacentTaskFragments(@onNull IBinder fragmentToken)1073 public WindowContainerTransaction clearAdjacentTaskFragments(@NonNull IBinder fragmentToken) { 1074 final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( 1075 OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS) 1076 .build(); 1077 return addTaskFragmentOperation(fragmentToken, operation); 1078 } 1079 1080 /** 1081 * Requests focus on the top running Activity in the given TaskFragment. This will only take 1082 * effect if there is no focus, or if the current focus is in the same Task as the requested 1083 * TaskFragment. 1084 * @param fragmentToken client assigned unique token to create TaskFragment with specified in 1085 * {@link TaskFragmentCreationParams#getFragmentToken()}. 1086 */ 1087 @NonNull requestFocusOnTaskFragment(@onNull IBinder fragmentToken)1088 public WindowContainerTransaction requestFocusOnTaskFragment(@NonNull IBinder fragmentToken) { 1089 final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( 1090 OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT) 1091 .build(); 1092 return addTaskFragmentOperation(fragmentToken, operation); 1093 } 1094 1095 /** 1096 * Finishes the Activity. 1097 * Comparing to directly calling {@link android.app.Activity#finish()}, calling this can make 1098 * sure the finishing happens in the same transaction with other operations. 1099 * @param activityToken activity to be finished. 1100 */ 1101 @NonNull finishActivity(@onNull IBinder activityToken)1102 public WindowContainerTransaction finishActivity(@NonNull IBinder activityToken) { 1103 final HierarchyOp hierarchyOp = 1104 new HierarchyOp.Builder( 1105 HierarchyOp.HIERARCHY_OP_TYPE_FINISH_ACTIVITY) 1106 .setContainer(activityToken) 1107 .build(); 1108 mHierarchyOps.add(hierarchyOp); 1109 return this; 1110 } 1111 1112 /** 1113 * Sets the TaskFragment {@code fragmentToken} to have a companion TaskFragment 1114 * {@code companionFragmentToken}. 1115 * This indicates that the organizer will remove the TaskFragment when the companion 1116 * TaskFragment is removed. 1117 * 1118 * @param fragmentToken client assigned unique token to create TaskFragment with specified 1119 * in {@link TaskFragmentCreationParams#getFragmentToken()}. 1120 * @param companionFragmentToken client assigned unique token to create TaskFragment with 1121 * specified in 1122 * {@link TaskFragmentCreationParams#getFragmentToken()}. 1123 * If it is {@code null}, the transaction will reset the companion 1124 * TaskFragment. 1125 * @hide 1126 */ 1127 @NonNull setCompanionTaskFragment(@onNull IBinder fragmentToken, @Nullable IBinder companionFragmentToken)1128 public WindowContainerTransaction setCompanionTaskFragment(@NonNull IBinder fragmentToken, 1129 @Nullable IBinder companionFragmentToken) { 1130 final TaskFragmentOperation operation = new TaskFragmentOperation.Builder( 1131 OP_TYPE_SET_COMPANION_TASK_FRAGMENT) 1132 .setSecondaryFragmentToken(companionFragmentToken) 1133 .build(); 1134 return addTaskFragmentOperation(fragmentToken, operation); 1135 } 1136 1137 /** 1138 * Adds a {@link TaskFragmentOperation} to apply to the given TaskFragment. 1139 * 1140 * @param fragmentToken client assigned unique token to create TaskFragment with specified in 1141 * {@link TaskFragmentCreationParams#getFragmentToken()}. 1142 * @param taskFragmentOperation the {@link TaskFragmentOperation} to apply to the given 1143 * TaskFramgent. 1144 * @hide 1145 */ 1146 @NonNull addTaskFragmentOperation(@onNull IBinder fragmentToken, @NonNull TaskFragmentOperation taskFragmentOperation)1147 public WindowContainerTransaction addTaskFragmentOperation(@NonNull IBinder fragmentToken, 1148 @NonNull TaskFragmentOperation taskFragmentOperation) { 1149 Objects.requireNonNull(fragmentToken); 1150 Objects.requireNonNull(taskFragmentOperation); 1151 final HierarchyOp hierarchyOp = 1152 new HierarchyOp.Builder( 1153 HierarchyOp.HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION) 1154 .setContainer(fragmentToken) 1155 .setTaskFragmentOperation(taskFragmentOperation) 1156 .build(); 1157 mHierarchyOps.add(hierarchyOp); 1158 return this; 1159 } 1160 1161 /** 1162 * Adds a hierarchy op for app compat reachability. 1163 * 1164 * @param container The token for the container Task 1165 * @param taskId The id of the current task 1166 * @hide 1167 */ setReachabilityOffset( @onNull WindowContainerToken container, int taskId, int x, int y)1168 public WindowContainerTransaction setReachabilityOffset( 1169 @NonNull WindowContainerToken container, int taskId, int x, int y) { 1170 mHierarchyOps.add(HierarchyOp.createForReachability(container.asBinder(), taskId, x, y)); 1171 return this; 1172 } 1173 1174 /** 1175 * Merges another WCT into this one. 1176 * @param transfer When true, this will transfer everything from other potentially leaving 1177 * other in an unusable state. When false, other is left alone, but 1178 * SurfaceFlinger Transactions will not be merged. 1179 * @hide 1180 */ merge(@onNull WindowContainerTransaction other, boolean transfer)1181 public void merge(@NonNull WindowContainerTransaction other, boolean transfer) { 1182 for (int i = 0, n = other.mChanges.size(); i < n; ++i) { 1183 final IBinder key = other.mChanges.keyAt(i); 1184 Change existing = mChanges.get(key); 1185 if (existing == null) { 1186 existing = new Change(); 1187 mChanges.put(key, existing); 1188 } 1189 existing.merge(other.mChanges.valueAt(i), transfer); 1190 } 1191 for (int i = 0, n = other.mHierarchyOps.size(); i < n; ++i) { 1192 final HierarchyOp otherHierarchyOp = other.mHierarchyOps.get(i); 1193 mHierarchyOps.add(transfer ? otherHierarchyOp : new HierarchyOp(otherHierarchyOp)); 1194 } 1195 if (mErrorCallbackToken != null && other.mErrorCallbackToken != null && mErrorCallbackToken 1196 != other.mErrorCallbackToken) { 1197 throw new IllegalArgumentException("Can't merge two WCTs with different error token"); 1198 } 1199 final IBinder taskFragmentOrganizerAsBinder = mTaskFragmentOrganizer != null 1200 ? mTaskFragmentOrganizer.asBinder() 1201 : null; 1202 final IBinder otherTaskFragmentOrganizerAsBinder = other.mTaskFragmentOrganizer != null 1203 ? other.mTaskFragmentOrganizer.asBinder() 1204 : null; 1205 if (!Objects.equals(taskFragmentOrganizerAsBinder, otherTaskFragmentOrganizerAsBinder)) { 1206 throw new IllegalArgumentException( 1207 "Can't merge two WCTs from different TaskFragmentOrganizers"); 1208 } 1209 mErrorCallbackToken = mErrorCallbackToken != null 1210 ? mErrorCallbackToken 1211 : other.mErrorCallbackToken; 1212 } 1213 1214 /** @hide */ isEmpty()1215 public boolean isEmpty() { 1216 return mChanges.isEmpty() && mHierarchyOps.isEmpty(); 1217 } 1218 1219 /** @hide */ 1220 @NonNull getChanges()1221 public Map<IBinder, Change> getChanges() { 1222 return mChanges; 1223 } 1224 1225 /** @hide */ 1226 @NonNull getHierarchyOps()1227 public List<HierarchyOp> getHierarchyOps() { 1228 return mHierarchyOps; 1229 } 1230 1231 /** @hide */ 1232 @Nullable getErrorCallbackToken()1233 public IBinder getErrorCallbackToken() { 1234 return mErrorCallbackToken; 1235 } 1236 1237 /** @hide */ 1238 @Nullable getTaskFragmentOrganizer()1239 public ITaskFragmentOrganizer getTaskFragmentOrganizer() { 1240 return mTaskFragmentOrganizer; 1241 } 1242 1243 @Override 1244 @NonNull toString()1245 public String toString() { 1246 return "WindowContainerTransaction {" 1247 + " changes= " + mChanges 1248 + " hops= " + mHierarchyOps 1249 + " errorCallbackToken=" + mErrorCallbackToken 1250 + " taskFragmentOrganizer=" + mTaskFragmentOrganizer 1251 + " }"; 1252 } 1253 1254 @Override writeToParcel(@onNull Parcel dest, int flags)1255 public void writeToParcel(@NonNull Parcel dest, int flags) { 1256 dest.writeMap(mChanges); 1257 dest.writeTypedList(mHierarchyOps); 1258 dest.writeStrongBinder(mErrorCallbackToken); 1259 dest.writeStrongInterface(mTaskFragmentOrganizer); 1260 } 1261 1262 @Override describeContents()1263 public int describeContents() { 1264 return 0; 1265 } 1266 1267 @NonNull 1268 public static final Creator<WindowContainerTransaction> CREATOR = 1269 new Creator<>() { 1270 @Override 1271 public WindowContainerTransaction createFromParcel(@NonNull Parcel in) { 1272 return new WindowContainerTransaction(in); 1273 } 1274 1275 @Override 1276 public WindowContainerTransaction[] newArray(int size) { 1277 return new WindowContainerTransaction[size]; 1278 } 1279 }; 1280 1281 /** 1282 * Holds changes on a single WindowContainer including Configuration changes. 1283 * @hide 1284 */ 1285 public static class Change implements Parcelable { 1286 public static final int CHANGE_FOCUSABLE = 1; 1287 public static final int CHANGE_BOUNDS_TRANSACTION = 1 << 1; 1288 public static final int CHANGE_PIP_CALLBACK = 1 << 2; 1289 public static final int CHANGE_HIDDEN = 1 << 3; 1290 public static final int CHANGE_IGNORE_ORIENTATION_REQUEST = 1 << 4; 1291 public static final int CHANGE_FORCE_NO_PIP = 1 << 5; 1292 public static final int CHANGE_FORCE_TRANSLUCENT = 1 << 6; 1293 public static final int CHANGE_DRAG_RESIZING = 1 << 7; 1294 public static final int CHANGE_RELATIVE_BOUNDS = 1 << 8; 1295 1296 @IntDef(flag = true, prefix = { "CHANGE_" }, value = { 1297 CHANGE_FOCUSABLE, 1298 CHANGE_BOUNDS_TRANSACTION, 1299 CHANGE_PIP_CALLBACK, 1300 CHANGE_HIDDEN, 1301 CHANGE_IGNORE_ORIENTATION_REQUEST, 1302 CHANGE_FORCE_NO_PIP, 1303 CHANGE_FORCE_TRANSLUCENT, 1304 CHANGE_DRAG_RESIZING, 1305 CHANGE_RELATIVE_BOUNDS 1306 }) 1307 @Retention(RetentionPolicy.SOURCE) 1308 public @interface ChangeMask {} 1309 1310 private final Configuration mConfiguration = new Configuration(); 1311 private boolean mFocusable = true; 1312 private boolean mHidden = false; 1313 private boolean mIgnoreOrientationRequest = false; 1314 private boolean mForceTranslucent = false; 1315 private boolean mDragResizing = false; 1316 1317 private @ChangeMask int mChangeMask = 0; 1318 private @ActivityInfo.Config int mConfigSetMask = 0; 1319 private @WindowConfiguration.WindowConfig int mWindowSetMask = 0; 1320 1321 private Rect mPinnedBounds = null; 1322 private SurfaceControl.Transaction mBoundsChangeTransaction = null; 1323 @Nullable 1324 private Rect mRelativeBounds = null; 1325 private boolean mConfigAtTransitionEnd = false; 1326 1327 private int mActivityWindowingMode = -1; 1328 private int mWindowingMode = -1; 1329 Change()1330 private Change() {} 1331 Change(@onNull Parcel in)1332 private Change(@NonNull Parcel in) { 1333 mConfiguration.readFromParcel(in); 1334 mFocusable = in.readBoolean(); 1335 mHidden = in.readBoolean(); 1336 mIgnoreOrientationRequest = in.readBoolean(); 1337 mForceTranslucent = in.readBoolean(); 1338 mDragResizing = in.readBoolean(); 1339 mChangeMask = in.readInt(); 1340 mConfigSetMask = in.readInt(); 1341 mWindowSetMask = in.readInt(); 1342 if ((mChangeMask & Change.CHANGE_PIP_CALLBACK) != 0) { 1343 mPinnedBounds = new Rect(); 1344 mPinnedBounds.readFromParcel(in); 1345 } 1346 if ((mChangeMask & Change.CHANGE_BOUNDS_TRANSACTION) != 0) { 1347 mBoundsChangeTransaction = 1348 SurfaceControl.Transaction.CREATOR.createFromParcel(in); 1349 } 1350 if ((mChangeMask & Change.CHANGE_RELATIVE_BOUNDS) != 0) { 1351 mRelativeBounds = new Rect(); 1352 mRelativeBounds.readFromParcel(in); 1353 } 1354 mConfigAtTransitionEnd = in.readBoolean(); 1355 1356 mWindowingMode = in.readInt(); 1357 mActivityWindowingMode = in.readInt(); 1358 } 1359 1360 /** 1361 * @param transfer When true, this will transfer other into this leaving other in an 1362 * undefined state. Use this if you don't intend to use other. When false, 1363 * SurfaceFlinger Transactions will not merge. 1364 */ merge(@onNull Change other, boolean transfer)1365 public void merge(@NonNull Change other, boolean transfer) { 1366 mConfiguration.setTo(other.mConfiguration, other.mConfigSetMask, other.mWindowSetMask); 1367 mConfigSetMask |= other.mConfigSetMask; 1368 mWindowSetMask |= other.mWindowSetMask; 1369 if ((other.mChangeMask & CHANGE_FOCUSABLE) != 0) { 1370 mFocusable = other.mFocusable; 1371 } 1372 if (transfer && (other.mChangeMask & CHANGE_BOUNDS_TRANSACTION) != 0) { 1373 mBoundsChangeTransaction = other.mBoundsChangeTransaction; 1374 other.mBoundsChangeTransaction = null; 1375 } 1376 if ((other.mChangeMask & CHANGE_PIP_CALLBACK) != 0) { 1377 mPinnedBounds = transfer ? other.mPinnedBounds : new Rect(other.mPinnedBounds); 1378 } 1379 if ((other.mChangeMask & CHANGE_HIDDEN) != 0) { 1380 mHidden = other.mHidden; 1381 } 1382 if ((other.mChangeMask & CHANGE_IGNORE_ORIENTATION_REQUEST) != 0) { 1383 mIgnoreOrientationRequest = other.mIgnoreOrientationRequest; 1384 } 1385 if ((other.mChangeMask & CHANGE_FORCE_TRANSLUCENT) != 0) { 1386 mForceTranslucent = other.mForceTranslucent; 1387 } 1388 if ((other.mChangeMask & CHANGE_DRAG_RESIZING) != 0) { 1389 mDragResizing = other.mDragResizing; 1390 } 1391 mChangeMask |= other.mChangeMask; 1392 if (other.mActivityWindowingMode >= WINDOWING_MODE_UNDEFINED) { 1393 mActivityWindowingMode = other.mActivityWindowingMode; 1394 } 1395 if (other.mWindowingMode >= WINDOWING_MODE_UNDEFINED) { 1396 mWindowingMode = other.mWindowingMode; 1397 } 1398 if (other.mRelativeBounds != null) { 1399 mRelativeBounds = transfer 1400 ? other.mRelativeBounds 1401 : new Rect(other.mRelativeBounds); 1402 } 1403 mConfigAtTransitionEnd = mConfigAtTransitionEnd 1404 || other.mConfigAtTransitionEnd; 1405 } 1406 getWindowingMode()1407 public int getWindowingMode() { 1408 return mWindowingMode; 1409 } 1410 getActivityWindowingMode()1411 public int getActivityWindowingMode() { 1412 return mActivityWindowingMode; 1413 } 1414 1415 @NonNull getConfiguration()1416 public Configuration getConfiguration() { 1417 return mConfiguration; 1418 } 1419 1420 /** Gets the requested focusable state */ getFocusable()1421 public boolean getFocusable() { 1422 if ((mChangeMask & CHANGE_FOCUSABLE) == 0) { 1423 throw new RuntimeException("Focusable not set. check CHANGE_FOCUSABLE first"); 1424 } 1425 return mFocusable; 1426 } 1427 1428 /** Gets the requested hidden state */ getHidden()1429 public boolean getHidden() { 1430 if ((mChangeMask & CHANGE_HIDDEN) == 0) { 1431 throw new RuntimeException("Hidden not set. check CHANGE_HIDDEN first"); 1432 } 1433 return mHidden; 1434 } 1435 1436 /** Gets the requested state of whether to ignore orientation request. */ getIgnoreOrientationRequest()1437 public boolean getIgnoreOrientationRequest() { 1438 if ((mChangeMask & CHANGE_IGNORE_ORIENTATION_REQUEST) == 0) { 1439 throw new RuntimeException("IgnoreOrientationRequest not set. " 1440 + "Check CHANGE_IGNORE_ORIENTATION_REQUEST first"); 1441 } 1442 return mIgnoreOrientationRequest; 1443 } 1444 1445 /** Gets the requested force translucent state. */ getForceTranslucent()1446 public boolean getForceTranslucent() { 1447 if ((mChangeMask & CHANGE_FORCE_TRANSLUCENT) == 0) { 1448 throw new RuntimeException("Force translucent not set. " 1449 + "Check CHANGE_FORCE_TRANSLUCENT first"); 1450 } 1451 return mForceTranslucent; 1452 } 1453 1454 /** Gets the requested drag resizing state. */ getDragResizing()1455 public boolean getDragResizing() { 1456 if ((mChangeMask & CHANGE_DRAG_RESIZING) == 0) { 1457 throw new RuntimeException("Drag resizing not set. " 1458 + "Check CHANGE_DRAG_RESIZING first"); 1459 } 1460 return mDragResizing; 1461 } 1462 1463 /** Gets whether the config should be sent to the client at the end of the transition. */ getConfigAtTransitionEnd()1464 public boolean getConfigAtTransitionEnd() { 1465 return mConfigAtTransitionEnd; 1466 } 1467 1468 @ChangeMask getChangeMask()1469 public int getChangeMask() { 1470 return mChangeMask; 1471 } 1472 1473 @ActivityInfo.Config getConfigSetMask()1474 public int getConfigSetMask() { 1475 return mConfigSetMask; 1476 } 1477 1478 @WindowConfiguration.WindowConfig getWindowSetMask()1479 public int getWindowSetMask() { 1480 return mWindowSetMask; 1481 } 1482 1483 /** 1484 * Returns the bounds to be used for scheduling the enter pip callback 1485 * or null if no callback is to be scheduled. 1486 */ 1487 @Nullable getEnterPipBounds()1488 public Rect getEnterPipBounds() { 1489 return mPinnedBounds; 1490 } 1491 1492 @Nullable getBoundsChangeTransaction()1493 public SurfaceControl.Transaction getBoundsChangeTransaction() { 1494 return mBoundsChangeTransaction; 1495 } 1496 1497 @Nullable getRelativeBounds()1498 public Rect getRelativeBounds() { 1499 return mRelativeBounds; 1500 } 1501 1502 @Override toString()1503 public String toString() { 1504 final boolean changesBounds = 1505 (mConfigSetMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0 1506 && ((mWindowSetMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS) 1507 != 0); 1508 final boolean changesAppBounds = 1509 (mConfigSetMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0 1510 && ((mWindowSetMask & WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS) 1511 != 0); 1512 final boolean changesSs = (mConfigSetMask & ActivityInfo.CONFIG_SCREEN_SIZE) != 0; 1513 final boolean changesSss = 1514 (mConfigSetMask & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0; 1515 StringBuilder sb = new StringBuilder(); 1516 sb.append('{'); 1517 if (changesBounds) { 1518 sb.append("bounds:" + mConfiguration.windowConfiguration.getBounds() + ","); 1519 } 1520 if (changesAppBounds) { 1521 sb.append("appbounds:" + mConfiguration.windowConfiguration.getAppBounds() + ","); 1522 } 1523 if (changesSss) { 1524 sb.append("ssw:" + mConfiguration.smallestScreenWidthDp + ","); 1525 } 1526 if (changesSs) { 1527 sb.append("sw/h:" + mConfiguration.screenWidthDp + "x" 1528 + mConfiguration.screenHeightDp + ","); 1529 } 1530 if ((mChangeMask & CHANGE_FOCUSABLE) != 0) { 1531 sb.append("focusable:" + mFocusable + ","); 1532 } 1533 if ((mChangeMask & CHANGE_FORCE_TRANSLUCENT) != 0) { 1534 sb.append("forceTranslucent:" + mForceTranslucent + ","); 1535 } 1536 if ((mChangeMask & CHANGE_HIDDEN) != 0) { 1537 sb.append("hidden:" + mHidden + ","); 1538 } 1539 if ((mChangeMask & CHANGE_DRAG_RESIZING) != 0) { 1540 sb.append("dragResizing:" + mDragResizing + ","); 1541 } 1542 if (mBoundsChangeTransaction != null) { 1543 sb.append("hasBoundsTransaction,"); 1544 } 1545 if ((mChangeMask & CHANGE_IGNORE_ORIENTATION_REQUEST) != 0) { 1546 sb.append("ignoreOrientationRequest:" + mIgnoreOrientationRequest + ","); 1547 } 1548 if ((mChangeMask & CHANGE_RELATIVE_BOUNDS) != 0) { 1549 sb.append("relativeBounds:").append(mRelativeBounds).append(","); 1550 } 1551 if (mConfigAtTransitionEnd) { 1552 sb.append("configAtTransitionEnd").append(","); 1553 } 1554 sb.append("}"); 1555 return sb.toString(); 1556 } 1557 1558 @Override writeToParcel(@onNull Parcel dest, int flags)1559 public void writeToParcel(@NonNull Parcel dest, int flags) { 1560 mConfiguration.writeToParcel(dest, flags); 1561 dest.writeBoolean(mFocusable); 1562 dest.writeBoolean(mHidden); 1563 dest.writeBoolean(mIgnoreOrientationRequest); 1564 dest.writeBoolean(mForceTranslucent); 1565 dest.writeBoolean(mDragResizing); 1566 dest.writeInt(mChangeMask); 1567 dest.writeInt(mConfigSetMask); 1568 dest.writeInt(mWindowSetMask); 1569 1570 if (mPinnedBounds != null) { 1571 mPinnedBounds.writeToParcel(dest, flags); 1572 } 1573 if (mBoundsChangeTransaction != null) { 1574 mBoundsChangeTransaction.writeToParcel(dest, flags); 1575 } 1576 if (mRelativeBounds != null) { 1577 mRelativeBounds.writeToParcel(dest, flags); 1578 } 1579 dest.writeBoolean(mConfigAtTransitionEnd); 1580 1581 dest.writeInt(mWindowingMode); 1582 dest.writeInt(mActivityWindowingMode); 1583 } 1584 1585 @Override describeContents()1586 public int describeContents() { 1587 return 0; 1588 } 1589 1590 public static final Creator<Change> CREATOR = new Creator<Change>() { 1591 @Override 1592 public Change createFromParcel(@NonNull Parcel in) { 1593 return new Change(in); 1594 } 1595 1596 @Override 1597 public Change[] newArray(int size) { 1598 return new Change[size]; 1599 } 1600 }; 1601 } 1602 1603 /** 1604 * Holds information about a reparent/reorder operation in the hierarchy. This is separate from 1605 * Changes because they must be executed in the same order that they are added. 1606 * @see com.android.server.wm.WindowOrganizerController#applyHierarchyOp 1607 * @hide 1608 */ 1609 public static final class HierarchyOp implements Parcelable { 1610 public static final int HIERARCHY_OP_TYPE_REPARENT = 0; 1611 public static final int HIERARCHY_OP_TYPE_REORDER = 1; 1612 public static final int HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT = 2; 1613 public static final int HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT = 3; 1614 public static final int HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS = 4; 1615 public static final int HIERARCHY_OP_TYPE_LAUNCH_TASK = 5; 1616 public static final int HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT = 6; 1617 public static final int HIERARCHY_OP_TYPE_PENDING_INTENT = 7; 1618 public static final int HIERARCHY_OP_TYPE_START_SHORTCUT = 8; 1619 public static final int HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER = 9; 1620 public static final int HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER = 10; 1621 public static final int HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER = 11; 1622 public static final int HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP = 12; 1623 public static final int HIERARCHY_OP_TYPE_REMOVE_TASK = 13; 1624 public static final int HIERARCHY_OP_TYPE_FINISH_ACTIVITY = 14; 1625 public static final int HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS = 15; 1626 public static final int HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH = 16; 1627 public static final int HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION = 17; 1628 public static final int HIERARCHY_OP_TYPE_MOVE_PIP_ACTIVITY_TO_PINNED_TASK = 18; 1629 public static final int HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE = 19; 1630 public static final int HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION = 20; 1631 public static final int HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES = 21; 1632 public static final int HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE = 22; 1633 public static final int HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT = 23; 1634 public static final int HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK = 24; 1635 public static final int HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY = 25; 1636 public static final int HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS = 26; 1637 1638 @IntDef(prefix = {"HIERARCHY_OP_TYPE_"}, value = { 1639 HIERARCHY_OP_TYPE_REPARENT, 1640 HIERARCHY_OP_TYPE_REORDER, 1641 HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT, 1642 HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT, 1643 HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS, 1644 HIERARCHY_OP_TYPE_LAUNCH_TASK, 1645 HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT, 1646 HIERARCHY_OP_TYPE_PENDING_INTENT, 1647 HIERARCHY_OP_TYPE_START_SHORTCUT, 1648 HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER, 1649 HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER, 1650 HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER, 1651 HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP, 1652 HIERARCHY_OP_TYPE_REMOVE_TASK, 1653 HIERARCHY_OP_TYPE_FINISH_ACTIVITY, 1654 HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS, 1655 HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH, 1656 HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION, 1657 HIERARCHY_OP_TYPE_MOVE_PIP_ACTIVITY_TO_PINNED_TASK, 1658 HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE, 1659 HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION, 1660 HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES, 1661 HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE, 1662 HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT, 1663 HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK, 1664 HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY, 1665 HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS, 1666 }) 1667 @Retention(RetentionPolicy.SOURCE) 1668 public @interface HierarchyOpType { 1669 } 1670 1671 // The following key(s) are for use with mLaunchOptions: 1672 // When launching a task (eg. from recents), this is the taskId to be launched. 1673 public static final String LAUNCH_KEY_TASK_ID = "android:transaction.hop.taskId"; 1674 1675 // When starting from a shortcut, this contains the calling package. 1676 public static final String LAUNCH_KEY_SHORTCUT_CALLING_PACKAGE = 1677 "android:transaction.hop.shortcut_calling_package"; 1678 1679 // The following keys are used to define the reachability direction after a double tap. 1680 public static final String REACHABILITY_EVENT_X = "android:transaction.reachability_x"; 1681 public static final String REACHABILITY_EVENT_Y = "android:transaction.reachability_y"; 1682 1683 @HierarchyOpType 1684 private final int mType; 1685 1686 // Container we are performing the operation on. 1687 @Nullable 1688 private IBinder mContainer; 1689 1690 @Nullable 1691 private IBinder[] mContainers; 1692 1693 // If this is same as mContainer, then only change position, don't reparent. 1694 @Nullable 1695 private IBinder mReparent; 1696 1697 @Nullable 1698 private InsetsFrameProvider mInsetsFrameProvider; 1699 1700 @Nullable 1701 private IBinder mInsetsFrameOwner; 1702 1703 // Moves/reparents to top of parent when {@code true}, otherwise moves/reparents to bottom. 1704 private boolean mToTop; 1705 1706 private boolean mReparentTopOnly; 1707 1708 @Nullable 1709 private int[] mWindowingModes; 1710 1711 @Nullable 1712 private int[] mActivityTypes; 1713 1714 @Nullable 1715 private Bundle mLaunchOptions; 1716 1717 @Nullable 1718 private Bundle mAppCompatOptions; 1719 1720 @Nullable 1721 private Intent mActivityIntent; 1722 1723 /** Used as options for {@link #addTaskFragmentOperation}. */ 1724 @Nullable 1725 private TaskFragmentOperation mTaskFragmentOperation; 1726 1727 @Nullable 1728 private KeyguardState mKeyguardState; 1729 1730 @Nullable 1731 private PendingIntent mPendingIntent; 1732 1733 @Nullable 1734 private ShortcutInfo mShortcutInfo; 1735 1736 @Nullable 1737 private Rect mBounds; 1738 1739 private boolean mIncludingParents; 1740 1741 private boolean mAlwaysOnTop; 1742 1743 private boolean mReparentLeafTaskIfRelaunch; 1744 1745 private boolean mIsTrimmableFromRecents; 1746 1747 private @InsetsType int mExcludeInsetsTypes; 1748 1749 private boolean mLaunchAdjacentDisabled; 1750 1751 @Nullable 1752 private Rect mSafeRegionBounds; 1753 1754 /** Creates a hierarchy operation for reparenting a container within the hierarchy. */ 1755 @NonNull createForReparent( @onNull IBinder container, @Nullable IBinder reparent, boolean toTop)1756 public static HierarchyOp createForReparent( 1757 @NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) { 1758 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT) 1759 .setContainer(container) 1760 .setReparentContainer(reparent) 1761 .setToTop(toTop) 1762 .build(); 1763 } 1764 1765 /** 1766 * Creates a a hierarchy op for the reorder operation. 1767 * 1768 * @param container which needs to be reordered 1769 * @param toTop if true, the container reorders 1770 * @param includingParents if true, all the parents in the hierarchy above are also 1771 * reoredered among their respective siblings 1772 * @return 1773 */ 1774 @NonNull createForReorder(@onNull IBinder container, boolean toTop, boolean includingParents)1775 public static HierarchyOp createForReorder(@NonNull IBinder container, boolean toTop, 1776 boolean includingParents) { 1777 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REORDER) 1778 .setContainer(container) 1779 .setReparentContainer(container) 1780 .setToTop(toTop) 1781 .setIncludingParents(includingParents) 1782 .build(); 1783 } 1784 1785 /** Creates a hierarchy op for reparenting child tasks from one container to another. */ 1786 @NonNull createForChildrenTasksReparent(@ullable IBinder currentParent, @Nullable IBinder newParent, @Nullable int[] windowingModes, @Nullable int[] activityTypes, boolean onTop, boolean reparentTopOnly)1787 public static HierarchyOp createForChildrenTasksReparent(@Nullable IBinder currentParent, 1788 @Nullable IBinder newParent, @Nullable int[] windowingModes, 1789 @Nullable int[] activityTypes, boolean onTop, boolean reparentTopOnly) { 1790 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT) 1791 .setContainer(currentParent) 1792 .setReparentContainer(newParent) 1793 .setWindowingModes(windowingModes) 1794 .setActivityTypes(activityTypes) 1795 .setToTop(onTop) 1796 .setReparentTopOnly(reparentTopOnly) 1797 .build(); 1798 } 1799 1800 /** Creates a hierarchy op for setting the launch root for tasks. */ 1801 @NonNull createForSetLaunchRoot(@ullable IBinder container, @Nullable int[] windowingModes, @Nullable int[] activityTypes)1802 public static HierarchyOp createForSetLaunchRoot(@Nullable IBinder container, 1803 @Nullable int[] windowingModes, @Nullable int[] activityTypes) { 1804 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT) 1805 .setContainer(container) 1806 .setWindowingModes(windowingModes) 1807 .setActivityTypes(activityTypes) 1808 .build(); 1809 } 1810 1811 /** Creates a hierarchy op for setting adjacent root tasks. */ 1812 @NonNull createForAdjacentRoots( @ullable IBinder root1, @Nullable IBinder root2)1813 public static HierarchyOp createForAdjacentRoots( 1814 @Nullable IBinder root1, @Nullable IBinder root2) { 1815 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS) 1816 .setContainer(root1) 1817 .setReparentContainer(root2) 1818 .build(); 1819 } 1820 1821 /** Creates a hierarchy op for launching a task. */ 1822 @NonNull createForTaskLaunch(int taskId, @Nullable Bundle options)1823 public static HierarchyOp createForTaskLaunch(int taskId, @Nullable Bundle options) { 1824 final Bundle fullOptions = options == null ? new Bundle() : options; 1825 fullOptions.putInt(LAUNCH_KEY_TASK_ID, taskId); 1826 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_LAUNCH_TASK) 1827 .setToTop(true) 1828 .setLaunchOptions(fullOptions) 1829 .build(); 1830 } 1831 1832 /** Creates a hierarchy op for starting a shortcut. */ 1833 @NonNull createForStartShortcut(@onNull String callingPackage, @NonNull ShortcutInfo shortcutInfo, @Nullable Bundle options)1834 public static HierarchyOp createForStartShortcut(@NonNull String callingPackage, 1835 @NonNull ShortcutInfo shortcutInfo, @Nullable Bundle options) { 1836 final Bundle fullOptions = options == null ? new Bundle() : options; 1837 fullOptions.putString(LAUNCH_KEY_SHORTCUT_CALLING_PACKAGE, callingPackage); 1838 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_START_SHORTCUT) 1839 .setShortcutInfo(shortcutInfo) 1840 .setLaunchOptions(fullOptions) 1841 .build(); 1842 } 1843 1844 /** Creates a hierarchy op for setting launch adjacent flag root. */ 1845 @NonNull createForSetLaunchAdjacentFlagRoot(@ullable IBinder container, boolean clearRoot)1846 public static HierarchyOp createForSetLaunchAdjacentFlagRoot(@Nullable IBinder container, 1847 boolean clearRoot) { 1848 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT) 1849 .setContainer(container) 1850 .setToTop(clearRoot) 1851 .build(); 1852 } 1853 1854 /** Creates a hierarchy op for disabling launch adjacent. */ 1855 @NonNull createForSetDisableLaunchAdjacent(@ullable IBinder container, boolean disabled)1856 public static HierarchyOp createForSetDisableLaunchAdjacent(@Nullable IBinder container, 1857 boolean disabled) { 1858 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT) 1859 .setContainer(container) 1860 .setLaunchAdjacentDisabled(disabled) 1861 .build(); 1862 } 1863 1864 /** Creates a hierarchy op for deleting a task **/ 1865 @NonNull createForRemoveTask(@onNull IBinder container)1866 public static HierarchyOp createForRemoveTask(@NonNull IBinder container) { 1867 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REMOVE_TASK) 1868 .setContainer(container) 1869 .build(); 1870 } 1871 1872 /** 1873 * Creates a hierarchy op for deleting a root task 1874 * 1875 * @hide 1876 **/ 1877 @NonNull createForRemoveRootTask(@onNull IBinder container)1878 public static HierarchyOp createForRemoveRootTask(@NonNull IBinder container) { 1879 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK) 1880 .setContainer(container) 1881 .build(); 1882 } 1883 1884 /** Creates a hierarchy op for clearing adjacent root tasks. */ 1885 @NonNull createForClearAdjacentRoots(@onNull IBinder root)1886 public static HierarchyOp createForClearAdjacentRoots(@NonNull IBinder root) { 1887 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS) 1888 .setContainer(root) 1889 .build(); 1890 } 1891 1892 /** Create a hierarchy op for app compat reachability. */ 1893 @NonNull createForReachability(IBinder container, int taskId, int x, int y)1894 public static HierarchyOp createForReachability(IBinder container, int taskId, int x, 1895 int y) { 1896 final Bundle appCompatOptions = new Bundle(); 1897 appCompatOptions.putInt(LAUNCH_KEY_TASK_ID, taskId); 1898 appCompatOptions.putInt(REACHABILITY_EVENT_X, x); 1899 appCompatOptions.putInt(REACHABILITY_EVENT_Y, y); 1900 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY) 1901 .setAppCompatOptions(appCompatOptions) 1902 .setContainer(container) 1903 .build(); 1904 } 1905 1906 /** Create a hierarchy op for setting a task non-trimmable by recents. */ 1907 @NonNull 1908 @FlaggedApi(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) createForSetTaskTrimmableFromRecents(@onNull IBinder container, boolean isTrimmableFromRecents)1909 public static HierarchyOp createForSetTaskTrimmableFromRecents(@NonNull IBinder container, 1910 boolean isTrimmableFromRecents) { 1911 return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE) 1912 .setContainer(container) 1913 .setIsTrimmableFromRecents(isTrimmableFromRecents) 1914 .build(); 1915 } 1916 1917 /** Creates a hierarchy op for setting the safe region bounds. */ 1918 @NonNull 1919 @FlaggedApi(Flags.FLAG_SAFE_REGION_LETTERBOXING) createForSetSafeRegionBounds(@onNull IBinder container, @Nullable Rect safeRegionBounds)1920 public static HierarchyOp createForSetSafeRegionBounds(@NonNull IBinder container, 1921 @Nullable Rect safeRegionBounds) { 1922 return new Builder(HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS) 1923 .setContainer(container) 1924 .setSafeRegionBounds(safeRegionBounds) 1925 .build(); 1926 } 1927 1928 /** Only creates through {@link Builder}. */ HierarchyOp(@ierarchyOpType int type)1929 private HierarchyOp(@HierarchyOpType int type) { 1930 mType = type; 1931 } 1932 HierarchyOp(@onNull HierarchyOp copy)1933 public HierarchyOp(@NonNull HierarchyOp copy) { 1934 mType = copy.mType; 1935 mContainer = copy.mContainer; 1936 mContainers = copy.mContainers; 1937 mBounds = copy.mBounds; 1938 mIncludingParents = copy.mIncludingParents; 1939 mReparent = copy.mReparent; 1940 mInsetsFrameProvider = copy.mInsetsFrameProvider; 1941 mInsetsFrameOwner = copy.mInsetsFrameOwner; 1942 mToTop = copy.mToTop; 1943 mReparentTopOnly = copy.mReparentTopOnly; 1944 mWindowingModes = copy.mWindowingModes; 1945 mActivityTypes = copy.mActivityTypes; 1946 mLaunchOptions = copy.mLaunchOptions; 1947 mAppCompatOptions = copy.mAppCompatOptions; 1948 mActivityIntent = copy.mActivityIntent; 1949 mTaskFragmentOperation = copy.mTaskFragmentOperation; 1950 mKeyguardState = copy.mKeyguardState; 1951 mPendingIntent = copy.mPendingIntent; 1952 mShortcutInfo = copy.mShortcutInfo; 1953 mAlwaysOnTop = copy.mAlwaysOnTop; 1954 mReparentLeafTaskIfRelaunch = copy.mReparentLeafTaskIfRelaunch; 1955 mIsTrimmableFromRecents = copy.mIsTrimmableFromRecents; 1956 mExcludeInsetsTypes = copy.mExcludeInsetsTypes; 1957 mLaunchAdjacentDisabled = copy.mLaunchAdjacentDisabled; 1958 mSafeRegionBounds = copy.mSafeRegionBounds; 1959 } 1960 HierarchyOp(@onNull Parcel in)1961 private HierarchyOp(@NonNull Parcel in) { 1962 mType = in.readInt(); 1963 mContainer = in.readStrongBinder(); 1964 mContainers = in.createBinderArray(); 1965 mBounds = in.readTypedObject(Rect.CREATOR); 1966 mIncludingParents = in.readBoolean(); 1967 mReparent = in.readStrongBinder(); 1968 mInsetsFrameProvider = in.readTypedObject(InsetsFrameProvider.CREATOR); 1969 mInsetsFrameOwner = in.readStrongBinder(); 1970 mToTop = in.readBoolean(); 1971 mReparentTopOnly = in.readBoolean(); 1972 mWindowingModes = in.createIntArray(); 1973 mActivityTypes = in.createIntArray(); 1974 mLaunchOptions = in.readBundle(); 1975 mAppCompatOptions = in.readBundle(getClass().getClassLoader()); 1976 mActivityIntent = in.readTypedObject(Intent.CREATOR); 1977 mTaskFragmentOperation = in.readTypedObject(TaskFragmentOperation.CREATOR); 1978 mKeyguardState = in.readTypedObject(KeyguardState.CREATOR); 1979 mPendingIntent = in.readTypedObject(PendingIntent.CREATOR); 1980 mShortcutInfo = in.readTypedObject(ShortcutInfo.CREATOR); 1981 mAlwaysOnTop = in.readBoolean(); 1982 mReparentLeafTaskIfRelaunch = in.readBoolean(); 1983 mIsTrimmableFromRecents = in.readBoolean(); 1984 mExcludeInsetsTypes = in.readInt(); 1985 mLaunchAdjacentDisabled = in.readBoolean(); 1986 mSafeRegionBounds = in.readTypedObject(Rect.CREATOR); 1987 } 1988 1989 @HierarchyOpType getType()1990 public int getType() { 1991 return mType; 1992 } 1993 isReparent()1994 public boolean isReparent() { 1995 return mType == HIERARCHY_OP_TYPE_REPARENT; 1996 } 1997 1998 @Nullable getNewParent()1999 public IBinder getNewParent() { 2000 return mReparent; 2001 } 2002 2003 @Nullable getInsetsFrameProvider()2004 public InsetsFrameProvider getInsetsFrameProvider() { 2005 return mInsetsFrameProvider; 2006 } 2007 2008 @Nullable getInsetsFrameOwner()2009 public IBinder getInsetsFrameOwner() { 2010 return mInsetsFrameOwner; 2011 } 2012 2013 @NonNull getContainer()2014 public IBinder getContainer() { 2015 return mContainer; 2016 } 2017 2018 @NonNull getContainers()2019 public IBinder[] getContainers() { 2020 return mContainers; 2021 } 2022 getToTop()2023 public boolean getToTop() { 2024 return mToTop; 2025 } 2026 getReparentTopOnly()2027 public boolean getReparentTopOnly() { 2028 return mReparentTopOnly; 2029 } 2030 2031 @Nullable getWindowingModes()2032 public int[] getWindowingModes() { 2033 return mWindowingModes; 2034 } 2035 2036 @Nullable getActivityTypes()2037 public int[] getActivityTypes() { 2038 return mActivityTypes; 2039 } 2040 2041 @Nullable getLaunchOptions()2042 public Bundle getLaunchOptions() { 2043 return mLaunchOptions; 2044 } 2045 2046 @Nullable getAppCompatOptions()2047 public Bundle getAppCompatOptions() { 2048 return mAppCompatOptions; 2049 } 2050 2051 @Nullable getActivityIntent()2052 public Intent getActivityIntent() { 2053 return mActivityIntent; 2054 } 2055 isAlwaysOnTop()2056 public boolean isAlwaysOnTop() { 2057 return mAlwaysOnTop; 2058 } 2059 isReparentLeafTaskIfRelaunch()2060 public boolean isReparentLeafTaskIfRelaunch() { 2061 return mReparentLeafTaskIfRelaunch; 2062 } 2063 2064 @Nullable getTaskFragmentOperation()2065 public TaskFragmentOperation getTaskFragmentOperation() { 2066 return mTaskFragmentOperation; 2067 } 2068 2069 @Nullable getKeyguardState()2070 public KeyguardState getKeyguardState() { 2071 return mKeyguardState; 2072 } 2073 2074 @Nullable getPendingIntent()2075 public PendingIntent getPendingIntent() { 2076 return mPendingIntent; 2077 } 2078 2079 @Nullable getShortcutInfo()2080 public ShortcutInfo getShortcutInfo() { 2081 return mShortcutInfo; 2082 } 2083 2084 @NonNull getBounds()2085 public Rect getBounds() { 2086 return mBounds; 2087 } 2088 2089 /** Denotes whether the parents should also be included in the op. */ includingParents()2090 public boolean includingParents() { 2091 return mIncludingParents; 2092 } 2093 2094 /** Denotes whether the task can be trimmable from recents */ isTrimmableFromRecents()2095 public boolean isTrimmableFromRecents() { 2096 return mIsTrimmableFromRecents; 2097 } 2098 getExcludeInsetsTypes()2099 public @InsetsType int getExcludeInsetsTypes() { 2100 return mExcludeInsetsTypes; 2101 } 2102 2103 /** Denotes whether launch-adjacent flag is respected from this task or its children */ isLaunchAdjacentDisabled()2104 public boolean isLaunchAdjacentDisabled() { 2105 return mLaunchAdjacentDisabled; 2106 } 2107 2108 /** Denotes the safe region bounds */ 2109 @Nullable getSafeRegionBounds()2110 public Rect getSafeRegionBounds() { 2111 return mSafeRegionBounds; 2112 } 2113 2114 /** Gets a string representation of a hierarchy-op type. */ hopToString(@ierarchyOpType int type)2115 public static String hopToString(@HierarchyOpType int type) { 2116 switch (type) { 2117 case HIERARCHY_OP_TYPE_REPARENT: return "reparent"; 2118 case HIERARCHY_OP_TYPE_REORDER: return "reorder"; 2119 case HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT: return "childrenTasksReparent"; 2120 case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: return "setLaunchRoot"; 2121 case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS: return "setAdjacentRoots"; 2122 case HIERARCHY_OP_TYPE_LAUNCH_TASK: return "launchTask"; 2123 case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT: return "setAdjacentFlagRoot"; 2124 case HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT: 2125 return "setDisableLaunchAdjacent"; 2126 case HIERARCHY_OP_TYPE_PENDING_INTENT: return "pendingIntent"; 2127 case HIERARCHY_OP_TYPE_START_SHORTCUT: return "startShortcut"; 2128 case HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER: return "restoreTransientOrder"; 2129 case HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER: return "addInsetsFrameProvider"; 2130 case HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER: 2131 return "removeInsetsFrameProvider"; 2132 case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: return "setAlwaysOnTop"; 2133 case HIERARCHY_OP_TYPE_REMOVE_TASK: return "removeTask"; 2134 case HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK: return "removeRootTask"; 2135 case HIERARCHY_OP_TYPE_FINISH_ACTIVITY: return "finishActivity"; 2136 case HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS: return "clearAdjacentRoots"; 2137 case HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH: 2138 return "setReparentLeafTaskIfRelaunch"; 2139 case HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION: 2140 return "addTaskFragmentOperation"; 2141 case HIERARCHY_OP_TYPE_MOVE_PIP_ACTIVITY_TO_PINNED_TASK: 2142 return "movePipActivityToPinnedTask"; 2143 case HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE: return "setIsTrimmable"; 2144 case HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION: return "restoreBackNav"; 2145 case HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES: return "setExcludeInsetsTypes"; 2146 case HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE: return "setKeyguardState"; 2147 case HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS: return "setSafeRegionBounds"; 2148 default: return "HOP(" + type + ")"; 2149 } 2150 } 2151 2152 @Override toString()2153 public String toString() { 2154 StringBuilder sb = new StringBuilder(); 2155 sb.append("{").append(hopToString(mType)).append(": "); 2156 switch (mType) { 2157 case HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT: 2158 sb.append("from=").append(mContainer).append(" to=").append(mReparent) 2159 .append(" mToTop=").append(mToTop) 2160 .append(" mReparentTopOnly=").append(mReparentTopOnly) 2161 .append(" mWindowingMode=").append(Arrays.toString(mWindowingModes)) 2162 .append(" mActivityType=").append(Arrays.toString(mActivityTypes)); 2163 break; 2164 case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: 2165 sb.append("container=").append(mContainer) 2166 .append(" mWindowingMode=").append(Arrays.toString(mWindowingModes)) 2167 .append(" mActivityType=").append(Arrays.toString(mActivityTypes)); 2168 break; 2169 case HIERARCHY_OP_TYPE_REPARENT: 2170 sb.append(mContainer).append(" to ").append(mToTop ? "top of " : "bottom of ") 2171 .append(mReparent); 2172 break; 2173 case HIERARCHY_OP_TYPE_REORDER: 2174 sb.append(mContainer).append(" to ").append(mToTop ? "top" : "bottom"); 2175 break; 2176 case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS: 2177 for (IBinder container : mContainers) { 2178 if (container == mContainers[0]) { 2179 sb.append("adjacentRoots=").append(container); 2180 } else { 2181 sb.append(", ").append(container); 2182 } 2183 } 2184 break; 2185 case HIERARCHY_OP_TYPE_LAUNCH_TASK: 2186 sb.append(mLaunchOptions); 2187 break; 2188 case HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY: 2189 sb.append(mAppCompatOptions); 2190 break; 2191 case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT: 2192 sb.append("container=").append(mContainer).append(" clearRoot=").append(mToTop); 2193 break; 2194 case HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT: 2195 sb.append("container=").append(mContainer).append(" disabled=") 2196 .append(mLaunchAdjacentDisabled); 2197 break; 2198 case HIERARCHY_OP_TYPE_START_SHORTCUT: 2199 sb.append("options=").append(mLaunchOptions) 2200 .append(" info=").append(mShortcutInfo); 2201 break; 2202 case HIERARCHY_OP_TYPE_PENDING_INTENT: 2203 sb.append("options=").append(mLaunchOptions); 2204 break; 2205 case HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER: 2206 case HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER: 2207 sb.append("container=").append(mContainer) 2208 .append(" provider=").append(mInsetsFrameProvider) 2209 .append(" owner=").append(mInsetsFrameOwner); 2210 break; 2211 case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: 2212 sb.append("container=").append(mContainer) 2213 .append(" alwaysOnTop=").append(mAlwaysOnTop); 2214 break; 2215 case HIERARCHY_OP_TYPE_REMOVE_TASK: 2216 sb.append("task=").append(mContainer); 2217 break; 2218 case HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK: 2219 sb.append("rootTask=").append(mContainer); 2220 break; 2221 case HIERARCHY_OP_TYPE_FINISH_ACTIVITY: 2222 sb.append("activity=").append(mContainer); 2223 break; 2224 case HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS: 2225 sb.append("container=").append(mContainer); 2226 break; 2227 case HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH: 2228 sb.append("container= ").append(mContainer) 2229 .append(" reparentLeafTaskIfRelaunch= ") 2230 .append(mReparentLeafTaskIfRelaunch); 2231 break; 2232 case HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION: 2233 sb.append("fragmentToken= ").append(mContainer) 2234 .append(" operation= ").append(mTaskFragmentOperation); 2235 break; 2236 case HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES: 2237 sb.append("container= ").append(mContainer) 2238 .append(" mExcludeInsetsTypes= ") 2239 .append(WindowInsets.Type.toString(mExcludeInsetsTypes)); 2240 break; 2241 case HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE: 2242 sb.append("KeyguardState= ").append(mKeyguardState); 2243 break; 2244 case HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE: 2245 sb.append("container= ").append(mContainer) 2246 .append(" isTrimmable= ") 2247 .append(mIsTrimmableFromRecents); 2248 break; 2249 case HIERARCHY_OP_TYPE_SET_SAFE_REGION_BOUNDS: 2250 sb.append("container= ").append(mContainer) 2251 .append(" safeRegionBounds= ") 2252 .append(mSafeRegionBounds); 2253 default: 2254 sb.append("container=").append(mContainer) 2255 .append(" reparent=").append(mReparent) 2256 .append(" mToTop=").append(mToTop) 2257 .append(" mWindowingMode=").append(Arrays.toString(mWindowingModes)) 2258 .append(" mActivityType=").append(Arrays.toString(mActivityTypes)); 2259 } 2260 return sb.append("}").toString(); 2261 } 2262 2263 @Override writeToParcel(@onNull Parcel dest, int flags)2264 public void writeToParcel(@NonNull Parcel dest, int flags) { 2265 dest.writeInt(mType); 2266 dest.writeStrongBinder(mContainer); 2267 dest.writeBinderArray(mContainers); 2268 dest.writeTypedObject(mBounds, flags); 2269 dest.writeBoolean(mIncludingParents); 2270 dest.writeStrongBinder(mReparent); 2271 dest.writeTypedObject(mInsetsFrameProvider, flags); 2272 dest.writeStrongBinder(mInsetsFrameOwner); 2273 dest.writeBoolean(mToTop); 2274 dest.writeBoolean(mReparentTopOnly); 2275 dest.writeIntArray(mWindowingModes); 2276 dest.writeIntArray(mActivityTypes); 2277 dest.writeBundle(mLaunchOptions); 2278 dest.writeBundle(mAppCompatOptions); 2279 dest.writeTypedObject(mActivityIntent, flags); 2280 dest.writeTypedObject(mTaskFragmentOperation, flags); 2281 dest.writeTypedObject(mKeyguardState, flags); 2282 dest.writeTypedObject(mPendingIntent, flags); 2283 dest.writeTypedObject(mShortcutInfo, flags); 2284 dest.writeBoolean(mAlwaysOnTop); 2285 dest.writeBoolean(mReparentLeafTaskIfRelaunch); 2286 dest.writeBoolean(mIsTrimmableFromRecents); 2287 dest.writeInt(mExcludeInsetsTypes); 2288 dest.writeBoolean(mLaunchAdjacentDisabled); 2289 dest.writeTypedObject(mSafeRegionBounds, flags); 2290 } 2291 2292 @Override describeContents()2293 public int describeContents() { 2294 return 0; 2295 } 2296 2297 public static final Creator<HierarchyOp> CREATOR = new Creator<HierarchyOp>() { 2298 @Override 2299 public HierarchyOp createFromParcel(@NonNull Parcel in) { 2300 return new HierarchyOp(in); 2301 } 2302 2303 @Override 2304 public HierarchyOp[] newArray(int size) { 2305 return new HierarchyOp[size]; 2306 } 2307 }; 2308 2309 private static class Builder { 2310 2311 @HierarchyOpType 2312 private final int mType; 2313 2314 @Nullable 2315 private IBinder mContainer; 2316 2317 @Nullable 2318 private IBinder[] mContainers; 2319 2320 @Nullable 2321 private IBinder mReparent; 2322 2323 @Nullable 2324 private InsetsFrameProvider mInsetsFrameProvider; 2325 2326 @Nullable 2327 private IBinder mInsetsFrameOwner; 2328 2329 private boolean mToTop; 2330 2331 private boolean mReparentTopOnly; 2332 2333 @Nullable 2334 private int[] mWindowingModes; 2335 2336 @Nullable 2337 private int[] mActivityTypes; 2338 2339 @Nullable 2340 private Bundle mLaunchOptions; 2341 2342 @Nullable 2343 private Bundle mAppCompatOptions; 2344 2345 @Nullable 2346 private Intent mActivityIntent; 2347 2348 @Nullable 2349 private TaskFragmentOperation mTaskFragmentOperation; 2350 2351 @Nullable 2352 private KeyguardState mKeyguardState; 2353 2354 @Nullable 2355 private PendingIntent mPendingIntent; 2356 2357 @Nullable 2358 private ShortcutInfo mShortcutInfo; 2359 2360 @Nullable 2361 private Rect mBounds; 2362 2363 private boolean mIncludingParents; 2364 2365 private boolean mAlwaysOnTop; 2366 2367 private boolean mReparentLeafTaskIfRelaunch; 2368 2369 private boolean mIsTrimmableFromRecents; 2370 2371 private @InsetsType int mExcludeInsetsTypes; 2372 2373 private boolean mLaunchAdjacentDisabled; 2374 2375 @Nullable 2376 private Rect mSafeRegionBounds; 2377 Builder(@ierarchyOpType int type)2378 Builder(@HierarchyOpType int type) { 2379 mType = type; 2380 } 2381 setContainer(@ullable IBinder container)2382 Builder setContainer(@Nullable IBinder container) { 2383 mContainer = container; 2384 return this; 2385 } 2386 setContainers(@ullable IBinder[] containers)2387 Builder setContainers(@Nullable IBinder[] containers) { 2388 mContainers = containers; 2389 return this; 2390 } 2391 setReparentContainer(@ullable IBinder reparentContainer)2392 Builder setReparentContainer(@Nullable IBinder reparentContainer) { 2393 mReparent = reparentContainer; 2394 return this; 2395 } 2396 setInsetsFrameProvider(InsetsFrameProvider provider)2397 Builder setInsetsFrameProvider(InsetsFrameProvider provider) { 2398 mInsetsFrameProvider = provider; 2399 return this; 2400 } 2401 setInsetsFrameOwner(@ullable IBinder owner)2402 Builder setInsetsFrameOwner(@Nullable IBinder owner) { 2403 mInsetsFrameOwner = owner; 2404 return this; 2405 } 2406 setToTop(boolean toTop)2407 Builder setToTop(boolean toTop) { 2408 mToTop = toTop; 2409 return this; 2410 } 2411 setReparentTopOnly(boolean reparentTopOnly)2412 Builder setReparentTopOnly(boolean reparentTopOnly) { 2413 mReparentTopOnly = reparentTopOnly; 2414 return this; 2415 } 2416 setWindowingModes(@ullable int[] windowingModes)2417 Builder setWindowingModes(@Nullable int[] windowingModes) { 2418 mWindowingModes = windowingModes; 2419 return this; 2420 } 2421 setActivityTypes(@ullable int[] activityTypes)2422 Builder setActivityTypes(@Nullable int[] activityTypes) { 2423 mActivityTypes = activityTypes; 2424 return this; 2425 } 2426 setLaunchOptions(@ullable Bundle launchOptions)2427 Builder setLaunchOptions(@Nullable Bundle launchOptions) { 2428 mLaunchOptions = launchOptions; 2429 return this; 2430 } 2431 setAppCompatOptions(@ullable Bundle appCompatOptions)2432 Builder setAppCompatOptions(@Nullable Bundle appCompatOptions) { 2433 mAppCompatOptions = appCompatOptions; 2434 return this; 2435 } 2436 setActivityIntent(@ullable Intent activityIntent)2437 Builder setActivityIntent(@Nullable Intent activityIntent) { 2438 mActivityIntent = activityIntent; 2439 return this; 2440 } 2441 setPendingIntent(@ullable PendingIntent sender)2442 Builder setPendingIntent(@Nullable PendingIntent sender) { 2443 mPendingIntent = sender; 2444 return this; 2445 } 2446 setAlwaysOnTop(boolean alwaysOnTop)2447 Builder setAlwaysOnTop(boolean alwaysOnTop) { 2448 mAlwaysOnTop = alwaysOnTop; 2449 return this; 2450 } 2451 setTaskFragmentOperation( @ullable TaskFragmentOperation taskFragmentOperation)2452 Builder setTaskFragmentOperation( 2453 @Nullable TaskFragmentOperation taskFragmentOperation) { 2454 mTaskFragmentOperation = taskFragmentOperation; 2455 return this; 2456 } 2457 setKeyguardState( @ullable KeyguardState keyguardState)2458 Builder setKeyguardState( 2459 @Nullable KeyguardState keyguardState) { 2460 mKeyguardState = keyguardState; 2461 return this; 2462 } 2463 setReparentLeafTaskIfRelaunch(boolean reparentLeafTaskIfRelaunch)2464 Builder setReparentLeafTaskIfRelaunch(boolean reparentLeafTaskIfRelaunch) { 2465 mReparentLeafTaskIfRelaunch = reparentLeafTaskIfRelaunch; 2466 return this; 2467 } 2468 setShortcutInfo(@ullable ShortcutInfo shortcutInfo)2469 Builder setShortcutInfo(@Nullable ShortcutInfo shortcutInfo) { 2470 mShortcutInfo = shortcutInfo; 2471 return this; 2472 } 2473 setBounds(@onNull Rect bounds)2474 Builder setBounds(@NonNull Rect bounds) { 2475 mBounds = bounds; 2476 return this; 2477 } 2478 setIncludingParents(boolean value)2479 Builder setIncludingParents(boolean value) { 2480 mIncludingParents = value; 2481 return this; 2482 } 2483 setIsTrimmableFromRecents(boolean isTrimmableFromRecents)2484 Builder setIsTrimmableFromRecents(boolean isTrimmableFromRecents) { 2485 mIsTrimmableFromRecents = isTrimmableFromRecents; 2486 return this; 2487 } 2488 setExcludeInsetsTypes(@nsetsType int excludeInsetsTypes)2489 Builder setExcludeInsetsTypes(@InsetsType int excludeInsetsTypes) { 2490 mExcludeInsetsTypes = excludeInsetsTypes; 2491 return this; 2492 } 2493 setLaunchAdjacentDisabled(boolean disabled)2494 Builder setLaunchAdjacentDisabled(boolean disabled) { 2495 mLaunchAdjacentDisabled = disabled; 2496 return this; 2497 } 2498 setSafeRegionBounds(Rect safeRegionBounds)2499 Builder setSafeRegionBounds(Rect safeRegionBounds) { 2500 mSafeRegionBounds = safeRegionBounds; 2501 return this; 2502 } 2503 2504 @NonNull build()2505 HierarchyOp build() { 2506 final HierarchyOp hierarchyOp = new HierarchyOp(mType); 2507 hierarchyOp.mContainer = mContainer; 2508 hierarchyOp.mContainers = mContainers; 2509 hierarchyOp.mReparent = mReparent; 2510 hierarchyOp.mWindowingModes = mWindowingModes != null 2511 ? Arrays.copyOf(mWindowingModes, mWindowingModes.length) 2512 : null; 2513 hierarchyOp.mActivityTypes = mActivityTypes != null 2514 ? Arrays.copyOf(mActivityTypes, mActivityTypes.length) 2515 : null; 2516 hierarchyOp.mInsetsFrameProvider = mInsetsFrameProvider; 2517 hierarchyOp.mInsetsFrameOwner = mInsetsFrameOwner; 2518 hierarchyOp.mToTop = mToTop; 2519 hierarchyOp.mReparentTopOnly = mReparentTopOnly; 2520 hierarchyOp.mLaunchOptions = mLaunchOptions; 2521 hierarchyOp.mAppCompatOptions = mAppCompatOptions; 2522 hierarchyOp.mActivityIntent = mActivityIntent; 2523 hierarchyOp.mPendingIntent = mPendingIntent; 2524 hierarchyOp.mAlwaysOnTop = mAlwaysOnTop; 2525 hierarchyOp.mTaskFragmentOperation = mTaskFragmentOperation; 2526 hierarchyOp.mKeyguardState = mKeyguardState; 2527 hierarchyOp.mShortcutInfo = mShortcutInfo; 2528 hierarchyOp.mBounds = mBounds; 2529 hierarchyOp.mIncludingParents = mIncludingParents; 2530 hierarchyOp.mReparentLeafTaskIfRelaunch = mReparentLeafTaskIfRelaunch; 2531 hierarchyOp.mIsTrimmableFromRecents = mIsTrimmableFromRecents; 2532 hierarchyOp.mExcludeInsetsTypes = mExcludeInsetsTypes; 2533 hierarchyOp.mLaunchAdjacentDisabled = mLaunchAdjacentDisabled; 2534 hierarchyOp.mSafeRegionBounds = mSafeRegionBounds; 2535 return hierarchyOp; 2536 } 2537 } 2538 } 2539 2540 /** 2541 * Helper class for building an options Bundle that can be used to set adjacent rules of 2542 * TaskFragments. 2543 */ 2544 public static class TaskFragmentAdjacentParams { 2545 private static final String DELAY_PRIMARY_LAST_ACTIVITY_REMOVAL = 2546 "android:transaction.adjacent.option.delay_primary_removal"; 2547 private static final String DELAY_SECONDARY_LAST_ACTIVITY_REMOVAL = 2548 "android:transaction.adjacent.option.delay_secondary_removal"; 2549 2550 private boolean mDelayPrimaryLastActivityRemoval; 2551 private boolean mDelaySecondaryLastActivityRemoval; 2552 TaskFragmentAdjacentParams()2553 public TaskFragmentAdjacentParams() { 2554 } 2555 TaskFragmentAdjacentParams(@onNull Bundle bundle)2556 public TaskFragmentAdjacentParams(@NonNull Bundle bundle) { 2557 mDelayPrimaryLastActivityRemoval = bundle.getBoolean( 2558 DELAY_PRIMARY_LAST_ACTIVITY_REMOVAL); 2559 mDelaySecondaryLastActivityRemoval = bundle.getBoolean( 2560 DELAY_SECONDARY_LAST_ACTIVITY_REMOVAL); 2561 } 2562 2563 /** @see #shouldDelayPrimaryLastActivityRemoval() */ setShouldDelayPrimaryLastActivityRemoval(boolean delay)2564 public void setShouldDelayPrimaryLastActivityRemoval(boolean delay) { 2565 mDelayPrimaryLastActivityRemoval = delay; 2566 } 2567 2568 /** @see #shouldDelaySecondaryLastActivityRemoval() */ setShouldDelaySecondaryLastActivityRemoval(boolean delay)2569 public void setShouldDelaySecondaryLastActivityRemoval(boolean delay) { 2570 mDelaySecondaryLastActivityRemoval = delay; 2571 } 2572 2573 /** 2574 * Whether to delay the last activity of the primary adjacent TaskFragment being immediately 2575 * removed while finishing. 2576 * <p> 2577 * It is usually set to {@code true} to give organizer an opportunity to perform other 2578 * actions or animations. An example is to finish together with the adjacent TaskFragment. 2579 * </p> 2580 */ shouldDelayPrimaryLastActivityRemoval()2581 public boolean shouldDelayPrimaryLastActivityRemoval() { 2582 return mDelayPrimaryLastActivityRemoval; 2583 } 2584 2585 /** 2586 * Similar to {@link #shouldDelayPrimaryLastActivityRemoval()}, but for the secondary 2587 * TaskFragment. 2588 */ shouldDelaySecondaryLastActivityRemoval()2589 public boolean shouldDelaySecondaryLastActivityRemoval() { 2590 return mDelaySecondaryLastActivityRemoval; 2591 } 2592 2593 @NonNull toBundle()2594 Bundle toBundle() { 2595 final Bundle b = new Bundle(); 2596 b.putBoolean(DELAY_PRIMARY_LAST_ACTIVITY_REMOVAL, mDelayPrimaryLastActivityRemoval); 2597 b.putBoolean(DELAY_SECONDARY_LAST_ACTIVITY_REMOVAL, mDelaySecondaryLastActivityRemoval); 2598 return b; 2599 } 2600 } 2601 } 2602