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

Commit ae669f6e authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move desktop-first policy from Shell to LPM" into main

parents 6e011cf4 4719e35a
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -3641,13 +3641,19 @@ class DesktopTasksController(
                // If there is an active desk on the target display, then it is already in desktop
                // windowing so the new task should also be placed in desktop windowing.
                anyDeskActive -> true
                DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_TOP_FULLSCREEN_BUGFIX.isTrue ->
                DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_TOP_FULLSCREEN_BUGFIX.isTrue ||
                    DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_POLICY_IN_LPM.isTrue ->
                    // Here we have no desk activated, but check if we really want to force a task
                    // into desktop.
                    if (rootTaskDisplayAreaOrganizer.isDisplayDesktopFirst(task.displayId)) {
                        if (DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_POLICY_IN_LPM.isTrue) {
                            // Fully trust the LPM's decision under desktop-first mode.
                            true
                        } else {
                            // In desktop-first mode, we force to activate desk only when the
                            // desktop-first policy can be applied.
                            shouldForceEnterDesktop
                        }
                    } else {
                        // In touch-first mode, new tasks should be forced into desktop, while known
                        // desktop tasks should be moved outside of desktop.
@@ -3949,6 +3955,12 @@ class DesktopTasksController(

        val repository = userRepositories.getProfile(openingTask.userId)
        val isDesktopFirst = rootTaskDisplayAreaOrganizer.isDisplayDesktopFirst(targetDisplayId)
        if (DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_POLICY_IN_LPM.isTrue && isDesktopFirst) {
            // The desktop-first policy has to be considered already in
            // `DesktopModeLaunchParamsModifier`.
            return false
        }

        if (DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_TOP_FULLSCREEN_BUGFIX.isTrue) {
            val anyDeskActive = repository.isAnyDeskActive(targetDisplayId)
            val focusedTask = focusTransitionObserver.getFocusedTaskOnDisplay(targetDisplayId)
+27 −2
Original line number Diff line number Diff line
@@ -5739,7 +5739,10 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    @DisableFlags(
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM,
    )
    fun handleRequest_fullscreenTask_noTasks_enforceDesktop_freeformDisplay_returnFreeformWCT() {
        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(null)
        desktopState.enterDesktopByDefaultOnFreeformDisplay = true
@@ -5766,6 +5769,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
    )
    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM)
    fun handleRequest_fullscreenTask_noInDesk_enforceDesktop_freeformDisplay_movesToDesk() {
        val deskId = 0
        taskRepository.setDeskInactive(deskId)
@@ -5787,13 +5791,13 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        Flags.FLAG_ENABLE_DESKTOP_FIRST_BASED_DEFAULT_TO_DESKTOP_BUGFIX,
    )
    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM)
    fun handleRequest_fullscreenTask_noInDesk_enforceDesktop_freeformDisplay_movesToDesk_desktopFirst() {
        // Ensure the force enter desktop works when the deprecated flag is off.
        desktopState.enterDesktopByDefaultOnFreeformDisplay = false
        val deskId = 0
        taskRepository.setDeskInactive(deskId)
        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(null)
        desktopState.enterDesktopByDefaultOnFreeformDisplay = true
        val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
        tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM

@@ -5809,6 +5813,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
    )
    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM)
    fun handleRequest_fullscreenTask_noInDesk_enforceDesktop_secondaryDisplay_movesToDesk() {
        val deskId = 5
        taskRepository.addDesk(displayId = SECONDARY_DISPLAY_ID, deskId = deskId)
@@ -5834,6 +5839,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        Flags.FLAG_ENABLE_DESKTOP_FIRST_BASED_DEFAULT_TO_DESKTOP_BUGFIX,
        Flags.FLAG_ENABLE_DESKTOP_FIRST_TOP_FULLSCREEN_BUGFIX,
    )
    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM)
    fun handleRequest_fullscreenTask_fullscreenFocused_freeformDisplay_returnNull() {
        val deskId = 0
        taskRepository.setDeskInactive(deskId)
@@ -5850,6 +5856,25 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        assertThat(controller.handleRequest(Binder(), createTransition(fullscreenTask))).isNull()
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
        Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND,
        Flags.FLAG_ENABLE_DESKTOP_FIRST_BASED_DEFAULT_TO_DESKTOP_BUGFIX,
        Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM,
    )
    fun handleRequest_fullscreenTask_noInDesk_enforceDesktop_desktopFirst_returnNull() {
        val deskId = 0
        taskRepository.setDeskInactive(deskId)
        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(null)
        desktopState.enterDesktopByDefaultOnFreeformDisplay = true
        val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
        tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM

        val fullscreenTask = createFullscreenTask()
        assertThat(controller.handleRequest(Binder(), createTransition(fullscreenTask))).isNull()
    }

    @Test
    fun handleRequest_fullscreenTask_notInDesk_enforceDesktop_fullscreenDisplay_returnNull() {
        taskRepository.setDeskInactive(deskId = 0)
+94 −8
Original line number Diff line number Diff line
@@ -134,13 +134,27 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
            }
        }

        boolean forcedFreeformByDesktopFirstPolicy = shouldApplyDesktopFirstWindowingModePolicy(
                task, source, options, suggestedDisplayArea, currentParams);
        if (forcedFreeformByDesktopFirstPolicy) {
            outParams.mWindowingMode = WINDOWING_MODE_FREEFORM;
            if (task == null) {
                // Windowing mode is resolved by desktop-first policy but not ready to resolve
                // bounds since task is null, return RESULT_DONE to prevent other modifiers from
                // overwriting the params.
                return RESULT_DONE;
            }
            hasLaunchWindowingMode = true;
        }

        if (task == null || !task.isAttached()) {
            appendLog("task null, skipping");
            return RESULT_SKIP;
        }

        if (DesktopModeFlags.DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX.isTrue()
                && !isEnteringDesktopMode(task, options, currentParams)) {
                && !isEnteringDesktopMode(task, source, options, suggestedDisplayArea,
                currentParams)) {
            appendLog("not entering desktop mode, skipping");
            return RESULT_SKIP;
        }
