Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbcd3435 authored by Louis Chang's avatar Louis Chang
Browse files

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
parent 038fd80c
Loading
Loading
Loading
Loading
+7 −128
Original line number Diff line number Diff line
@@ -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,
            return 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
@@ -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
+7 −11
Original line number Diff line number Diff line
@@ -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)
+15 −1
Original line number Diff line number Diff line
@@ -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;
+1 −5
Original line number Diff line number Diff line
@@ -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)
+30 −4
Original line number Diff line number Diff line
@@ -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);
    }

Loading