From bbcd34357beafefa2fc648094ae4a025e674d895 Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Tue, 18 Jan 2022 10:57:12 +0800 Subject: Removing RWC#getValidLaunchRootTaskInTaskDisplayArea ... and consolidate the flow with TDA#getOrCreateRootTask. Updating few changes regarding to the launch windowing mode calculation since the windowing mode is an important input while determining the root task. It wasn't needed because the candidate root task was reused in most cases. Secondly, the root task was always created on default TDA (regardless the preferable one is the secondary TDA) if no launching activity was given. This CL also changes the behavior to allow creating root tasks from the preferable TDA. Bug: 184806710 Test: atest RootWindowContainerTests Change-Id: I1e8055bb7bb2da8fe35bdfae1f85c610d5751434 --- .../com/android/server/wm/RootWindowContainer.java | 135 ++------------------- .../com/android/server/wm/TaskDisplayArea.java | 18 ++- .../server/wm/TaskLaunchParamsModifier.java | 16 ++- .../android/server/wm/ActivityStarterTests.java | 6 +- .../server/wm/RootWindowContainerTests.java | 34 +++++- .../server/wm/TaskLaunchParamsModifierTests.java | 4 +- 6 files changed, 62 insertions(+), 151 deletions(-) diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 8ab2ee03a1e3..c07b661057df 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -18,15 +18,9 @@ package com.android.server.wm; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; -import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; @@ -2791,35 +2785,17 @@ class RootWindowContainer extends WindowContainer Task rootTask = null; // Next preference for root task goes to the taskDisplayArea candidate. - if (launchParams != null && launchParams.mPreferredTaskDisplayArea != null) { + if (launchParams != null && launchParams.mPreferredTaskDisplayArea != null + && canLaunchOnDisplay(r, launchParams.mPreferredTaskDisplayArea.getDisplayId())) { taskDisplayArea = launchParams.mPreferredTaskDisplayArea; } - - if (taskDisplayArea == null && displayId != INVALID_DISPLAY) { - final DisplayContent displayContent = getDisplayContent(displayId); - if (displayContent != null) { - taskDisplayArea = displayContent.getDefaultTaskDisplayArea(); - } + if (taskDisplayArea == null && displayId != INVALID_DISPLAY + && canLaunchOnDisplay(r, displayId)) { + taskDisplayArea = getDisplayContent(displayId).getDefaultTaskDisplayArea(); } - if (taskDisplayArea != null) { - final int tdaDisplayId = taskDisplayArea.getDisplayId(); - if (canLaunchOnDisplay(r, tdaDisplayId)) { - if (r != null) { - final Task result = getValidLaunchRootTaskInTaskDisplayArea( - taskDisplayArea, r, candidateTask, options, launchParams); - if (result != null) { - return result; - } - } - // Falling back to default task container - taskDisplayArea = taskDisplayArea.mDisplayContent.getDefaultTaskDisplayArea(); - rootTask = taskDisplayArea.getOrCreateRootTask(r, options, candidateTask, - sourceTask, launchParams, launchFlags, activityType, onTop); - if (rootTask != null) { - return rootTask; - } - } + return taskDisplayArea.getOrCreateRootTask(r, options, candidateTask, + sourceTask, launchParams, launchFlags, activityType, onTop); } // Give preference to the root task and display of the input task and activity if they @@ -2869,103 +2845,6 @@ class RootWindowContainer extends WindowContainer return r.canBeLaunchedOnDisplay(displayId); } - /** - * Get a topmost root task on the display area, that is a valid launch root task for - * specified activity. If there is no such root task, new dynamic root task can be created. - * - * @param taskDisplayArea Target display area. - * @param r Activity that should be launched there. - * @param candidateTask The possible task the activity might be put in. - * @return Existing root task if there is a valid one, new dynamic root task if it is valid - * or null. - */ - @VisibleForTesting - Task getValidLaunchRootTaskInTaskDisplayArea(@NonNull TaskDisplayArea taskDisplayArea, - @NonNull ActivityRecord r, @Nullable Task candidateTask, - @Nullable ActivityOptions options, - @Nullable LaunchParamsController.LaunchParams launchParams) { - if (!r.canBeLaunchedOnDisplay(taskDisplayArea.getDisplayId())) { - return null; - } - - // If {@code r} is already in target display area and its task is the same as the candidate - // task, the intention should be getting a launch root task for the reusable activity, so we - // can use the existing root task. - if (candidateTask != null) { - final TaskDisplayArea attachedTaskDisplayArea = candidateTask.getDisplayArea(); - if (attachedTaskDisplayArea == null || attachedTaskDisplayArea == taskDisplayArea) { - return candidateTask.getRootTask(); - } - // Or the candidate task is already a root task that can be reused by reparenting - // it to the target display. - if (candidateTask.isRootTask()) { - final Task rootTask = candidateTask.getRootTask(); - rootTask.reparent(taskDisplayArea, true /* onTop */); - return rootTask; - } - } - - int windowingMode; - if (launchParams != null) { - // When launch params is not null, we always defer to its windowing mode. Sometimes - // it could be unspecified, which indicates it should inherit windowing mode from - // display. - windowingMode = launchParams.mWindowingMode; - } else { - windowingMode = options != null ? options.getLaunchWindowingMode() - : r.getWindowingMode(); - } - windowingMode = taskDisplayArea.validateWindowingMode(windowingMode, r, candidateTask); - - // Return the topmost valid root task on the display. - final int targetWindowingMode = windowingMode; - final Task topmostValidRootTask = taskDisplayArea.getRootTask(rootTask -> - isValidLaunchRootTask(rootTask, r, targetWindowingMode)); - if (topmostValidRootTask != null) { - return topmostValidRootTask; - } - - // If there is no valid root task on the secondary display area - check if new dynamic root - // task will do. - if (taskDisplayArea != getDisplayContent(taskDisplayArea.getDisplayId()) - .getDefaultTaskDisplayArea()) { - final int activityType = - options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED - ? options.getLaunchActivityType() : r.getActivityType(); - return taskDisplayArea.createRootTask( - windowingMode, activityType, true /*onTop*/, options); - } - - return null; - } - - // TODO: Can probably be consolidated into getLaunchRootTask()... - private boolean isValidLaunchRootTask(Task task, ActivityRecord r, int windowingMode) { - switch (task.getActivityType()) { - case ACTIVITY_TYPE_HOME: - return r.isActivityTypeHome(); - case ACTIVITY_TYPE_RECENTS: - return r.isActivityTypeRecents(); - case ACTIVITY_TYPE_ASSISTANT: - return r.isActivityTypeAssistant(); - case ACTIVITY_TYPE_DREAM: - return r.isActivityTypeDream(); - } - if (task.mCreatedByOrganizer) { - // Don't launch directly into task created by organizer...but why can't we? - return false; - } - // There is a 1-to-1 relationship between root task and task when not in - // primary split-windowing mode. - if (task.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY - && r.supportsSplitScreenWindowingModeInDisplayArea(task.getDisplayArea()) - && (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY - || windowingMode == WINDOWING_MODE_UNDEFINED)) { - return true; - } - return false; - } - int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task task) { // Preference is given to the activity type for the activity then the task since the type diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index f0cca18eca99..2f50b14968d5 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -941,36 +941,32 @@ final class TaskDisplayArea extends DisplayArea { Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop, @Nullable Task candidateTask, @Nullable Task sourceTask, @Nullable ActivityOptions options, int launchFlags) { + final int resolvedWindowingMode = + windowingMode == WINDOWING_MODE_UNDEFINED ? getWindowingMode() : windowingMode; // Need to pass in a determined windowing mode to see if a new root task should be created, // so use its parent's windowing mode if it is undefined. - if (!alwaysCreateRootTask( - windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : getWindowingMode(), - activityType)) { - Task rootTask = getRootTask(windowingMode, activityType); + if (!alwaysCreateRootTask(resolvedWindowingMode, activityType)) { + Task rootTask = getRootTask(resolvedWindowingMode, activityType); if (rootTask != null) { return rootTask; } } else if (candidateTask != null) { final int position = onTop ? POSITION_TOP : POSITION_BOTTOM; - final Task launchRootTask = getLaunchRootTask(windowingMode, activityType, options, - sourceTask, launchFlags); + final Task launchRootTask = getLaunchRootTask(resolvedWindowingMode, activityType, + options, sourceTask, launchFlags); if (launchRootTask != null) { if (candidateTask.getParent() == null) { launchRootTask.addChild(candidateTask, position); } else if (candidateTask.getParent() != launchRootTask) { candidateTask.reparent(launchRootTask, position); } - } else if (candidateTask.getDisplayArea() != this || !candidateTask.isRootTask()) { + } else if (candidateTask.getDisplayArea() != this) { if (candidateTask.getParent() == null) { addChild(candidateTask, position); } else { candidateTask.reparent(this, onTop); } } - // Update windowing mode if necessary, e.g. moving a pinned task to fullscreen. - if (candidateTask.getWindowingMode() != windowingMode) { - candidateTask.setWindowingMode(windowingMode); - } return candidateTask.getRootTask(); } return new Task.Builder(mAtmService) diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index b8ceb4a4f421..9bb02710a5bc 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -157,12 +157,26 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // display. if (launchMode == WINDOWING_MODE_UNDEFINED && canInheritWindowingModeFromSource(display, source)) { - launchMode = source.getWindowingMode(); + // The source's windowing mode may be different from its task, e.g. activity is set + // to fullscreen and its task is pinned windowing mode when the activity is entering + // pip. + launchMode = source.getTask().getWindowingMode(); if (DEBUG) { appendLog("inherit-from-source=" + WindowConfiguration.windowingModeToString(launchMode)); } } + // If the launch windowing mode is still undefined, inherit from the target task if the + // task is already on the right display area (otherwise, the task may be on a different + // display area that has incompatible windowing mode). + if (launchMode == WINDOWING_MODE_UNDEFINED + && task != null && task.getTaskDisplayArea() == suggestedDisplayArea) { + launchMode = task.getWindowingMode(); + if (DEBUG) { + appendLog("inherit-from-task=" + + WindowConfiguration.windowingModeToString(launchMode)); + } + } // hasInitialBounds is set if either activity options or layout has specified bounds. If // that's set we'll skip some adjustments later to avoid overriding the initial bounds. boolean hasInitialBounds = false; diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index 87abc53bfc5a..16c5bfec76ae 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -925,14 +925,10 @@ public class ActivityStarterTests extends WindowTestsBase { any(), anyBoolean(), anyBoolean(), eq(false)); } - private ActivityRecord createSingleTaskActivityOn(Task stack) { + private ActivityRecord createSingleTaskActivityOn(Task task) { final ComponentName componentName = ComponentName.createRelative( DEFAULT_COMPONENT_PACKAGE_NAME, DEFAULT_COMPONENT_PACKAGE_NAME + ".SingleTaskActivity"); - final Task task = new TaskBuilder(mSupervisor) - .setComponent(componentName) - .setParentTaskFragment(stack) - .build(); return new ActivityBuilder(mAtm) .setComponent(componentName) .setLaunchMode(LAUNCH_SINGLE_TASK) diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index ba6510440747..acceadf8c499 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -938,7 +938,33 @@ public class RootWindowContainerTests extends WindowTestsBase { } @Test - public void testGetValidLaunchRootTaskOnDisplayWithCandidateRootTask() { + public void testGetLaunchRootTaskOnSecondaryTaskDisplayArea() { + // Adding another TaskDisplayArea to the default display. + final DisplayContent display = mRootWindowContainer.getDefaultDisplay(); + final TaskDisplayArea taskDisplayArea = new TaskDisplayArea(display, + mWm, "TDA", FEATURE_VENDOR_FIRST); + display.addChild(taskDisplayArea, POSITION_BOTTOM); + + // Making sure getting the root task from the preferred TDA + LaunchParamsController.LaunchParams launchParams = + new LaunchParamsController.LaunchParams(); + launchParams.mPreferredTaskDisplayArea = taskDisplayArea; + Task root = mRootWindowContainer.getLaunchRootTask(null /* r */, null /* options */, + null /* candidateTask */, null /* sourceTask */, true /* onTop */, launchParams, + 0 /* launchParams */); + assertEquals(taskDisplayArea, root.getTaskDisplayArea()); + + // Making sure still getting the root task from the preferred TDA when passing in a + // launching activity. + ActivityRecord r = new ActivityBuilder(mAtm).build(); + root = mRootWindowContainer.getLaunchRootTask(r, null /* options */, + null /* candidateTask */, null /* sourceTask */, true /* onTop */, launchParams, + 0 /* launchParams */); + assertEquals(taskDisplayArea, root.getTaskDisplayArea()); + } + + @Test + public void testGetOrCreateRootTaskOnDisplayWithCandidateRootTask() { // Create a root task with an activity on secondary display. final TestDisplayContent secondaryDisplay = new TestDisplayContent.Builder(mAtm, 300, 600).build(); @@ -947,9 +973,9 @@ public class RootWindowContainerTests extends WindowTestsBase { final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build(); // Make sure the root task is valid and can be reused on default display. - final Task rootTask = mRootWindowContainer.getValidLaunchRootTaskInTaskDisplayArea( - mRootWindowContainer.getDefaultTaskDisplayArea(), activity, task, - null /* options */, null /* launchParams */); + final Task rootTask = mRootWindowContainer.getDefaultTaskDisplayArea().getOrCreateRootTask( + activity, null /* options */, task, null /* sourceTask */, null /* launchParams */, + 0 /* launchFlags */, ACTIVITY_TYPE_STANDARD, true /* onTop */); assertEquals(task, rootTask); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index 168c250a8c93..c0759c110039 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -575,7 +575,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { final TestDisplayContent fullscreenDisplay = createNewDisplayContent( WINDOWING_MODE_FULLSCREEN); final ActivityRecord source = createSourceActivity(fullscreenDisplay); - source.setWindowingMode(WINDOWING_MODE_FREEFORM); + source.getTask().setWindowingMode(WINDOWING_MODE_FREEFORM); assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setSource(source).calculate()); @@ -951,7 +951,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { final TestDisplayContent fullscreenDisplay = createNewDisplayContent( WINDOWING_MODE_FULLSCREEN); final ActivityRecord source = createSourceActivity(fullscreenDisplay); - source.setWindowingMode(WINDOWING_MODE_FREEFORM); + source.getTask().setWindowingMode(WINDOWING_MODE_FREEFORM); final ActivityOptions options = ActivityOptions.makeBasic(); final Rect expected = new Rect(0, 0, 150, 150); -- cgit v1.2.3-59-g8ed1b