@@ -199,6 +213,9 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
            // Copy over any values.
            outParams.set(currentParams);
            outParams.mPreferredTaskDisplayArea = suggestedDisplayArea;
            if (forcedFreeformByDesktopFirstPolicy) {
                outParams.mWindowingMode = WINDOWING_MODE_FREEFORM;
            }
        }

        boolean isFullscreenInDeskTask = inDesktopFirstContainer && requestFullscreen;
@@ -209,7 +226,8 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
            requestFullscreen |= task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
            isFullscreenInDeskTask = inDesktopFirstContainer && requestFullscreen;
            if (DesktopModeFlags.DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX.isTrue()
                    && isEnteringDesktopMode(sourceTask, options, currentParams)
                    && isEnteringDesktopMode(sourceTask, source, options, suggestedDisplayArea,
                    currentParams)
                    && !isFullscreenInDeskTask) {
                // If trampoline source is not freeform but we are entering or in desktop mode,
                // ignore the source windowing mode and set the windowing mode to freeform.
@@ -304,8 +322,32 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
    @VisibleForTesting
    boolean isEnteringDesktopMode(
            @NonNull Task task,
            @Nullable ActivityRecord source,
            @Nullable ActivityOptions options,
            @NonNull TaskDisplayArea taskDisplayArea,
            @NonNull LaunchParamsController.LaunchParams currentParams) {
        if (isRequestingFreeformWindowMode(task, options, currentParams)) {
            // It's launching in freeform without any modifications.
            return true;
        }

        if (!checkSourceWindowModesCompatible(task, options, currentParams)) {
            // It's launching in incompatible mode.
            return false;
        }

        if (shouldApplyDesktopFirstWindowingModePolicy(task, source, options, taskDisplayArea,
                currentParams)) {
            // It's a target of desktop-first policy.
            return true;
        }

        if (DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_POLICY_IN_LPM.isTrue()
                && taskDisplayArea.inFreeformWindowingMode()) {
            // The display is in desktop-first mode but non-freeform mode is requested.
            return false;
        }

        //  As freeform tasks cannot exist outside of desktop mode, it is safe to assume if
        //  freeform tasks are visible we are in desktop mode and as a result any launching
        //  activity will also enter desktop mode. On this same relationship, we can also assume
@@ -313,9 +355,7 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
        //  will force the device into desktop mode.
        final Task visibleFreeformTask = task.getDisplayContent().getTask(
                t -> t.inFreeformWindowingMode() && t.isVisibleRequested());
        return (visibleFreeformTask != null
                    && checkSourceWindowModesCompatible(task, options, currentParams))
                || isRequestingFreeformWindowMode(task, options, currentParams);
        return visibleFreeformTask != null;
    }

    private boolean isRequestingFreeformWindowMode(
@@ -328,16 +368,62 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
                && !DesktopExperienceFlags.IGNORE_CURRENT_PARAMS_IN_DESKTOP_LAUNCH_PARAMS.isTrue());
    }

    /**
     * Modify windowing mode of LaunchParams according to the desktop-first policy. Returns true if
     * the policy is applied.
     */
    private boolean shouldApplyDesktopFirstWindowingModePolicy(
            @Nullable Task task,
            @Nullable ActivityRecord source,
            @Nullable ActivityOptions options,
            @NonNull TaskDisplayArea taskDisplayArea,
            @NonNull LaunchParamsController.LaunchParams currentParams) {
        if (!DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_POLICY_IN_LPM.isTrue()) {
            return false;
        }

        if (!taskDisplayArea.inFreeformWindowingMode()) {
            // The display is in touch-first mode.
            return false;
        }

        if (!checkSourceWindowModesCompatible(task, options, currentParams)) {
            // The task is launching in incompatible mode (e.g., PIP).
            appendLog("desktop-first-but-incompatible-mode");
            return false;
        }

        final boolean hasLaunchWindowingModeOption = options != null
                && options.getLaunchWindowingMode() != WINDOWING_MODE_UNDEFINED;
        if (hasLaunchWindowingModeOption) {
            // ActivityOptions comes first.
            appendLog("desktop-first-but-has-launch-windowing-mode-options");
            return false;
        }

        final boolean isFullscreenRelaunch = source != null && source.getTask() != null
                && source.getTask().getWindowingMode() == WINDOWING_MODE_FULLSCREEN
                && source.getTask() == task;
        if (isFullscreenRelaunch) {
            // Fullscreen relaunch is not a target of desktop-first policy.
            appendLog("desktop-first-but-fullscreen-relaunch");
            return false;
        }

        appendLog("forced-freeform-in-desktop-first");
        return true;
    }

    /**
     * Returns true is all possible source window modes are compatible with desktop mode.
     */
    private boolean checkSourceWindowModesCompatible(
            @NonNull Task task,
            @Nullable Task task,
            @Nullable ActivityOptions options,
            @NonNull LaunchParamsController.LaunchParams currentParams) {
        // 1. Check the task's own windowing mode.
        final boolean isTaskWindowModeCompatible =
                isCompatibleDesktopWindowingMode(task.getWindowingMode());
        final boolean isTaskWindowModeCompatible = task == null
                || isCompatibleDesktopWindowingMode(task.getWindowingMode());
        // 2. Check the windowing mode from ActivityOptions, if they exist.
        // If options are null, we consider it compatible.
        final boolean isOptionsWindowModeCompatible = options == null
+113 −8
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ public class DesktopModeLaunchParamsModifierTests extends
        Context spyContext = spy(mContext);
        mTarget = spy(new DesktopModeLaunchParamsModifier(spyContext, mSupervisor,
                new DesktopModeCompatPolicy(spyContext)));
        doReturn(true).when(mTarget).isEnteringDesktopMode(any(), any(), any());
        doReturn(true).when(mTarget).isEnteringDesktopMode(any(), any(), any(), any(), any());
        doReturn(HOME_ACTIVITIES).when(mPackageManager).getHomeActivities(any());
        doReturn(mPackageManager).when(spyContext).getPackageManager();
    }
