From 91feddacb058a685031755736974fd9caf63085a Mon Sep 17 00:00:00 2001 From: Jeff Chang Date: Wed, 20 Apr 2022 17:56:37 +0800 Subject: [PATCH] Update launch root rule to consider candidate task if needed Bbcd34357, changed the rule for evaluating the root task while dealing with the candidate task. The source task of the created-by-organizer parent is considered as the default root task. The rule changes the behavior in split-screen cases. This CL considers the candidate task in priority for split-screen as before. Bug: 227473044 Test: atest MultiWindowTests atest TaskDisplayAreaTests Change-Id: Ibb75ab0311550d1093c878500e4671f569977753 --- .../core/java/com/android/server/wm/Task.java | 4 +-- .../android/server/wm/TaskDisplayArea.java | 25 ++++++++++++--- .../server/wm/TaskDisplayAreaTests.java | 31 +++++++++++++++++++ 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 9ea566ece6ec5..f16c27f40489e 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -1718,8 +1718,8 @@ class Task extends TaskFragment { /** Returns {@code true} if this task is currently in split-screen. */ boolean inSplitScreen() { return getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW - && getRootTask() != null - && getRootTask().getAdjacentTaskFragment() != null; + && getCreatedByOrganizerTask() != null + && getCreatedByOrganizerTask().getAdjacentTaskFragment() != null; } private boolean supportsSplitScreenWindowingModeInner(@Nullable TaskDisplayArea tda) { diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 7a7bf1f877b93..a3c934f1654a0 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -963,7 +963,7 @@ final class TaskDisplayArea extends DisplayArea { } else if (candidateTask != null) { final int position = onTop ? POSITION_TOP : POSITION_BOTTOM; final Task launchRootTask = getLaunchRootTask(resolvedWindowingMode, activityType, - options, sourceTask, launchFlags); + options, sourceTask, launchFlags, candidateTask); if (launchRootTask != null) { if (candidateTask.getParent() == null) { launchRootTask.addChild(candidateTask, position); @@ -1112,6 +1112,13 @@ final class TaskDisplayArea extends DisplayArea { @Nullable Task getLaunchRootTask(int windowingMode, int activityType, @Nullable ActivityOptions options, @Nullable Task sourceTask, int launchFlags) { + return getLaunchRootTask(windowingMode, activityType, options, sourceTask, launchFlags, + null /* candidateTask */); + } + + @Nullable + Task getLaunchRootTask(int windowingMode, int activityType, @Nullable ActivityOptions options, + @Nullable Task sourceTask, int launchFlags, @Nullable Task candidateTask) { // Try to use the launch root task in options if available. if (options != null) { final Task launchRootTask = Task.fromWindowContainerToken(options.getLaunchRootTask()); @@ -1152,9 +1159,19 @@ final class TaskDisplayArea extends DisplayArea { } // For a better split UX, If a task is launching from a created-by-organizer task, it should - // be launched into the same created-by-organizer task as well. - if (sourceTask != null) { - return sourceTask.getCreatedByOrganizerTask(); + // be launched into the same created-by-organizer task as well. Unless, the candidate task + // is already positioned in the split. + Task preferredRootInSplit = sourceTask != null && sourceTask.inSplitScreen() + ? sourceTask.getCreatedByOrganizerTask() : null; + if (preferredRootInSplit != null) { + if (candidateTask != null) { + final Task candidateRoot = candidateTask.getCreatedByOrganizerTask(); + if (candidateRoot != null && candidateRoot != preferredRootInSplit + && preferredRootInSplit == candidateRoot.getAdjacentTaskFragment()) { + preferredRootInSplit = candidateRoot; + } + } + return preferredRootInSplit; } return null; diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java index 80f6bceb884c3..e5e0145095c1a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java @@ -741,4 +741,35 @@ public class TaskDisplayAreaTests extends WindowTestsBase { assertEquals(isAssistantOnTop ? topPosition : topPosition - 4, getTaskIndexOf(taskDisplayArea, assistRootTask)); } + + /** + * This test verifies proper launch root based on source and candidate task for split screen. + * If a task is launching from a created-by-organizer task, it should be launched into the + * same created-by-organizer task as well. Unless, the candidate task is already positioned in + * the split. + */ + @Test + public void getLaunchRootTaskInSplit() { + final Task rootTask = createTask( + mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); + rootTask.mCreatedByOrganizer = true; + final Task adjacentRootTask = createTask( + mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); + adjacentRootTask.mCreatedByOrganizer = true; + final Task candidateTask = createTaskInRootTask(rootTask, 0 /* userId*/); + final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea(); + adjacentRootTask.setAdjacentTaskFragment(rootTask, false /* moveTogether */); + + // Verify the launch root with candidate task + Task actualRootTask = taskDisplayArea.getLaunchRootTask(WINDOWING_MODE_UNDEFINED, + ACTIVITY_TYPE_STANDARD, null /* options */, adjacentRootTask /* sourceTask */, + 0 /* launchFlags */, candidateTask); + assertSame(rootTask, actualRootTask.getRootTask()); + + // Verify the launch root task without candidate task + actualRootTask = taskDisplayArea.getLaunchRootTask(WINDOWING_MODE_UNDEFINED, + ACTIVITY_TYPE_STANDARD, null /* options */, adjacentRootTask /* sourceTask */, + 0 /* launchFlags */); + assertSame(adjacentRootTask, actualRootTask.getRootTask()); + } }