diff options
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 ac5ed7b200f2..b9cd657da0e2 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<DisplayContent> 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<DisplayContent> 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<WindowContainer> { 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); |