Merge "Add an option to reorder a task along with its parents" into main
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index 5e88d97c..f4f6c8a 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -375,7 +375,23 @@
*/
@NonNull
public WindowContainerTransaction reorder(@NonNull WindowContainerToken child, boolean onTop) {
- mHierarchyOps.add(HierarchyOp.createForReorder(child.asBinder(), onTop));
+ return reorder(child, onTop, false /* includingParents */);
+ }
+
+ /**
+ * Reorders a container within its parent with an option to reorder all the parents in the
+ * hierarchy above among their respective siblings.
+ *
+ * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
+ * the bottom.
+ * @param includingParents When {@code true}, all the parents in the hierarchy above are also
+ * reordered among their respective siblings.
+ * @hide
+ */
+ @NonNull
+ public WindowContainerTransaction reorder(@NonNull WindowContainerToken child, boolean onTop,
+ boolean includingParents) {
+ mHierarchyOps.add(HierarchyOp.createForReorder(child.asBinder(), onTop, includingParents));
return this;
}
@@ -1451,6 +1467,8 @@
@Nullable
private Rect mBounds;
+ private boolean mIncludingParents;
+
private boolean mAlwaysOnTop;
private boolean mReparentLeafTaskIfRelaunch;
@@ -1464,11 +1482,22 @@
.build();
}
- public static HierarchyOp createForReorder(@NonNull IBinder container, boolean toTop) {
+ /**
+ * Creates the {@link HierarchyOp} for the reorder operation.
+ *
+ * @param container which needs to be reordered
+ * @param toTop if true, the container reorders
+ * @param includingParents if true, all the parents in the hierarchy above are also
+ * reoredered among their respective siblings
+ * @return
+ */
+ public static HierarchyOp createForReorder(@NonNull IBinder container, boolean toTop,
+ boolean includingParents) {
return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REORDER)
.setContainer(container)
.setReparentContainer(container)
.setToTop(toTop)
+ .setIncludingParents(includingParents)
.build();
}
@@ -1555,6 +1584,7 @@
mType = copy.mType;
mContainer = copy.mContainer;
mBounds = copy.mBounds;
+ mIncludingParents = copy.mIncludingParents;
mReparent = copy.mReparent;
mInsetsFrameProvider = copy.mInsetsFrameProvider;
mInsetsFrameOwner = copy.mInsetsFrameOwner;
@@ -1575,6 +1605,7 @@
mType = in.readInt();
mContainer = in.readStrongBinder();
mBounds = in.readTypedObject(Rect.CREATOR);
+ mIncludingParents = in.readBoolean();
mReparent = in.readStrongBinder();
mInsetsFrameProvider = in.readTypedObject(InsetsFrameProvider.CREATOR);
mInsetsFrameOwner = in.readStrongBinder();
@@ -1678,6 +1709,12 @@
return mBounds;
}
+ /** Denotes whether the parents should also be included in the op. */
+ @NonNull
+ public boolean includingParents() {
+ return mIncludingParents;
+ }
+
/** Gets a string representation of a hierarchy-op type. */
public static String hopToString(int type) {
switch (type) {
@@ -1789,6 +1826,7 @@
dest.writeInt(mType);
dest.writeStrongBinder(mContainer);
dest.writeTypedObject(mBounds, flags);
+ dest.writeBoolean(mIncludingParents);
dest.writeStrongBinder(mReparent);
dest.writeTypedObject(mInsetsFrameProvider, flags);
dest.writeStrongBinder(mInsetsFrameOwner);
@@ -1866,6 +1904,8 @@
@Nullable
private Rect mBounds;
+ private boolean mIncludingParents;
+
private boolean mAlwaysOnTop;
private boolean mReparentLeafTaskIfRelaunch;
@@ -1955,6 +1995,11 @@
return this;
}
+ Builder setIncludingParents(boolean value) {
+ mIncludingParents = value;
+ return this;
+ }
+
HierarchyOp build() {
final HierarchyOp hierarchyOp = new HierarchyOp(mType);
hierarchyOp.mContainer = mContainer;
@@ -1976,6 +2021,7 @@
hierarchyOp.mTaskFragmentOperation = mTaskFragmentOperation;
hierarchyOp.mShortcutInfo = mShortcutInfo;
hierarchyOp.mBounds = mBounds;
+ hierarchyOp.mIncludingParents = mIncludingParents;
hierarchyOp.mReparentLeafTaskIfRelaunch = mReparentLeafTaskIfRelaunch;
return hierarchyOp;
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 7eda53f..1034611 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -23,8 +23,8 @@
import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS;
-import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_OR_MOVE_TASK_FRAGMENT_DECOR_SURFACE;
+import static android.window.TaskFragmentOperation.OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.TaskFragmentOperation.OP_TYPE_REMOVE_TASK_FRAGMENT_DECOR_SURFACE;
import static android.window.TaskFragmentOperation.OP_TYPE_REORDER_TO_BOTTOM_OF_TASK;
@@ -1835,7 +1835,7 @@
task.getParent().positionChildAt(
hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
- task, false /* includingParents */);
+ task, hop.includingParents());
}
return TRANSACT_EFFECTS_LIFECYCLE;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index fb854c5..ab4deca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -31,6 +31,7 @@
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -1455,6 +1456,53 @@
}
@Test
+ public void testReorderWithParents() {
+ /*
+ root
+ ____|______
+ | |
+ firstTda secondTda
+ | |
+ firstRootTask secondRootTask
+
+ */
+ final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
+ final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
+ mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
+ FEATURE_VENDOR_FIRST);
+ final Task firstRootTask = firstTaskDisplayArea.createRootTask(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
+ final Task secondRootTask = secondTaskDisplayArea.createRootTask(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
+ .setTask(firstRootTask).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
+ .setTask(secondRootTask).build();
+ // This assertion is just a defense to ensure that firstRootTask is not the top most
+ // by default
+ assertThat(mDisplayContent.getTopRootTask()).isEqualTo(secondRootTask);
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+
+ // Reorder to top
+ wct.reorder(firstRootTask.mRemoteToken.toWindowContainerToken(), true /* onTop */,
+ true /* includingParents */);
+ mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
+
+ // firstRootTask can only be on the top if its TDA was also reordered to the Top which
+ // in-turn ensures that the reorder happened including the parents.
+ assertThat(mDisplayContent.getTopRootTask()).isEqualTo(firstRootTask);
+
+ // Reorder to bottom
+ wct.reorder(firstRootTask.mRemoteToken.toWindowContainerToken(), false /* onTop */,
+ true /* includingParents */);
+ mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
+
+ // firstRootTask can only be on the bottom if its TDA was also reordered to the bottom
+ // which in-turn ensures that the reorder happened including the parents.
+ assertThat(mDisplayContent.getBottomMostTask()).isEqualTo(firstRootTask);
+ }
+
+ @Test
public void testAppearDeferThenVanish() {
final ITaskOrganizer organizer = registerMockOrganizer();
final Task rootTask = createRootTask();