Introduce WCT#clearAdjacentRoots()

This CL adds clearAdjacentRoots() to WCT as the “inversion” of
setAdjacentRoots().
ARC needs this capability because adjacency of the split roots
depends on the device status and it should be possible to switch
that in runtime.

Bug: 245239136
Test: WindowOrganizerTests
Change-Id: I59fb28508d56973fe4643f4c4a7deee6d29cbb4f
This commit is contained in:
Toshiki Kikuchi
2022-09-06 15:14:42 +09:00
parent 3eab2c0d56
commit ef2bb4ffbb
3 changed files with 45 additions and 2 deletions

View File

@@ -814,6 +814,18 @@ public final class WindowContainerTransaction implements Parcelable {
return this;
}
/**
* Clears container adjacent.
* @param root the root container to clear the adjacent roots for.
* @hide
*/
@NonNull
public WindowContainerTransaction clearAdjacentRoots(
@NonNull WindowContainerToken root) {
mHierarchyOps.add(HierarchyOp.createForClearAdjacentRoots(root.asBinder()));
return this;
}
/**
* Merges another WCT into this one.
* @param transfer When true, this will transfer everything from other potentially leaving
@@ -1229,6 +1241,7 @@ public final class WindowContainerTransaction implements Parcelable {
public static final int HIERARCHY_OP_TYPE_REMOVE_TASK = 20;
public static final int HIERARCHY_OP_TYPE_FINISH_ACTIVITY = 21;
public static final int HIERARCHY_OP_TYPE_SET_COMPANION_TASK_FRAGMENT = 22;
public static final int HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS = 23;
// The following key(s) are for use with mLaunchOptions:
// When launching a task (eg. from recents), this is the taskId to be launched.
@@ -1365,6 +1378,13 @@ public final class WindowContainerTransaction implements Parcelable {
.build();
}
/** Create a hierarchy op for clearing adjacent root tasks. */
public static HierarchyOp createForClearAdjacentRoots(@NonNull IBinder root) {
return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS)
.setContainer(root)
.build();
}
/** Only creates through {@link Builder}. */
private HierarchyOp(int type) {
mType = type;
@@ -1560,6 +1580,8 @@ public final class WindowContainerTransaction implements Parcelable {
case HIERARCHY_OP_TYPE_SET_COMPANION_TASK_FRAGMENT:
return "{setCompanionTaskFragment: container = " + mContainer + " companion = "
+ mReparent + "}";
case HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS:
return "{ClearAdjacentRoot: container=" + mContainer + "}";
default:
return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
+ " mToTop=" + mToTop

View File

@@ -23,6 +23,7 @@ import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_FINISH_ACTIVITY;
@@ -850,6 +851,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
effects |= setAdjacentRootsHierarchyOp(hop);
break;
}
case HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS: {
effects |= clearAdjacentRootsHierarchyOp(hop);
break;
}
case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT: {
final TaskFragmentCreationParams taskFragmentCreationOptions =
hop.getTaskFragmentCreationOptions();
@@ -1486,6 +1491,17 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
return TRANSACT_EFFECTS_LIFECYCLE;
}
private int clearAdjacentRootsHierarchyOp(WindowContainerTransaction.HierarchyOp hop) {
final TaskFragment root = WindowContainer.fromBinder(hop.getContainer()).asTaskFragment();
if (!root.mCreatedByOrganizer) {
throw new IllegalArgumentException("clearAdjacentRootsHierarchyOp: Not created by"
+ " organizer root=" + root);
}
root.resetAdjacentTaskFragment();
return TRANSACT_EFFECTS_LIFECYCLE;
}
private void sanitizeWindowContainer(WindowContainer wc) {
if (!(wc instanceof TaskFragment) && !(wc instanceof DisplayArea)) {
throw new RuntimeException("Invalid token in task fragment or displayArea transaction");
@@ -1650,6 +1666,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
WindowContainer.fromBinder(hop.getAdjacentRoot()),
organizer);
break;
case HIERARCHY_OP_TYPE_CLEAR_ADJACENT_ROOTS:
enforceTaskFragmentOrganized(func,
WindowContainer.fromBinder(hop.getContainer()), organizer);
break;
case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT:
// We are allowing organizer to create TaskFragment. We will check the
// ownerToken in #createTaskFragment, and trigger error callback if that is not

View File

@@ -736,11 +736,12 @@ public class WindowOrganizerTests extends WindowTestsBase {
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertEquals(dc.getDefaultTaskDisplayArea().mLaunchAdjacentFlagRootTask, task1);
task1.setAdjacentTaskFragment(null);
task2.setAdjacentTaskFragment(null);
wct = new WindowContainerTransaction();
wct.clearAdjacentRoots(info1.token);
wct.clearLaunchAdjacentFlagRoot(info1.token);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertEquals(task1.getAdjacentTaskFragment(), null);
assertEquals(task2.getAdjacentTaskFragment(), null);
assertEquals(dc.getDefaultTaskDisplayArea().mLaunchAdjacentFlagRootTask, null);
}