@@ -176,7 +176,7 @@ public class DesktopModeLaunchParamsModifierTests extends
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsSkipIfIsEnteringDesktopModeFalse() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenReturn(false);
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenReturn(false);

        final Task task = new TaskBuilder(mSupervisor).build();

@@ -188,7 +188,7 @@ public class DesktopModeLaunchParamsModifierTests extends
            Flags.FLAG_RESPECT_FULLSCREEN_ACTIVITY_OPTION_IN_DESKTOP_LAUNCH_PARAMS})
    public void testAppliesFullscreenAndReturnDoneIfRequestViaActivityOptions() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenReturn(true);
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenReturn(true);

        final Task task = new TaskBuilder(mSupervisor).build();
        final ActivityOptions options = ActivityOptions.makeBasic();
@@ -365,7 +365,7 @@ public class DesktopModeLaunchParamsModifierTests extends
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsContinueIfFreeformTaskExists() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenCallRealMethod();
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenCallRealMethod();

        final DisplayContent dc = spy(createNewDisplay());
        final Task existingFreeformTask = new TaskBuilder(mSupervisor).setCreateActivity(true)
@@ -383,7 +383,7 @@ public class DesktopModeLaunchParamsModifierTests extends
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsContinueIfTaskInFreeform() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenCallRealMethod();
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenCallRealMethod();

        final Task task = new TaskBuilder(mSupervisor).setWindowingMode(WINDOWING_MODE_FREEFORM)
                .build();
