[2/n] Hide desktop button in overview for incompatible tasks
Flag: NONE bug fix
Test: atest -c NexusLauncherTests:com.android.quickstep.DesktopSystemShortcutTest,
atest -c NexusLauncherTests:com.android.quickstep.ExternalDisplaySystemShortcutTest
Fixes: 389923274
Change-Id: I82acc85ca57b5454f9eeedd800dcd7da9990f9c8
diff --git a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
index d60dab6..914855b 100644
--- a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
+++ b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
@@ -26,6 +26,7 @@
import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.TaskContainer
import com.android.systemui.shared.system.InteractionJankMonitorWrapper
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource
@@ -70,16 +71,31 @@
container: RecentsViewContainer,
taskContainer: TaskContainer,
): List<DesktopSystemShortcut>? {
- return if (!DesktopModeStatus.canEnterDesktopMode(container.asContext())) null
- else if (!taskContainer.task.isDockable) null
- else
- listOf(
- DesktopSystemShortcut(
- container,
- taskContainer,
- abstractFloatingViewHelper,
+ val context = container.asContext()
+ val taskKey = taskContainer.task.key
+ val desktopModeCompatPolicy = DesktopModeCompatPolicy(context)
+ return when {
+ !DesktopModeStatus.canEnterDesktopMode(context) -> null
+
+ desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
+ taskKey.baseActivity?.packageName,
+ taskKey.numActivities,
+ taskKey.isTopActivityNoDisplay,
+ taskKey.isActivityStackTransparent,
+ ) -> null
+
+ !taskContainer.task.isDockable -> null
+
+ else -> {
+ listOf(
+ DesktopSystemShortcut(
+ container,
+ taskContainer,
+ abstractFloatingViewHelper,
+ )
)
- )
+ }
+ }
}
override fun showForGroupedTask() = true
diff --git a/quickstep/src/com/android/quickstep/ExternalDisplaySystemShortcut.kt b/quickstep/src/com/android/quickstep/ExternalDisplaySystemShortcut.kt
index 46c4f36..f97cf9c 100644
--- a/quickstep/src/com/android/quickstep/ExternalDisplaySystemShortcut.kt
+++ b/quickstep/src/com/android/quickstep/ExternalDisplaySystemShortcut.kt
@@ -25,6 +25,7 @@
import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.TaskContainer
import com.android.window.flags.Flags
+import com.android.wm.shell.shared.desktopmode.DesktopModeCompatPolicy
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
/** A menu item that allows the user to move the current app into external display. */
@@ -66,18 +67,31 @@
container: RecentsViewContainer,
taskContainer: TaskContainer,
): List<ExternalDisplaySystemShortcut>? {
- return if (
- DesktopModeStatus.canEnterDesktopMode(container.asContext()) &&
- Flags.moveToExternalDisplayShortcut()
- )
- listOf(
- ExternalDisplaySystemShortcut(
- container,
- abstractFloatingViewHelper,
- taskContainer,
+ val context = container.asContext()
+ val taskKey = taskContainer.task.key
+ val desktopModeCompatPolicy = DesktopModeCompatPolicy(context)
+ return when {
+ !DesktopModeStatus.canEnterDesktopMode(context) -> null
+
+ !Flags.moveToExternalDisplayShortcut() -> null
+
+ desktopModeCompatPolicy.isTopActivityExemptFromDesktopWindowing(
+ taskKey.baseActivity?.packageName,
+ taskKey.numActivities,
+ taskKey.isTopActivityNoDisplay,
+ taskKey.isActivityStackTransparent,
+ ) -> null
+
+ else -> {
+ listOf(
+ ExternalDisplaySystemShortcut(
+ container,
+ abstractFloatingViewHelper,
+ taskContainer,
+ )
)
- )
- else null
+ }
+ }
}
override fun showForGroupedTask() = true
diff --git a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
index c152ee1..52bd2ea 100644
--- a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
@@ -17,28 +17,33 @@
package com.android.quickstep
import android.content.ComponentName
+import android.content.Context
import android.content.Intent
+import android.platform.test.annotations.EnableFlags
+import android.view.Display.DEFAULT_DISPLAY
import androidx.test.platform.app.InstrumentationRegistry
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.internal.R
import com.android.launcher3.AbstractFloatingView
import com.android.launcher3.AbstractFloatingViewHelper
import com.android.launcher3.Flags.enableRefactorTaskThumbnail
import com.android.launcher3.logging.StatsLogManager
import com.android.launcher3.logging.StatsLogManager.LauncherEvent
import com.android.launcher3.model.data.TaskViewItemInfo
-import com.android.launcher3.uioverrides.QuickstepLauncher
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.launcher3.util.TransformingTouchDelegate
import com.android.quickstep.TaskOverlayFactory.TaskOverlay
import com.android.quickstep.task.thumbnail.TaskThumbnailView
import com.android.quickstep.views.LauncherRecentsView
+import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.TaskContainer
import com.android.quickstep.views.TaskThumbnailViewDeprecated
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskViewIcon
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.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource
import com.google.common.truth.Truth.assertThat
@@ -58,7 +63,7 @@
/** Test for [DesktopSystemShortcut] */
class DesktopSystemShortcutTest {
- private val launcher: QuickstepLauncher = mock()
+ private val launcher: RecentsViewContainer = mock()
private val statsLogManager: StatsLogManager = mock()
private val statsLogger: StatsLogManager.StatsLogger = mock()
private val recentsView: LauncherRecentsView = mock()
@@ -67,6 +72,7 @@
private val overlayFactory: TaskOverlayFactory = mock()
private val factory: TaskShortcutFactory =
DesktopSystemShortcut.createFactory(abstractFloatingViewHelper)
+ private val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
private lateinit var mockitoSession: StaticMockitoSession
@@ -79,6 +85,7 @@
.startMocking()
whenever(DesktopModeStatus.canEnterDesktopMode(any())).thenReturn(true)
whenever(overlayFactory.createOverlay(any())).thenReturn(mock<TaskOverlay<*>>())
+ whenever(launcher.asContext()).thenReturn(context)
}
@After
@@ -97,6 +104,53 @@
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
+ fun createDesktopTaskShortcutFactory_transparentTask() {
+ val baseComponent = ComponentName("", /* class */ "")
+ val taskKey =
+ TaskKey(
+ /* id */ 1,
+ /* windowingMode */ 0,
+ Intent(),
+ baseComponent,
+ /* userId */ 0,
+ /* lastActiveTime */ 2000,
+ DEFAULT_DISPLAY,
+ baseComponent,
+ /* numActivities */ 1,
+ /* isTopActivityNoDisplay */ false,
+ /* isActivityStackTransparent */ true,
+ )
+ val taskContainer = createTaskContainer(Task(taskKey))
+ val shortcuts = factory.getShortcuts(launcher, taskContainer)
+ assertThat(shortcuts).isNull()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
+ fun createDesktopTaskShortcutFactory_systemUiTask() {
+ val sysUiPackageName: String = context.resources.getString(R.string.config_systemUi)
+ val baseComponent = ComponentName(sysUiPackageName, /* class */ "")
+ val taskKey =
+ TaskKey(
+ /* id */ 1,
+ /* windowingMode */ 0,
+ Intent(),
+ baseComponent,
+ /* userId */ 0,
+ /* lastActiveTime */ 2000,
+ DEFAULT_DISPLAY,
+ baseComponent,
+ /* numActivities */ 1,
+ /* isTopActivityNoDisplay */ false,
+ /* isActivityStackTransparent */ false,
+ )
+ val taskContainer = createTaskContainer(Task(taskKey))
+ val shortcuts = factory.getShortcuts(launcher, taskContainer)
+ assertThat(shortcuts).isNull()
+ }
+
+ @Test
fun createDesktopTaskShortcutFactory_undockable() {
val unDockableTask = createTask().apply { isDockable = false }
val taskContainer = createTaskContainer(unDockableTask)
@@ -114,8 +168,7 @@
whenever(launcher.statsLogManager).thenReturn(statsLogManager)
whenever(statsLogManager.logger()).thenReturn(statsLogger)
whenever(statsLogger.withItemInfo(any())).thenReturn(statsLogger)
- whenever(taskView.context)
- .thenReturn(InstrumentationRegistry.getInstrumentation().targetContext)
+ whenever(taskView.context).thenReturn(context)
whenever(recentsView.moveTaskToDesktop(any(), any(), any())).thenAnswer {
val successCallback = it.getArgument<Runnable>(2)
successCallback.run()
@@ -145,7 +198,22 @@
}
private fun createTask() =
- Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply { isDockable = true }
+ Task(
+ TaskKey(
+ /* id */ 1,
+ /* windowingMode */ 0,
+ Intent(),
+ ComponentName("", ""),
+ /* userId */ 0,
+ /* lastActiveTime */ 2000,
+ DEFAULT_DISPLAY,
+ ComponentName("", ""),
+ /* numActivities */ 1,
+ /* isTopActivityNoDisplay */ false,
+ /* isActivityStackTransparent */ false,
+ )
+ )
+ .apply { isDockable = true }
private fun createTaskContainer(task: Task) =
TaskContainer(
diff --git a/quickstep/tests/src/com/android/quickstep/ExternalDisplaySystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/ExternalDisplaySystemShortcutTest.kt
index 9c2c13c..4111dec 100644
--- a/quickstep/tests/src/com/android/quickstep/ExternalDisplaySystemShortcutTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/ExternalDisplaySystemShortcutTest.kt
@@ -17,23 +17,27 @@
package com.android.quickstep
import android.content.ComponentName
+import android.content.Context
import android.content.Intent
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
+import android.view.Display.DEFAULT_DISPLAY
+import androidx.test.platform.app.InstrumentationRegistry
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.internal.R
import com.android.launcher3.AbstractFloatingView
import com.android.launcher3.AbstractFloatingViewHelper
import com.android.launcher3.Flags.enableRefactorTaskThumbnail
import com.android.launcher3.logging.StatsLogManager
import com.android.launcher3.logging.StatsLogManager.LauncherEvent
import com.android.launcher3.model.data.TaskViewItemInfo
-import com.android.launcher3.uioverrides.QuickstepLauncher
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.launcher3.util.TransformingTouchDelegate
import com.android.quickstep.TaskOverlayFactory.TaskOverlay
import com.android.quickstep.task.thumbnail.TaskThumbnailView
import com.android.quickstep.views.LauncherRecentsView
+import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.TaskContainer
import com.android.quickstep.views.TaskThumbnailViewDeprecated
import com.android.quickstep.views.TaskView
@@ -62,7 +66,7 @@
@get:Rule val setFlagsRule = SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT)
- private val launcher: QuickstepLauncher = mock()
+ private val launcher: RecentsViewContainer = mock()
private val statsLogManager: StatsLogManager = mock()
private val statsLogger: StatsLogManager.StatsLogger = mock()
private val recentsView: LauncherRecentsView = mock()
@@ -71,6 +75,7 @@
private val overlayFactory: TaskOverlayFactory = mock()
private val factory: TaskShortcutFactory =
ExternalDisplaySystemShortcut.createFactory(abstractFloatingViewHelper)
+ private val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
private lateinit var mockitoSession: StaticMockitoSession
@@ -83,6 +88,7 @@
.startMocking()
whenever(DesktopModeStatus.canEnterDesktopMode(any())).thenReturn(true)
whenever(overlayFactory.createOverlay(any())).thenReturn(mock<TaskOverlay<*>>())
+ whenever(launcher.asContext()).thenReturn(context)
}
@After
@@ -102,6 +108,59 @@
}
@Test
+ @EnableFlags(
+ Flags.FLAG_MOVE_TO_EXTERNAL_DISPLAY_SHORTCUT,
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY,
+ )
+ fun createExternalDisplayTaskShortcut_transparentTask() {
+ val baseComponent = ComponentName("", /* class */ "")
+ val taskKey =
+ TaskKey(
+ /* id */ 1,
+ /* windowingMode */ 0,
+ Intent(),
+ baseComponent,
+ /* userId */ 0,
+ /* lastActiveTime */ 2000,
+ DEFAULT_DISPLAY,
+ baseComponent,
+ /* numActivities */ 1,
+ /* isTopActivityNoDisplay */ false,
+ /* isActivityStackTransparent */ true,
+ )
+ val taskContainer = createTaskContainer(Task(taskKey))
+ val shortcuts = factory.getShortcuts(launcher, taskContainer)
+ assertThat(shortcuts).isNull()
+ }
+
+ @Test
+ @EnableFlags(
+ Flags.FLAG_MOVE_TO_EXTERNAL_DISPLAY_SHORTCUT,
+ Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY,
+ )
+ fun createExternalDisplayTaskShortcut_systemUiTask() {
+ val sysUiPackageName: String = context.resources.getString(R.string.config_systemUi)
+ val baseComponent = ComponentName(sysUiPackageName, /* class */ "")
+ val taskKey =
+ TaskKey(
+ /* id */ 1,
+ /* windowingMode */ 0,
+ Intent(),
+ baseComponent,
+ /* userId */ 0,
+ /* lastActiveTime */ 2000,
+ DEFAULT_DISPLAY,
+ baseComponent,
+ /* numActivities */ 1,
+ /* isTopActivityNoDisplay */ false,
+ /* isActivityStackTransparent */ false,
+ )
+ val taskContainer = createTaskContainer(Task(taskKey))
+ val shortcuts = factory.getShortcuts(launcher, taskContainer)
+ assertThat(shortcuts).isNull()
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_MOVE_TO_EXTERNAL_DISPLAY_SHORTCUT)
fun externalDisplaySystemShortcutClicked() {
val task = createTask()
@@ -134,7 +193,22 @@
verify(statsLogger).log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_EXTERNAL_DISPLAY_TAP)
}
- private fun createTask() = Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000))
+ private fun createTask() =
+ Task(
+ TaskKey(
+ /* id */ 1,
+ /* windowingMode */ 0,
+ Intent(),
+ ComponentName("", ""),
+ /* userId */ 0,
+ /* lastActiveTime */ 2000,
+ DEFAULT_DISPLAY,
+ ComponentName("", ""),
+ /* numActivities */ 1,
+ /* isTopActivityNoDisplay */ false,
+ /* isActivityStackTransparent */ false,
+ )
+ )
private fun createTaskContainer(task: Task) =
TaskContainer(