diff options
| author | 2025-01-17 14:07:54 -0800 | |
|---|---|---|
| committer | 2025-01-17 14:07:54 -0800 | |
| commit | 60f66360c23cc7a9f99b37581b716bd3cc1e4c7c (patch) | |
| tree | c0a0e0b4d854d9bb1d6dcf4046ebc24f487ef65f | |
| parent | 5ea9b08ef8d05e8dd046494a73aa676615f8e5bb (diff) | |
| parent | 968154b0cd9bbcb3809e1f47004e2260dfe80779 (diff) | |
Merge "[4/N] Desks: Add WCT#removeRootTask()" into main
4 files changed, 88 insertions, 2 deletions
| diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl index 1748b9d38538..8934cf67b380 100644 --- a/core/java/android/window/ITaskOrganizerController.aidl +++ b/core/java/android/window/ITaskOrganizerController.aidl @@ -39,7 +39,12 @@ interface ITaskOrganizerController {       */      void unregisterTaskOrganizer(ITaskOrganizer organizer); -    /** Creates a persistent root task in WM for a particular windowing-mode. */ +    /** +    * Creates a persistent root task in WM for a particular windowing-mode. +    * +    * It may be removed using {@link #deleteRootTask} or through +    * {@link WindowContainerTransaction#removeRootTask}. +    */      void createRootTask(int displayId, int windowingMode, IBinder launchCookie,              boolean removeWithTaskOrganizer); diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java index 02f8e2f59b33..ce0ccd5c6d0d 100644 --- a/core/java/android/window/WindowContainerTransaction.java +++ b/core/java/android/window/WindowContainerTransaction.java @@ -614,6 +614,10 @@ public final class WindowContainerTransaction implements Parcelable {      /**       * Finds and removes a task and its children using its container token. The task is removed       * from recents. +     * +     * If the task is a root task, its leaves are removed but the root task is not. Use +     * {@link #removeRootTask(WindowContainerToken)} to remove the root task. +     *       * @param containerToken ContainerToken of Task to be removed       */      @NonNull @@ -623,6 +627,19 @@ public final class WindowContainerTransaction implements Parcelable {      }      /** +     * Finds and removes a root task created by an organizer and its leaves using its container +     * token. +     * +     * @param containerToken ContainerToken of the root task to be removed +     * @hide +     */ +    @NonNull +    public WindowContainerTransaction removeRootTask(@NonNull WindowContainerToken containerToken) { +        mHierarchyOps.add(HierarchyOp.createForRemoveRootTask(containerToken.asBinder())); +        return this; +    } + +    /**       * Sets whether a container is being drag-resized.       * When {@code true}, the client will reuse a single (larger) surface size to avoid       * continuous allocations on every size change. @@ -1573,6 +1590,7 @@ public final class WindowContainerTransaction implements Parcelable {          public static final int HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES = 21;          public static final int HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE = 22;          public static final int HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT = 23; +        public static final int HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK = 24;          @IntDef(prefix = {"HIERARCHY_OP_TYPE_"}, value = {                  HIERARCHY_OP_TYPE_REPARENT, @@ -1598,7 +1616,8 @@ public final class WindowContainerTransaction implements Parcelable {                  HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION,                  HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES,                  HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE, -                HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT +                HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT, +                HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK,          })          @Retention(RetentionPolicy.SOURCE)          public @interface HierarchyOpType { @@ -1795,6 +1814,18 @@ public final class WindowContainerTransaction implements Parcelable {                      .build();          } +        /** +         * Creates a hierarchy op for deleting a root task +         * +         * @hide +         **/ +        @NonNull +        public static HierarchyOp createForRemoveRootTask(@NonNull IBinder container) { +            return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK) +                    .setContainer(container) +                    .build(); +        } +          /** Creates a hierarchy op for clearing adjacent root tasks. */          @NonNull          public static HierarchyOp createForClearAdjacentRoots(@NonNull IBinder root) { @@ -2012,6 +2043,7 @@ public final class WindowContainerTransaction implements Parcelable {                      return "removeInsetsFrameProvider";                  case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: return "setAlwaysOnTop";                  case HIERARCHY_OP_TYPE_REMOVE_TASK: return "removeTask"; +                case HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK: return "removeRootTask";                  case HIERARCHY_OP_TYPE_FINISH_ACTIVITY: return "finishActivity";                  case HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS: return "clearAdjacentRoots";                  case HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH: @@ -2096,6 +2128,9 @@ public final class WindowContainerTransaction implements Parcelable {                  case HIERARCHY_OP_TYPE_REMOVE_TASK:                      sb.append("task=").append(mContainer);                      break; +                case HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK: +                    sb.append("rootTask=").append(mContainer); +                    break;                  case HIERARCHY_OP_TYPE_FINISH_ACTIVITY:                      sb.append("activity=").append(mContainer);                      break; diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index ad19b9a44670..a1755e4d9d3b 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -52,6 +52,7 @@ import static android.window.WindowContainerTransaction.Change.CHANGE_FOCUSABLE;  import static android.window.WindowContainerTransaction.Change.CHANGE_FORCE_TRANSLUCENT;  import static android.window.WindowContainerTransaction.Change.CHANGE_HIDDEN;  import static android.window.WindowContainerTransaction.Change.CHANGE_RELATIVE_BOUNDS; +import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK;  import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE;  import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER;  import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION; @@ -1131,6 +1132,23 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub                  }                  break;              } +            case HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK: { +                final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer()); +                if (wc == null || wc.asTask() == null || !wc.isAttached() +                        || !wc.asTask().isRootTask() || !wc.asTask().mCreatedByOrganizer) { +                    Slog.e(TAG, "Attempt to remove invalid task: " + wc); +                    break; +                } +                final Task task = wc.asTask(); +                if (task.isVisibleRequested() || task.isVisible()) { +                    effects |= TRANSACT_EFFECTS_LIFECYCLE; +                } +                // Removes its leaves, but not itself. +                mService.mTaskSupervisor.removeRootTask(task); +                // Now that the root has no leaves, remove it too. . +                task.remove(true /* withTransition */, "remove-root-task-through-hierarchyOp"); +                break; +            }              case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: {                  final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());                  if (wc == null || !wc.isAttached()) { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java index e9ece5dbdcc4..369600c3f8d7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java @@ -79,6 +79,34 @@ public class WindowContainerTransactionTests extends WindowTestsBase {      }      @Test +    public void testRemoveRootTask() { +        final Task rootTask = createTask(mDisplayContent); +        final Task task = createTaskInRootTask(rootTask, 0 /* userId */); +        final ActivityRecord activity = createActivityRecord(mDisplayContent, task); +        final TaskDisplayArea taskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea(); + +        WindowContainerTransaction wct = new WindowContainerTransaction(); +        WindowContainerToken token = rootTask.getTaskInfo().token; +        wct.removeTask(token); +        applyTransaction(wct); + +        // There is still an activity to be destroyed, so the task is not removed immediately. +        assertNotNull(task.getParent()); +        assertTrue(rootTask.hasChild()); +        assertTrue(task.hasChild()); +        assertTrue(activity.finishing); + +        activity.destroyed("testRemoveRootTask"); +        // Assert that the container was removed after the activity is destroyed. +        assertNull(task.getParent()); +        assertEquals(0, task.getChildCount()); +        assertNull(activity.getParent()); +        assertNull(taskDisplayArea.getTask(task1 -> task1.mTaskId == rootTask.mTaskId)); +        verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(task); +        verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(rootTask); +    } + +    @Test      public void testDesktopMode_tasksAreBroughtToFront() {          final TestDesktopOrganizer desktopOrganizer = new TestDesktopOrganizer(mAtm);          TaskDisplayArea tda = desktopOrganizer.mDefaultTDA; |