Loading libs/WindowManager/Shell/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -148,4 +148,7 @@ <!-- Whether pointer pilfer is required to start back animation. --> <bool name="config_backAnimationRequiresPointerPilfer">true</bool> <!-- Whether desktop mode is supported on the current device --> <bool name="config_isDesktopModeSupported">false</bool> </resources> libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java +23 −14 Original line number Diff line number Diff line Loading @@ -16,13 +16,13 @@ package com.android.wm.shell.desktopmode; import static android.content.res.Configuration.SCREENLAYOUT_SIZE_XLARGE; import android.annotation.NonNull; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; import android.os.SystemProperties; import com.android.internal.annotations.VisibleForTesting; import com.android.window.flags.Flags; import com.android.wm.shell.R; /** * Constants for desktop mode feature Loading Loading @@ -70,8 +70,11 @@ public class DesktopModeStatus { private static final boolean USE_ROUNDED_CORNERS = SystemProperties.getBoolean( "persist.wm.debug.desktop_use_rounded_corners", true); private static final boolean ENFORCE_DISPLAY_RESTRICTIONS = SystemProperties.getBoolean( "persist.wm.debug.desktop_mode_enforce_display_restrictions", true); /** * Flag to indicate whether to restrict desktop mode to supported devices. */ private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean( "persist.wm.debug.desktop_mode_enforce_device_restrictions", true); /** * Return {@code true} if desktop windowing is enabled Loading Loading @@ -113,19 +116,25 @@ public class DesktopModeStatus { } /** * Return whether the display size restrictions should be enforced. * Return {@code true} if desktop mode should be restricted to supported devices. */ @VisibleForTesting public static boolean enforceDeviceRestrictions() { return ENFORCE_DEVICE_RESTRICTIONS; } /** * Return {@code true} if the current device supports desktop mode. */ public static boolean enforceDisplayRestrictions() { return ENFORCE_DISPLAY_RESTRICTIONS; @VisibleForTesting public static boolean isDesktopModeSupported(@NonNull Context context) { return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported); } /** * Return {@code true} if the display associated with the task is at least of size * {@link android.content.res.Configuration#SCREENLAYOUT_SIZE_XLARGE} or has been overridden to * ignore the size constraint. * Return {@code true} if desktop mode can be entered on the current device. */ public static boolean meetsMinimumDisplayRequirements(@NonNull RunningTaskInfo taskInfo) { return !enforceDisplayRestrictions() || taskInfo.configuration.isLayoutSizeAtLeast(SCREENLAYOUT_SIZE_XLARGE); public static boolean canEnterDesktopMode(@NonNull Context context) { return !enforceDeviceRestrictions() || isDesktopModeSupported(context); } } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +1 −1 Original line number Diff line number Diff line Loading @@ -306,7 +306,7 @@ class DesktopTasksController( task: RunningTaskInfo, wct: WindowContainerTransaction = WindowContainerTransaction() ) { if (!DesktopModeStatus.meetsMinimumDisplayRequirements(task)) { if (!DesktopModeStatus.canEnterDesktopMode(context)) { KtProtoLog.w( WM_SHELL_DESKTOP_MODE, "DesktopTasksController: Cannot enter desktop, " + "display does not meet minimum size requirements") Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +1 −1 Original line number Diff line number Diff line Loading @@ -1052,7 +1052,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD && !taskInfo.configuration.windowConfiguration.isAlwaysOnTop() && DesktopModeStatus.meetsMinimumDisplayRequirements(taskInfo); && DesktopModeStatus.canEnterDesktopMode(mContext); } private void createWindowDecoration( Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +17 −14 Original line number Diff line number Diff line Loading @@ -23,8 +23,6 @@ import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED import android.content.res.Configuration.SCREENLAYOUT_SIZE_NORMAL import android.content.res.Configuration.SCREENLAYOUT_SIZE_XLARGE import android.os.Binder import android.testing.AndroidTestingRunner import android.view.Display.DEFAULT_DISPLAY Loading @@ -38,6 +36,7 @@ import android.window.TransitionRequestInfo import android.window.WindowContainerTransaction import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.dx.mockito.inline.extended.ExtendedMockito.never import com.android.dx.mockito.inline.extended.StaticMockitoSession Loading Loading @@ -89,6 +88,7 @@ import org.mockito.Mockito.anyInt import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.quality.Strictness @SmallTest @RunWith(AndroidTestingRunner::class) Loading Loading @@ -126,7 +126,8 @@ class DesktopTasksControllerTest : ShellTestCase() { @Before fun setUp() { mockitoSession = mockitoSession().spyStatic(DesktopModeStatus::class.java).startMocking() mockitoSession = mockitoSession().strictness(Strictness.LENIENT) .spyStatic(DesktopModeStatus::class.java).startMocking() whenever(DesktopModeStatus.isEnabled()).thenReturn(true) shellInit = Mockito.spy(ShellInit(testExecutor)) Loading Loading @@ -335,25 +336,25 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test fun moveToDesktop_screenSizeBelowXLarge_doesNothing() { fun moveToDesktop_deviceNotSupported_doesNothing() { val task = setUpFullscreenTask() // Update screen layout to be below minimum size task.configuration.screenLayout = SCREENLAYOUT_SIZE_NORMAL // Simulate non compatible device doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } controller.moveToDesktop(task) verifyWCTNotExecuted() } @Test fun moveToDesktop_screenSizeBelowXLarge_displayRestrictionsOverridden_taskIsMovedToDesktop() { fun moveToDesktop_deviceNotSupported_deviceRestrictionsOverridden_taskIsMovedToDesktop() { val task = setUpFullscreenTask() // Update screen layout to be below minimum size task.configuration.screenLayout = SCREENLAYOUT_SIZE_NORMAL // Simulate non compatible device doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } // Simulate enforce display restrictions system property overridden to false whenever(DesktopModeStatus.enforceDisplayRestrictions()).thenReturn(false) // Simulate enforce device restrictions system property overridden to false whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(false) controller.moveToDesktop(task) Loading @@ -363,7 +364,7 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test fun moveToDesktop_screenSizeXLarge_taskIsMovedToDesktop() { fun moveToDesktop_deviceSupported_taskIsMovedToDesktop() { val task = setUpFullscreenTask() controller.moveToDesktop(task) Loading Loading @@ -874,7 +875,8 @@ class DesktopTasksControllerTest : ShellTestCase() { private fun setUpFullscreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { val task = createFullscreenTask(displayId) task.configuration.screenLayout = SCREENLAYOUT_SIZE_XLARGE doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true) whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) runningTasks.add(task) return task Loading @@ -882,7 +884,8 @@ class DesktopTasksControllerTest : ShellTestCase() { private fun setUpSplitScreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { val task = createSplitScreenTask(displayId) task.configuration.screenLayout = SCREENLAYOUT_SIZE_XLARGE doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true) whenever(splitScreenController.isTaskInSplitScreen(task.taskId)).thenReturn(true) whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) runningTasks.add(task) Loading Loading
libs/WindowManager/Shell/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -148,4 +148,7 @@ <!-- Whether pointer pilfer is required to start back animation. --> <bool name="config_backAnimationRequiresPointerPilfer">true</bool> <!-- Whether desktop mode is supported on the current device --> <bool name="config_isDesktopModeSupported">false</bool> </resources>
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java +23 −14 Original line number Diff line number Diff line Loading @@ -16,13 +16,13 @@ package com.android.wm.shell.desktopmode; import static android.content.res.Configuration.SCREENLAYOUT_SIZE_XLARGE; import android.annotation.NonNull; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; import android.os.SystemProperties; import com.android.internal.annotations.VisibleForTesting; import com.android.window.flags.Flags; import com.android.wm.shell.R; /** * Constants for desktop mode feature Loading Loading @@ -70,8 +70,11 @@ public class DesktopModeStatus { private static final boolean USE_ROUNDED_CORNERS = SystemProperties.getBoolean( "persist.wm.debug.desktop_use_rounded_corners", true); private static final boolean ENFORCE_DISPLAY_RESTRICTIONS = SystemProperties.getBoolean( "persist.wm.debug.desktop_mode_enforce_display_restrictions", true); /** * Flag to indicate whether to restrict desktop mode to supported devices. */ private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean( "persist.wm.debug.desktop_mode_enforce_device_restrictions", true); /** * Return {@code true} if desktop windowing is enabled Loading Loading @@ -113,19 +116,25 @@ public class DesktopModeStatus { } /** * Return whether the display size restrictions should be enforced. * Return {@code true} if desktop mode should be restricted to supported devices. */ @VisibleForTesting public static boolean enforceDeviceRestrictions() { return ENFORCE_DEVICE_RESTRICTIONS; } /** * Return {@code true} if the current device supports desktop mode. */ public static boolean enforceDisplayRestrictions() { return ENFORCE_DISPLAY_RESTRICTIONS; @VisibleForTesting public static boolean isDesktopModeSupported(@NonNull Context context) { return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported); } /** * Return {@code true} if the display associated with the task is at least of size * {@link android.content.res.Configuration#SCREENLAYOUT_SIZE_XLARGE} or has been overridden to * ignore the size constraint. * Return {@code true} if desktop mode can be entered on the current device. */ public static boolean meetsMinimumDisplayRequirements(@NonNull RunningTaskInfo taskInfo) { return !enforceDisplayRestrictions() || taskInfo.configuration.isLayoutSizeAtLeast(SCREENLAYOUT_SIZE_XLARGE); public static boolean canEnterDesktopMode(@NonNull Context context) { return !enforceDeviceRestrictions() || isDesktopModeSupported(context); } }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +1 −1 Original line number Diff line number Diff line Loading @@ -306,7 +306,7 @@ class DesktopTasksController( task: RunningTaskInfo, wct: WindowContainerTransaction = WindowContainerTransaction() ) { if (!DesktopModeStatus.meetsMinimumDisplayRequirements(task)) { if (!DesktopModeStatus.canEnterDesktopMode(context)) { KtProtoLog.w( WM_SHELL_DESKTOP_MODE, "DesktopTasksController: Cannot enter desktop, " + "display does not meet minimum size requirements") Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +1 −1 Original line number Diff line number Diff line Loading @@ -1052,7 +1052,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && taskInfo.getWindowingMode() != WINDOWING_MODE_PINNED && taskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD && !taskInfo.configuration.windowConfiguration.isAlwaysOnTop() && DesktopModeStatus.meetsMinimumDisplayRequirements(taskInfo); && DesktopModeStatus.canEnterDesktopMode(mContext); } private void createWindowDecoration( Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +17 −14 Original line number Diff line number Diff line Loading @@ -23,8 +23,6 @@ import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED import android.content.res.Configuration.SCREENLAYOUT_SIZE_NORMAL import android.content.res.Configuration.SCREENLAYOUT_SIZE_XLARGE import android.os.Binder import android.testing.AndroidTestingRunner import android.view.Display.DEFAULT_DISPLAY Loading @@ -38,6 +36,7 @@ import android.window.TransitionRequestInfo import android.window.WindowContainerTransaction import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.dx.mockito.inline.extended.ExtendedMockito.never import com.android.dx.mockito.inline.extended.StaticMockitoSession Loading Loading @@ -89,6 +88,7 @@ import org.mockito.Mockito.anyInt import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever import org.mockito.quality.Strictness @SmallTest @RunWith(AndroidTestingRunner::class) Loading Loading @@ -126,7 +126,8 @@ class DesktopTasksControllerTest : ShellTestCase() { @Before fun setUp() { mockitoSession = mockitoSession().spyStatic(DesktopModeStatus::class.java).startMocking() mockitoSession = mockitoSession().strictness(Strictness.LENIENT) .spyStatic(DesktopModeStatus::class.java).startMocking() whenever(DesktopModeStatus.isEnabled()).thenReturn(true) shellInit = Mockito.spy(ShellInit(testExecutor)) Loading Loading @@ -335,25 +336,25 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test fun moveToDesktop_screenSizeBelowXLarge_doesNothing() { fun moveToDesktop_deviceNotSupported_doesNothing() { val task = setUpFullscreenTask() // Update screen layout to be below minimum size task.configuration.screenLayout = SCREENLAYOUT_SIZE_NORMAL // Simulate non compatible device doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } controller.moveToDesktop(task) verifyWCTNotExecuted() } @Test fun moveToDesktop_screenSizeBelowXLarge_displayRestrictionsOverridden_taskIsMovedToDesktop() { fun moveToDesktop_deviceNotSupported_deviceRestrictionsOverridden_taskIsMovedToDesktop() { val task = setUpFullscreenTask() // Update screen layout to be below minimum size task.configuration.screenLayout = SCREENLAYOUT_SIZE_NORMAL // Simulate non compatible device doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } // Simulate enforce display restrictions system property overridden to false whenever(DesktopModeStatus.enforceDisplayRestrictions()).thenReturn(false) // Simulate enforce device restrictions system property overridden to false whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(false) controller.moveToDesktop(task) Loading @@ -363,7 +364,7 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test fun moveToDesktop_screenSizeXLarge_taskIsMovedToDesktop() { fun moveToDesktop_deviceSupported_taskIsMovedToDesktop() { val task = setUpFullscreenTask() controller.moveToDesktop(task) Loading Loading @@ -874,7 +875,8 @@ class DesktopTasksControllerTest : ShellTestCase() { private fun setUpFullscreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { val task = createFullscreenTask(displayId) task.configuration.screenLayout = SCREENLAYOUT_SIZE_XLARGE doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true) whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) runningTasks.add(task) return task Loading @@ -882,7 +884,8 @@ class DesktopTasksControllerTest : ShellTestCase() { private fun setUpSplitScreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo { val task = createSplitScreenTask(displayId) task.configuration.screenLayout = SCREENLAYOUT_SIZE_XLARGE doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } whenever(DesktopModeStatus.enforceDeviceRestrictions()).thenReturn(true) whenever(splitScreenController.isTaskInSplitScreen(task.taskId)).thenReturn(true) whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) runningTasks.add(task) Loading