Merge "Removing RWC#getValidLaunchRootTaskInTaskDisplayArea" into tm-dev

This commit is contained in:
Louis Chang
2022-02-24 14:57:30 +00:00
committed by Android (Google) Code Review
6 changed files with 62 additions and 151 deletions

View File

@@ -18,15 +18,9 @@ package com.android.server.wm;
import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER; 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_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 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.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -2791,35 +2785,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
Task rootTask = null; Task rootTask = null;
// Next preference for root task goes to the taskDisplayArea candidate. // 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; taskDisplayArea = launchParams.mPreferredTaskDisplayArea;
} }
if (taskDisplayArea == null && displayId != INVALID_DISPLAY
if (taskDisplayArea == null && displayId != INVALID_DISPLAY) { && canLaunchOnDisplay(r, displayId)) {
final DisplayContent displayContent = getDisplayContent(displayId); taskDisplayArea = getDisplayContent(displayId).getDefaultTaskDisplayArea();
if (displayContent != null) {
taskDisplayArea = displayContent.getDefaultTaskDisplayArea();
}
} }
if (taskDisplayArea != null) { if (taskDisplayArea != null) {
final int tdaDisplayId = taskDisplayArea.getDisplayId(); return taskDisplayArea.getOrCreateRootTask(r, options, candidateTask,
if (canLaunchOnDisplay(r, tdaDisplayId)) { sourceTask, launchParams, launchFlags, activityType, onTop);
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;
}
}
} }
// Give preference to the root task and display of the input task and activity if they // 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); 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, int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
@Nullable Task task) { @Nullable Task task) {
// Preference is given to the activity type for the activity then the task since the type // Preference is given to the activity type for the activity then the task since the type

View File

@@ -941,36 +941,32 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop, Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop,
@Nullable Task candidateTask, @Nullable Task sourceTask, @Nullable Task candidateTask, @Nullable Task sourceTask,
@Nullable ActivityOptions options, int launchFlags) { @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, // 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. // so use its parent's windowing mode if it is undefined.
if (!alwaysCreateRootTask( if (!alwaysCreateRootTask(resolvedWindowingMode, activityType)) {
windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : getWindowingMode(), Task rootTask = getRootTask(resolvedWindowingMode, activityType);
activityType)) {
Task rootTask = getRootTask(windowingMode, activityType);
if (rootTask != null) { if (rootTask != null) {
return rootTask; return rootTask;
} }
} else if (candidateTask != null) { } else if (candidateTask != null) {
final int position = onTop ? POSITION_TOP : POSITION_BOTTOM; final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
final Task launchRootTask = getLaunchRootTask(windowingMode, activityType, options, final Task launchRootTask = getLaunchRootTask(resolvedWindowingMode, activityType,
sourceTask, launchFlags); options, sourceTask, launchFlags);
if (launchRootTask != null) { if (launchRootTask != null) {
if (candidateTask.getParent() == null) { if (candidateTask.getParent() == null) {
launchRootTask.addChild(candidateTask, position); launchRootTask.addChild(candidateTask, position);
} else if (candidateTask.getParent() != launchRootTask) { } else if (candidateTask.getParent() != launchRootTask) {
candidateTask.reparent(launchRootTask, position); candidateTask.reparent(launchRootTask, position);
} }
} else if (candidateTask.getDisplayArea() != this || !candidateTask.isRootTask()) { } else if (candidateTask.getDisplayArea() != this) {
if (candidateTask.getParent() == null) { if (candidateTask.getParent() == null) {
addChild(candidateTask, position); addChild(candidateTask, position);
} else { } else {
candidateTask.reparent(this, onTop); 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 candidateTask.getRootTask();
} }
return new Task.Builder(mAtmService) return new Task.Builder(mAtmService)

View File

@@ -157,12 +157,26 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// display. // display.
if (launchMode == WINDOWING_MODE_UNDEFINED if (launchMode == WINDOWING_MODE_UNDEFINED
&& canInheritWindowingModeFromSource(display, source)) { && 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) { if (DEBUG) {
appendLog("inherit-from-source=" appendLog("inherit-from-source="
+ WindowConfiguration.windowingModeToString(launchMode)); + 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 // 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. // that's set we'll skip some adjustments later to avoid overriding the initial bounds.
boolean hasInitialBounds = false; boolean hasInitialBounds = false;

View File

@@ -925,14 +925,10 @@ public class ActivityStarterTests extends WindowTestsBase {
any(), anyBoolean(), anyBoolean(), eq(false)); any(), anyBoolean(), anyBoolean(), eq(false));
} }
private ActivityRecord createSingleTaskActivityOn(Task stack) { private ActivityRecord createSingleTaskActivityOn(Task task) {
final ComponentName componentName = ComponentName.createRelative( final ComponentName componentName = ComponentName.createRelative(
DEFAULT_COMPONENT_PACKAGE_NAME, DEFAULT_COMPONENT_PACKAGE_NAME,
DEFAULT_COMPONENT_PACKAGE_NAME + ".SingleTaskActivity"); DEFAULT_COMPONENT_PACKAGE_NAME + ".SingleTaskActivity");
final Task task = new TaskBuilder(mSupervisor)
.setComponent(componentName)
.setParentTaskFragment(stack)
.build();
return new ActivityBuilder(mAtm) return new ActivityBuilder(mAtm)
.setComponent(componentName) .setComponent(componentName)
.setLaunchMode(LAUNCH_SINGLE_TASK) .setLaunchMode(LAUNCH_SINGLE_TASK)

View File

@@ -938,7 +938,33 @@ public class RootWindowContainerTests extends WindowTestsBase {
} }
@Test @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. // Create a root task with an activity on secondary display.
final TestDisplayContent secondaryDisplay = new TestDisplayContent.Builder(mAtm, 300, final TestDisplayContent secondaryDisplay = new TestDisplayContent.Builder(mAtm, 300,
600).build(); 600).build();
@@ -947,9 +973,9 @@ public class RootWindowContainerTests extends WindowTestsBase {
final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build(); final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
// Make sure the root task is valid and can be reused on default display. // Make sure the root task is valid and can be reused on default display.
final Task rootTask = mRootWindowContainer.getValidLaunchRootTaskInTaskDisplayArea( final Task rootTask = mRootWindowContainer.getDefaultTaskDisplayArea().getOrCreateRootTask(
mRootWindowContainer.getDefaultTaskDisplayArea(), activity, task, activity, null /* options */, task, null /* sourceTask */, null /* launchParams */,
null /* options */, null /* launchParams */); 0 /* launchFlags */, ACTIVITY_TYPE_STANDARD, true /* onTop */);
assertEquals(task, rootTask); assertEquals(task, rootTask);
} }

View File

@@ -575,7 +575,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
final TestDisplayContent fullscreenDisplay = createNewDisplayContent( final TestDisplayContent fullscreenDisplay = createNewDisplayContent(
WINDOWING_MODE_FULLSCREEN); WINDOWING_MODE_FULLSCREEN);
final ActivityRecord source = createSourceActivity(fullscreenDisplay); final ActivityRecord source = createSourceActivity(fullscreenDisplay);
source.setWindowingMode(WINDOWING_MODE_FREEFORM); source.getTask().setWindowingMode(WINDOWING_MODE_FREEFORM);
assertEquals(RESULT_CONTINUE, assertEquals(RESULT_CONTINUE,
new CalculateRequestBuilder().setSource(source).calculate()); new CalculateRequestBuilder().setSource(source).calculate());
@@ -951,7 +951,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
final TestDisplayContent fullscreenDisplay = createNewDisplayContent( final TestDisplayContent fullscreenDisplay = createNewDisplayContent(
WINDOWING_MODE_FULLSCREEN); WINDOWING_MODE_FULLSCREEN);
final ActivityRecord source = createSourceActivity(fullscreenDisplay); final ActivityRecord source = createSourceActivity(fullscreenDisplay);
source.setWindowingMode(WINDOWING_MODE_FREEFORM); source.getTask().setWindowingMode(WINDOWING_MODE_FREEFORM);
final ActivityOptions options = ActivityOptions.makeBasic(); final ActivityOptions options = ActivityOptions.makeBasic();
final Rect expected = new Rect(0, 0, 150, 150); final Rect expected = new Rect(0, 0, 150, 150);