Loading quickstep/src/com/android/quickstep/DesktopModeStatus.java 0 → 100644 +58 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.quickstep; import android.content.Context; import android.os.SystemProperties; import com.android.internal.annotations.VisibleForTesting; import com.android.window.flags.Flags; // TODO(b/335401172): Explore unifying logic across core and shell public class DesktopModeStatus { /** * 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 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. */ @VisibleForTesting public static boolean isDesktopModeSupported(Context context) { return context.getResources().getBoolean( com.android.internal.R.bool.config_isDesktopModeSupported); } /** * Return {@code true} if desktop mode can be entered on the current device. */ public static boolean canEnterDesktopMode(Context context) { return Flags.enableDesktopWindowingMode() && (!enforceDeviceRestrictions() || isDesktopModeSupported(context)); } } quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt +2 −3 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import com.android.launcher3.popup.SystemShortcut import com.android.quickstep.views.RecentsView import com.android.quickstep.views.RecentsViewContainer import com.android.quickstep.views.TaskView.TaskIdAttributeContainer import com.android.window.flags.Flags /** A menu item, "Desktop", that allows the user to bring the current app into Desktop Windowing. */ class DesktopSystemShortcut( Loading Loading @@ -52,7 +51,7 @@ class DesktopSystemShortcut( } companion object { /** Creates a factory for creating Desktop system shorcuts. */ /** Creates a factory for creating Desktop system shortcuts. */ @JvmOverloads fun createFactory( abstractFloatingViewHelper: AbstractFloatingViewHelper = AbstractFloatingViewHelper() Loading @@ -62,7 +61,7 @@ class DesktopSystemShortcut( container: RecentsViewContainer, taskContainer: TaskIdAttributeContainer ): List<DesktopSystemShortcut>? { return if (!Flags.enableDesktopWindowingMode()) null return if (!DesktopModeStatus.canEnterDesktopMode(container.asContext())) null else if (!taskContainer.task.isDockable) null else listOf( Loading quickstep/src/com/android/quickstep/views/RecentsView.java +3 −3 Original line number Diff line number Diff line Loading @@ -68,7 +68,6 @@ import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SELECT_ACTIVE; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; Loading Loading @@ -167,6 +166,7 @@ import com.android.launcher3.util.TranslateEdgeEffect; import com.android.launcher3.util.VibratorWrapper; import com.android.launcher3.util.ViewPool; import com.android.quickstep.BaseContainerInterface; import com.android.quickstep.DesktopModeStatus; import com.android.quickstep.GestureState; import com.android.quickstep.OverviewCommandHelper; import com.android.quickstep.RecentsAnimationController; Loading Loading @@ -2817,7 +2817,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo } private boolean hasDesktopTask(Task[] runningTasks) { if (!enableDesktopWindowingMode()) { if (!DesktopModeStatus.canEnterDesktopMode(mContext)) { return false; } for (Task task : runningTasks) { Loading Loading @@ -6229,7 +6229,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo */ public void moveTaskToDesktop(TaskIdAttributeContainer taskContainer, Runnable successCallback) { if (!enableDesktopWindowingMode()) { if (!DesktopModeStatus.canEnterDesktopMode(mContext)) { return; } switchToScreenshot(() -> finishRecentsAnimation(/* toRecents= */true, /* shouldPip= */false, Loading quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt +65 −2 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package com.android.quickstep 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.StaticMockitoSession import android.content.ComponentName import android.content.Intent import android.platform.test.flag.junit.SetFlagsRule import com.android.launcher3.AbstractFloatingView import com.android.launcher3.AbstractFloatingViewHelper import com.android.launcher3.Launcher import com.android.launcher3.logging.StatsLogManager import com.android.launcher3.logging.StatsLogManager.LauncherEvent import com.android.launcher3.model.data.WorkspaceItemInfo Loading @@ -33,8 +35,11 @@ import com.android.systemui.shared.recents.model.Task import com.android.systemui.shared.recents.model.Task.TaskKey import com.android.window.flags.Flags import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test import org.mockito.quality.Strictness import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.mock Loading @@ -56,8 +61,23 @@ class DesktopSystemShortcutTest { private val factory: TaskShortcutFactory = DesktopSystemShortcut.createFactory(abstractFloatingViewHelper) private lateinit var mockitoSession: StaticMockitoSession @Before fun setUp(){ mockitoSession = mockitoSession().strictness(Strictness.LENIENT) .spyStatic(DesktopModeStatus::class.java).startMocking() doReturn(true).`when` { DesktopModeStatus.enforceDeviceRestrictions() } doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } } @After fun tearDown(){ mockitoSession.finishMocking() } @Test fun createDesktopTaskShortcutFactory_featureOff() { fun createDesktopTaskShortcutFactory_desktopModeDisabled() { setFlagsRule.disableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) val task = Loading @@ -76,6 +96,49 @@ class DesktopSystemShortcutTest { assertThat(shortcuts).isNull() } @Test fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported() { setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } val task = Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply { isDockable = true } val taskContainer = taskView.TaskIdAttributeContainer( task, null, null, SplitConfigurationOptions.STAGE_POSITION_UNDEFINED ) val shortcuts = factory.getShortcuts(launcher, taskContainer) assertThat(shortcuts).isNull() } @Test fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported_OverrideEnabled() { setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } doReturn(false).`when` { DesktopModeStatus.enforceDeviceRestrictions() } val task = Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply { isDockable = true } val taskContainer = taskView.TaskIdAttributeContainer( task, null, null, SplitConfigurationOptions.STAGE_POSITION_UNDEFINED ) val shortcuts = factory.getShortcuts(launcher, taskContainer) assertThat(shortcuts).isNotNull() } @Test fun createDesktopTaskShortcutFactory_undockable() { setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) Loading Loading
quickstep/src/com/android/quickstep/DesktopModeStatus.java 0 → 100644 +58 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.quickstep; import android.content.Context; import android.os.SystemProperties; import com.android.internal.annotations.VisibleForTesting; import com.android.window.flags.Flags; // TODO(b/335401172): Explore unifying logic across core and shell public class DesktopModeStatus { /** * 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 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. */ @VisibleForTesting public static boolean isDesktopModeSupported(Context context) { return context.getResources().getBoolean( com.android.internal.R.bool.config_isDesktopModeSupported); } /** * Return {@code true} if desktop mode can be entered on the current device. */ public static boolean canEnterDesktopMode(Context context) { return Flags.enableDesktopWindowingMode() && (!enforceDeviceRestrictions() || isDesktopModeSupported(context)); } }
quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt +2 −3 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import com.android.launcher3.popup.SystemShortcut import com.android.quickstep.views.RecentsView import com.android.quickstep.views.RecentsViewContainer import com.android.quickstep.views.TaskView.TaskIdAttributeContainer import com.android.window.flags.Flags /** A menu item, "Desktop", that allows the user to bring the current app into Desktop Windowing. */ class DesktopSystemShortcut( Loading Loading @@ -52,7 +51,7 @@ class DesktopSystemShortcut( } companion object { /** Creates a factory for creating Desktop system shorcuts. */ /** Creates a factory for creating Desktop system shortcuts. */ @JvmOverloads fun createFactory( abstractFloatingViewHelper: AbstractFloatingViewHelper = AbstractFloatingViewHelper() Loading @@ -62,7 +61,7 @@ class DesktopSystemShortcut( container: RecentsViewContainer, taskContainer: TaskIdAttributeContainer ): List<DesktopSystemShortcut>? { return if (!Flags.enableDesktopWindowingMode()) null return if (!DesktopModeStatus.canEnterDesktopMode(container.asContext())) null else if (!taskContainer.task.isDockable) null else listOf( Loading
quickstep/src/com/android/quickstep/views/RecentsView.java +3 −3 Original line number Diff line number Diff line Loading @@ -68,7 +68,6 @@ import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SELECT_ACTIVE; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; Loading Loading @@ -167,6 +166,7 @@ import com.android.launcher3.util.TranslateEdgeEffect; import com.android.launcher3.util.VibratorWrapper; import com.android.launcher3.util.ViewPool; import com.android.quickstep.BaseContainerInterface; import com.android.quickstep.DesktopModeStatus; import com.android.quickstep.GestureState; import com.android.quickstep.OverviewCommandHelper; import com.android.quickstep.RecentsAnimationController; Loading Loading @@ -2817,7 +2817,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo } private boolean hasDesktopTask(Task[] runningTasks) { if (!enableDesktopWindowingMode()) { if (!DesktopModeStatus.canEnterDesktopMode(mContext)) { return false; } for (Task task : runningTasks) { Loading Loading @@ -6229,7 +6229,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo */ public void moveTaskToDesktop(TaskIdAttributeContainer taskContainer, Runnable successCallback) { if (!enableDesktopWindowingMode()) { if (!DesktopModeStatus.canEnterDesktopMode(mContext)) { return; } switchToScreenshot(() -> finishRecentsAnimation(/* toRecents= */true, /* shouldPip= */false, Loading
quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt +65 −2 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package com.android.quickstep 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.StaticMockitoSession import android.content.ComponentName import android.content.Intent import android.platform.test.flag.junit.SetFlagsRule import com.android.launcher3.AbstractFloatingView import com.android.launcher3.AbstractFloatingViewHelper import com.android.launcher3.Launcher import com.android.launcher3.logging.StatsLogManager import com.android.launcher3.logging.StatsLogManager.LauncherEvent import com.android.launcher3.model.data.WorkspaceItemInfo Loading @@ -33,8 +35,11 @@ import com.android.systemui.shared.recents.model.Task import com.android.systemui.shared.recents.model.Task.TaskKey import com.android.window.flags.Flags import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test import org.mockito.quality.Strictness import org.mockito.kotlin.any import org.mockito.kotlin.eq import org.mockito.kotlin.mock Loading @@ -56,8 +61,23 @@ class DesktopSystemShortcutTest { private val factory: TaskShortcutFactory = DesktopSystemShortcut.createFactory(abstractFloatingViewHelper) private lateinit var mockitoSession: StaticMockitoSession @Before fun setUp(){ mockitoSession = mockitoSession().strictness(Strictness.LENIENT) .spyStatic(DesktopModeStatus::class.java).startMocking() doReturn(true).`when` { DesktopModeStatus.enforceDeviceRestrictions() } doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } } @After fun tearDown(){ mockitoSession.finishMocking() } @Test fun createDesktopTaskShortcutFactory_featureOff() { fun createDesktopTaskShortcutFactory_desktopModeDisabled() { setFlagsRule.disableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) val task = Loading @@ -76,6 +96,49 @@ class DesktopSystemShortcutTest { assertThat(shortcuts).isNull() } @Test fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported() { setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } val task = Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply { isDockable = true } val taskContainer = taskView.TaskIdAttributeContainer( task, null, null, SplitConfigurationOptions.STAGE_POSITION_UNDEFINED ) val shortcuts = factory.getShortcuts(launcher, taskContainer) assertThat(shortcuts).isNull() } @Test fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported_OverrideEnabled() { setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) } doReturn(false).`when` { DesktopModeStatus.enforceDeviceRestrictions() } val task = Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply { isDockable = true } val taskContainer = taskView.TaskIdAttributeContainer( task, null, null, SplitConfigurationOptions.STAGE_POSITION_UNDEFINED ) val shortcuts = factory.getShortcuts(launcher, taskContainer) assertThat(shortcuts).isNotNull() } @Test fun createDesktopTaskShortcutFactory_undockable() { setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) Loading