@@ -397,7 +397,7 @@ public class DesktopModeLaunchParamsModifierTests extends
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsContinueIfFreeformRequestViaActivityOptions() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenCallRealMethod();
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenCallRealMethod();

        final Task task = new TaskBuilder(mSupervisor).build();
        final ActivityOptions options = ActivityOptions.makeBasic();
@@ -412,7 +412,7 @@ public class DesktopModeLaunchParamsModifierTests extends
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsContinueIfFreeformRequestViaPreviousModifier() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenCallRealMethod();
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenCallRealMethod();

        final Task task = new TaskBuilder(mSupervisor).build();
        final ActivityOptions options = ActivityOptions.makeBasic();
@@ -1920,7 +1920,7 @@ public class DesktopModeLaunchParamsModifierTests extends
            Flags.FLAG_IGNORE_CURRENT_PARAMS_IN_DESKTOP_LAUNCH_PARAMS})
    public void testDoesntInheritWindowingModeFromCurrentParams() {
        setupDesktopModeLaunchParamsModifier();
        doCallRealMethod().when(mTarget).isEnteringDesktopMode(any(), any(), any());
        doCallRealMethod().when(mTarget).isEnteringDesktopMode(any(), any(), any(), any(), any());

        final Task task = new TaskBuilder(mSupervisor).setActivityType(
                ACTIVITY_TYPE_STANDARD).build();
@@ -1982,6 +1982,111 @@ public class DesktopModeLaunchParamsModifierTests extends
        assertEquals(emptyRect, mResult.mAppBounds);
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM,
            Flags.FLAG_ENABLE_FREEFORM_DISPLAY_LAUNCH_PARAMS})
    public void testCalculate_desktopFirstPolicy_forcesFreeform() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenCallRealMethod();

        final DisplayContent dc = createDisplayContent(ORIENTATION_LANDSCAPE,
                LANDSCAPE_DISPLAY_BOUNDS, WINDOWING_MODE_FREEFORM);
        final Task launchingTask = new TaskBuilder(mSupervisor)
                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                .setDisplay(dc)
                .build();

        assertEquals(RESULT_DONE,
                new CalculateRequestBuilder().setTask(launchingTask).calculate());
        assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode);
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM,
            Flags.FLAG_ENABLE_FREEFORM_DISPLAY_LAUNCH_PARAMS})
    public void testCalculate_desktopFirstPolicy_taskNull_forcesFreeform() {
        setupDesktopModeLaunchParamsModifier();

        final DisplayContent dc = createDisplayContent(ORIENTATION_LANDSCAPE,
                LANDSCAPE_DISPLAY_BOUNDS, WINDOWING_MODE_FREEFORM);
        final ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchDisplayId(dc.getDisplayId());

        // When task is null, getPreferredLaunchTaskDisplayArea will use the display from options.
        // Then forceFreeformByDesktopFirstPolicy will be true.
        // Because task is null, it should return RESULT_DONE.
        assertEquals(RESULT_DONE,
                new CalculateRequestBuilder().setTask(null).setOptions(options).calculate());
        assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode);
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM,
            Flags.FLAG_ENABLE_FREEFORM_DISPLAY_LAUNCH_PARAMS})
    public void testCalculate_desktopFirstPolicy_fullscreenRelaunch_bypassesPolicy() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenCallRealMethod();

        final DisplayContent dc = createDisplayContent(ORIENTATION_LANDSCAPE,
                LANDSCAPE_DISPLAY_BOUNDS, WINDOWING_MODE_FREEFORM);
        final Task launchingTask = new TaskBuilder(mSupervisor)
                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                .setDisplay(dc)
                .build();
        final ActivityRecord source = new ActivityBuilder(mAtm).setTask(launchingTask).build();

        // The task is launched by a different task on a desktop-first display.
        assertEquals(RESULT_SKIP,
                new CalculateRequestBuilder().setTask(launchingTask).setSource(source).calculate());
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM,
            Flags.FLAG_ENABLE_FREEFORM_DISPLAY_LAUNCH_PARAMS})
    public void testCalculate_desktopFirstPolicy_fullscreenSourceTask_forcesFreeform() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenCallRealMethod();

        final DisplayContent dc = createDisplayContent(ORIENTATION_LANDSCAPE,
                LANDSCAPE_DISPLAY_BOUNDS, WINDOWING_MODE_FREEFORM);
        final Task launchingTask = new TaskBuilder(mSupervisor)
                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                .setDisplay(dc)
                .build();
        final Task sourceTask = new TaskBuilder(mSupervisor)
                .setWindowingMode(WINDOWING_MODE_FREEFORM)
                .setDisplay(dc)
                .build();
        final ActivityRecord source = new ActivityBuilder(mAtm).setTask(sourceTask).build();

        // The task is launched by a different task on a desktop-first display.
        assertEquals(RESULT_DONE,
                new CalculateRequestBuilder().setTask(launchingTask).setSource(source).calculate());
        assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode);
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_FIRST_POLICY_IN_LPM,
            Flags.FLAG_ENABLE_FREEFORM_DISPLAY_LAUNCH_PARAMS})
    public void testCalculate_desktopFirstPolicy_requestFullscreen_bypassesPolicy() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any(), any(), any())).thenCallRealMethod();

        final DisplayContent dc = createDisplayContent(ORIENTATION_LANDSCAPE,
                LANDSCAPE_DISPLAY_BOUNDS, WINDOWING_MODE_FREEFORM);
        final Task launchingTask = new TaskBuilder(mSupervisor)
                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                .setDisplay(dc)
                .build();
        final ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);

        // The policy should be bypassed if fullscreen is requested.
        assertEquals(RESULT_SKIP,
                new CalculateRequestBuilder().setTask(launchingTask).setOptions(
                        options).calculate());
    }

    private Task createTask(DisplayContent display, boolean isResizeable) {
        final int resizeMode = isResizeable ? RESIZE_MODE_RESIZEABLE
                : RESIZE_MODE_UNRESIZEABLE;