Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f622bbe9 authored by Gaurav Bhola's avatar Gaurav Bhola
Browse files

Support DisplayArea reordering via WindowContainerTransaction

- Extend the .reorder() api to work for DisplayAreas as well.

Flag: NONE (bug fix)
Fix: 344613038
Test: atest WindowOrganizerTests
Change-Id: Icbf6c5db434f4c15e39e0e499d72e152fc8219cf
parent c4371ef0
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -1187,7 +1187,13 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                        }
                    }
                }
                effects |= sanitizeAndApplyHierarchyOp(wc, hop);
                if (wc.asTask() != null) {
                    effects |= sanitizeAndApplyHierarchyOpForTask(wc.asTask(), hop);
                } else if (wc.asDisplayArea() != null) {
                    effects |= sanitizeAndApplyHierarchyOpForDisplayArea(wc.asDisplayArea(), hop);
                } else {
                    throw new IllegalArgumentException("Invalid container in hierarchy op");
                }
                break;
            }
            case HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION: {
@@ -1837,12 +1843,22 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
        return starterResult[0];
    }

    private int sanitizeAndApplyHierarchyOp(WindowContainer container,
            WindowContainerTransaction.HierarchyOp hop) {
        final Task task = container.asTask();
        if (task == null) {
            throw new IllegalArgumentException("Invalid container in hierarchy op");
    private int sanitizeAndApplyHierarchyOpForDisplayArea(@NonNull DisplayArea displayArea,
            @NonNull WindowContainerTransaction.HierarchyOp hop) {
        if (hop.getType() != HIERARCHY_OP_TYPE_REORDER) {
            throw new UnsupportedOperationException("DisplayArea only supports reordering");
        }
        if (displayArea.getParent() == null) {
            return TRANSACT_EFFECTS_NONE;
        }
        displayArea.getParent().positionChildAt(
                hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
                displayArea, hop.includingParents());
        return TRANSACT_EFFECTS_LIFECYCLE;
    }

    private int sanitizeAndApplyHierarchyOpForTask(@NonNull Task task,
            @NonNull WindowContainerTransaction.HierarchyOp hop) {
        final DisplayContent dc = task.getDisplayContent();
        if (dc == null) {
            Slog.w(TAG, "Container is no longer attached: " + task);
+67 −7
Original line number Diff line number Diff line
@@ -1488,7 +1488,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
    @Test
    public void testReorderWithParents() {
        /*
                  root
                  default TDA
               ____|______
               |         |
           firstTda    secondTda
@@ -1496,10 +1496,12 @@ public class WindowOrganizerTests extends WindowTestsBase {
         firstRootTask    secondRootTask

         */
        final TaskDisplayArea firstTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
        final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
                mDisplayContent, mRootWindowContainer.mWmService, "TestTaskDisplayArea",
        final TaskDisplayArea firstTaskDisplayArea = createTaskDisplayArea(
                mDisplayContent, mRootWindowContainer.mWmService, "FirstTaskDisplayArea",
                FEATURE_VENDOR_FIRST);
        final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
                mDisplayContent, mRootWindowContainer.mWmService, "SecondTaskDisplayArea",
                FEATURE_VENDOR_FIRST + 1);
        final Task firstRootTask = firstTaskDisplayArea.createRootTask(
                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
        final Task secondRootTask = secondTaskDisplayArea.createRootTask(
@@ -1508,9 +1510,6 @@ public class WindowOrganizerTests extends WindowTestsBase {
                .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
@@ -1532,6 +1531,67 @@ public class WindowOrganizerTests extends WindowTestsBase {
        assertThat(mDisplayContent.getBottomMostTask()).isEqualTo(firstRootTask);
    }

    @Test
    public void testReorderDisplayArea() {
        /*
                  defaultTda
               ____|______
               |         |
           firstTda    secondTda
               |             |
         firstRootTask    secondRootTask

         */
        final TaskDisplayArea firstTaskDisplayArea = createTaskDisplayArea(
                mDisplayContent, mRootWindowContainer.mWmService, "FirstTaskDisplayArea",
                FEATURE_VENDOR_FIRST);
        final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
                mDisplayContent, mRootWindowContainer.mWmService, "SecondTaskDisplayArea",
                FEATURE_VENDOR_FIRST + 1);
        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();

        WindowContainerTransaction wct = new WindowContainerTransaction();

        // Reorder to top
        wct.reorder(firstTaskDisplayArea.mRemoteToken.toWindowContainerToken(), true /* onTop */,
                true /* includingParents */);
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
        assertThat(mDisplayContent.getTopRootTask()).isEqualTo(firstRootTask);

        // Reorder to bottom
        wct.reorder(firstTaskDisplayArea.mRemoteToken.toWindowContainerToken(), false /* onTop */,
                true /* includingParents */);
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
        assertThat(mDisplayContent.getBottomMostTask()).isEqualTo(firstRootTask);
    }

    @Test
    public void testReparentDisplayAreaUnsupported() {
        final TaskDisplayArea firstTaskDisplayArea = createTaskDisplayArea(
                mDisplayContent, mRootWindowContainer.mWmService, "FirstTaskDisplayArea",
                FEATURE_VENDOR_FIRST);
        final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
                mDisplayContent, mRootWindowContainer.mWmService, "SecondTaskDisplayArea",
                FEATURE_VENDOR_FIRST + 1);

        WindowContainerTransaction wct = new WindowContainerTransaction();
        wct.reparent(firstTaskDisplayArea.mRemoteToken.toWindowContainerToken(),
                secondTaskDisplayArea.mRemoteToken.toWindowContainerToken(),
                true /* onTop */
        );

        assertThrows(UnsupportedOperationException.class, () ->
                mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct)
        );
    }

    @Test
    public void testAppearDeferThenVanish() {
        final ITaskOrganizer organizer = registerMockOrganizer();