Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +16 −4 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +27 −2 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) Loading @@ -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 Loading @@ -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) Loading @@ -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) Loading @@ -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) Loading services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java +94 −8 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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; Loading @@ -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. Loading Loading @@ -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 Loading @@ -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( Loading @@ -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 Loading services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java +113 −8 Original line number Diff line number Diff line Loading @@ -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(); } Loading Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -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) Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +16 −4 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +27 −2 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) Loading @@ -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 Loading @@ -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) Loading @@ -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) Loading @@ -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) Loading
services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java +94 −8 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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; Loading @@ -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. Loading Loading @@ -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 Loading @@ -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( Loading @@ -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 Loading
services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java +113 −8 Original line number Diff line number Diff line Loading @@ -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(); } Loading Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -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) Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -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(); Loading Loading @@ -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; Loading