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

Commit 6de3d810 authored by Garfield Tan's avatar Garfield Tan
Browse files

Let WM shell set launch display area per params

There are needs in foldables and new split screen to route new tasks
with certain activity type and windowing mode to specific display areas.
This CL fulfills this need.

Bug: 175140202
Test: atest TaskLaunchParamsModifierTests
Change-Id: Id42371ce0ccbfb00776dd9364d95292cdff56f4f
parent 1f6edbda
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -277,7 +277,8 @@ class LaunchParamsController {
        @interface Phase {}

        /**
         * Stops once we are done with preferred display calculation.
         * Stops once we are done with preferred display calculation. The result returned from this
         * phase is only guaranteed to have a display area which display is the launch display.
         */
        int PHASE_DISPLAY = 0;

@@ -286,10 +287,15 @@ class LaunchParamsController {
         */
        int PHASE_WINDOWING_MODE = 1;

        /**
         * Stops once we are done with display area calculation.
         */
        int PHASE_DISPLAY_AREA = 2;

        /**
         * Stops once we are done with window bounds calculation.
         */
        int PHASE_BOUNDS = 2;
        int PHASE_BOUNDS = 3;

        /**
         * Returns the launch params that the provided activity launch params should be overridden
+48 −11
Original line number Diff line number Diff line
@@ -89,6 +89,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
    private final Rect mTmpStableBounds = new Rect();
    private final int[] mTmpDirections = new int[2];

    private TaskDisplayArea mTmpDisplayArea;

    private StringBuilder mLogBuilder;

    TaskLaunchParamsModifier(ActivityTaskSupervisor supervisor) {
@@ -127,15 +129,15 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
            return RESULT_SKIP;
        }

        // STEP 1: Determine the display area to launch the activity/task.
        final TaskDisplayArea taskDisplayArea = getPreferredLaunchTaskDisplayArea(task,
        // STEP 1: Determine the suggested display area to launch the activity/task.
        final TaskDisplayArea suggestedDisplayArea = getPreferredLaunchTaskDisplayArea(task,
                options, source, currentParams, activity, request);
        outParams.mPreferredTaskDisplayArea = taskDisplayArea;
        // TODO(b/152116619): Update the usages of display to use taskDisplayArea below.
        final DisplayContent display = taskDisplayArea.mDisplayContent;
        outParams.mPreferredTaskDisplayArea = suggestedDisplayArea;
        final DisplayContent display = suggestedDisplayArea.mDisplayContent;
        if (DEBUG) {
            appendLog("task-display-area=" + outParams.mPreferredTaskDisplayArea
                    + " display-area-windowing-mode=" + taskDisplayArea.getWindowingMode());
            appendLog("display-id=" + display.getDisplayId()
                    + " display-windowing-mode=" + display.getWindowingMode()
                    + " suggested-display-area=" + suggestedDisplayArea);
        }

        if (phase == PHASE_DISPLAY) {
@@ -204,9 +206,11 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
        // We inherit launch params from previous modifiers or LaunchParamsController if options,
        // layout and display conditions are not contradictory to their suggestions. It's important
        // to carry over their values because LaunchParamsController doesn't automatically do that.
        // We only check if display matches because display area can be changed later.
        if (!currentParams.isEmpty() && !hasInitialBounds
                && (currentParams.mPreferredTaskDisplayArea == null
                    || currentParams.mPreferredTaskDisplayArea == taskDisplayArea)) {
                    || currentParams.mPreferredTaskDisplayArea.getDisplayId()
                        == display.getDisplayId())) {
            // Only set windowing mode if display is in freeform. If the display is in fullscreen
            // mode we should only launch a task in fullscreen mode.
            if (currentParams.hasWindowingMode() && display.inFreeformWindowingMode()) {
@@ -255,14 +259,47 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
            return RESULT_CONTINUE;
        }

        // STEP 3: Determine final launch bounds based on resolved windowing mode and activity
        // STEP 3: Finalize the display area. Here we allow WM shell route all launches that match
        // certain criteria to specific task display areas.
        final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
                : display.getWindowingMode();
        TaskDisplayArea taskDisplayArea = suggestedDisplayArea;
        // If launch task display area is set in options we should just use it. We assume the
        // suggestedDisplayArea has the right one in this case.
        if (options == null || options.getLaunchTaskDisplayArea() == null) {
            final int activityType =
                    mSupervisor.mRootWindowContainer.resolveActivityType(root, options, task);
            display.forAllTaskDisplayAreas(displayArea -> {
                final Task launchRoot = displayArea.getLaunchRootTask(resolvedMode, activityType);
                if (launchRoot == null) {
                    return false;
                }
                mTmpDisplayArea = displayArea;
                return true;
            });
            if (mTmpDisplayArea != null) {
                taskDisplayArea = mTmpDisplayArea;
                mTmpDisplayArea = null;
                appendLog("overridden-display-area=["
                        + WindowConfiguration.activityTypeToString(activityType) + ", "
                        + WindowConfiguration.windowingModeToString(resolvedMode) + ", "
                        + taskDisplayArea + "]");
            }
        }
        appendLog("display-area=" + taskDisplayArea);
        outParams.mPreferredTaskDisplayArea = taskDisplayArea;

        if (phase == PHASE_DISPLAY_AREA) {
            return RESULT_CONTINUE;
        }
        // TODO(b/152116619): Update the usages of display to use taskDisplayArea below.

        // STEP 4: Determine final launch bounds based on resolved windowing mode and activity
        // requested orientation. We set bounds to empty for fullscreen mode and keep bounds as is
        // for all other windowing modes that's not freeform mode. One can read comments in
        // relevant methods to further understand this step.
        //
        // We skip making adjustments if the params are fully resolved from previous results.
        final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
                : display.getWindowingMode();
        if (fullyResolvedCurrentParam) {
            if (resolvedMode == WINDOWING_MODE_FREEFORM) {
                // Make sure bounds are in the display if it's possibly in a different display/area.
+89 −13
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.wm;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -32,6 +33,7 @@ import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER_FIRST;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -113,9 +115,9 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
        assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setActivity(null).calculate());
    }

    // =============================
    // Display ID Related Tests
    // =============================
    // =======================
    // Display Related Tests
    // =======================
    @Test
    public void testDefaultToPrimaryDisplayArea() {
        createNewDisplayContent(WINDOWING_MODE_FREEFORM);
@@ -291,7 +293,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
        when(mActivity.getProcessName()).thenReturn(processName);
        when(mActivity.getUid()).thenReturn(uid);
        doReturn(controller)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(processName, uid);

        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -312,11 +314,11 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
        when(mActivity.getProcessName()).thenReturn(processName);
        when(mActivity.getUid()).thenReturn(uid);
        doReturn(null)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(processName, uid);

        doReturn(controller)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);

        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -344,10 +346,10 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
                .thenReturn(expectedTaskDisplayArea);

        doReturn(controllerForApplication)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(processName, uid);
        doReturn(controllerForLaunching)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);

        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -369,15 +371,15 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
        when(controller.getTopActivityDisplayArea()).thenReturn(expectedTaskDisplayArea);

        doReturn(null)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(mActivity.processName, mActivity.info.applicationInfo.uid);

        doReturn(null)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);

        doReturn(controller)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(request.realCallingPid, request.realCallingUid);

        assertEquals(RESULT_CONTINUE,
@@ -389,11 +391,11 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
    @Test
    public void testUsesDefaultDisplayAreaIfWindowProcessControllerIsNotPresent() {
        doReturn(null)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(mActivity.processName, mActivity.info.applicationInfo.uid);

        doReturn(null)
                .when(mSupervisor.mService)
                .when(mAtm)
                .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);

        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
@@ -401,6 +403,80 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
        assertEquals(DEFAULT_DISPLAY, mResult.mPreferredTaskDisplayArea.getDisplayId());
    }

    @Test
    public void testOverridesDisplayAreaWithStandardTypeAndFullscreenMode() {
        final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
                mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
        final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
        launchRoot.mCreatedByOrganizer = true;

        secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
                new int[] { ACTIVITY_TYPE_STANDARD });

        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());

        assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
    }

    @Test
    public void testOverridesDisplayAreaWithHomeTypeAndFullscreenMode() {
        final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
                mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
        final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
        launchRoot.mCreatedByOrganizer = true;

        mActivity.setActivityType(ACTIVITY_TYPE_HOME);
        secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
                new int[] { ACTIVITY_TYPE_HOME });

        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());

        assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
    }

    @Test
    public void testOverridesDisplayAreaWithStandardTypeAndFreeformMode() {
        final TestDisplayContent freeformDisplay = createNewDisplayContent(
                WINDOWING_MODE_FREEFORM);
        final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(freeformDisplay,
                mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
        final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
        launchRoot.mCreatedByOrganizer = true;

        secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FREEFORM },
                new int[] { ACTIVITY_TYPE_STANDARD });

        mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());

        assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
    }

    @Test
    public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayArea() {
        final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
                mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
        final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
        launchRoot.mCreatedByOrganizer = true;

        secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
                new int[] { ACTIVITY_TYPE_STANDARD });

        ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchTaskDisplayArea(
                mDefaultDisplay.getDefaultTaskDisplayArea().mRemoteToken.toWindowContainerToken());

        assertEquals(RESULT_CONTINUE,
                new CalculateRequestBuilder().setOptions(options).calculate());

        assertEquals(
                mDefaultDisplay.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea);
    }

    // =====================================
    // Launch Windowing Mode Related Tests
    // =====================================