Loading core/java/android/window/WindowContainerTransaction.java +48 −2 Original line number Diff line number Diff line Loading @@ -375,7 +375,23 @@ public final class WindowContainerTransaction implements Parcelable { */ @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; } Loading Loading @@ -1451,6 +1467,8 @@ public final class WindowContainerTransaction implements Parcelable { @Nullable private Rect mBounds; private boolean mIncludingParents; private boolean mAlwaysOnTop; private boolean mReparentLeafTaskIfRelaunch; Loading @@ -1464,11 +1482,22 @@ public final class WindowContainerTransaction implements Parcelable { .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(); } Loading Loading @@ -1555,6 +1584,7 @@ public final class WindowContainerTransaction implements Parcelable { mType = copy.mType; mContainer = copy.mContainer; mBounds = copy.mBounds; mIncludingParents = copy.mIncludingParents; mReparent = copy.mReparent; mInsetsFrameProvider = copy.mInsetsFrameProvider; mInsetsFrameOwner = copy.mInsetsFrameOwner; Loading @@ -1575,6 +1605,7 @@ public final class WindowContainerTransaction implements Parcelable { 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(); Loading Loading @@ -1678,6 +1709,12 @@ public final class WindowContainerTransaction implements Parcelable { 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) { Loading Loading @@ -1789,6 +1826,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeInt(mType); dest.writeStrongBinder(mContainer); dest.writeTypedObject(mBounds, flags); dest.writeBoolean(mIncludingParents); dest.writeStrongBinder(mReparent); dest.writeTypedObject(mInsetsFrameProvider, flags); dest.writeStrongBinder(mInsetsFrameOwner); Loading Loading @@ -1866,6 +1904,8 @@ public final class WindowContainerTransaction implements Parcelable { @Nullable private Rect mBounds; private boolean mIncludingParents; private boolean mAlwaysOnTop; private boolean mReparentLeafTaskIfRelaunch; Loading Loading @@ -1955,6 +1995,11 @@ public final class WindowContainerTransaction implements Parcelable { return this; } Builder setIncludingParents(boolean value) { mIncludingParents = value; return this; } HierarchyOp build() { final HierarchyOp hierarchyOp = new HierarchyOp(mType); hierarchyOp.mContainer = mContainer; Loading @@ -1976,6 +2021,7 @@ public final class WindowContainerTransaction implements Parcelable { hierarchyOp.mTaskFragmentOperation = mTaskFragmentOperation; hierarchyOp.mShortcutInfo = mShortcutInfo; hierarchyOp.mBounds = mBounds; hierarchyOp.mIncludingParents = mIncludingParents; hierarchyOp.mReparentLeafTaskIfRelaunch = mReparentLeafTaskIfRelaunch; return hierarchyOp; Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +2 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 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; Loading Loading @@ -1835,7 +1835,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub task.getParent().positionChildAt( hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM, task, false /* includingParents */); task, hop.includingParents()); } return TRANSACT_EFFECTS_LIFECYCLE; } Loading services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +48 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 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; Loading Loading @@ -1454,6 +1455,53 @@ public class WindowOrganizerTests extends WindowTestsBase { pendingEvents.get(0).mTask.getTaskInfo().taskDescription.getLabel()); } @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(); Loading Loading
core/java/android/window/WindowContainerTransaction.java +48 −2 Original line number Diff line number Diff line Loading @@ -375,7 +375,23 @@ public final class WindowContainerTransaction implements Parcelable { */ @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; } Loading Loading @@ -1451,6 +1467,8 @@ public final class WindowContainerTransaction implements Parcelable { @Nullable private Rect mBounds; private boolean mIncludingParents; private boolean mAlwaysOnTop; private boolean mReparentLeafTaskIfRelaunch; Loading @@ -1464,11 +1482,22 @@ public final class WindowContainerTransaction implements Parcelable { .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(); } Loading Loading @@ -1555,6 +1584,7 @@ public final class WindowContainerTransaction implements Parcelable { mType = copy.mType; mContainer = copy.mContainer; mBounds = copy.mBounds; mIncludingParents = copy.mIncludingParents; mReparent = copy.mReparent; mInsetsFrameProvider = copy.mInsetsFrameProvider; mInsetsFrameOwner = copy.mInsetsFrameOwner; Loading @@ -1575,6 +1605,7 @@ public final class WindowContainerTransaction implements Parcelable { 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(); Loading Loading @@ -1678,6 +1709,12 @@ public final class WindowContainerTransaction implements Parcelable { 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) { Loading Loading @@ -1789,6 +1826,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeInt(mType); dest.writeStrongBinder(mContainer); dest.writeTypedObject(mBounds, flags); dest.writeBoolean(mIncludingParents); dest.writeStrongBinder(mReparent); dest.writeTypedObject(mInsetsFrameProvider, flags); dest.writeStrongBinder(mInsetsFrameOwner); Loading Loading @@ -1866,6 +1904,8 @@ public final class WindowContainerTransaction implements Parcelable { @Nullable private Rect mBounds; private boolean mIncludingParents; private boolean mAlwaysOnTop; private boolean mReparentLeafTaskIfRelaunch; Loading Loading @@ -1955,6 +1995,11 @@ public final class WindowContainerTransaction implements Parcelable { return this; } Builder setIncludingParents(boolean value) { mIncludingParents = value; return this; } HierarchyOp build() { final HierarchyOp hierarchyOp = new HierarchyOp(mType); hierarchyOp.mContainer = mContainer; Loading @@ -1976,6 +2021,7 @@ public final class WindowContainerTransaction implements Parcelable { hierarchyOp.mTaskFragmentOperation = mTaskFragmentOperation; hierarchyOp.mShortcutInfo = mShortcutInfo; hierarchyOp.mBounds = mBounds; hierarchyOp.mIncludingParents = mIncludingParents; hierarchyOp.mReparentLeafTaskIfRelaunch = mReparentLeafTaskIfRelaunch; return hierarchyOp; Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +2 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 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; Loading Loading @@ -1835,7 +1835,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub task.getParent().positionChildAt( hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM, task, false /* includingParents */); task, hop.includingParents()); } return TRANSACT_EFFECTS_LIFECYCLE; } Loading
services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +48 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 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; Loading Loading @@ -1454,6 +1455,53 @@ public class WindowOrganizerTests extends WindowTestsBase { pendingEvents.get(0).mTask.getTaskInfo().taskDescription.getLabel()); } @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(); Loading