Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +22 −6 Original line number Diff line number Diff line Loading @@ -1194,7 +1194,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: { Loading Loading @@ -1850,12 +1856,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); Loading services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +67 −7 Original line number Diff line number Diff line Loading @@ -1488,7 +1488,7 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testReorderWithParents() { /* root default TDA ____|______ | | firstTda secondTda Loading @@ -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( Loading @@ -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 Loading @@ -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(); Loading Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +22 −6 Original line number Diff line number Diff line Loading @@ -1194,7 +1194,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: { Loading Loading @@ -1850,12 +1856,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); Loading
services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +67 −7 Original line number Diff line number Diff line Loading @@ -1488,7 +1488,7 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testReorderWithParents() { /* root default TDA ____|______ | | firstTda secondTda Loading @@ -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( Loading @@ -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 Loading @@ -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(); Loading