Merge changes from topic "p-shortcut-impl" into main
* changes:
Widget Picker: Update the launcher integration to support shortcuts
Widget Picker: Update UI layer to support shortcuts
Widget Picker: Update data layer to support shortcuts
diff --git a/aconfig/launcher_overview.aconfig b/aconfig/launcher_overview.aconfig
index 61cdc75..c6fb8bf 100644
--- a/aconfig/launcher_overview.aconfig
+++ b/aconfig/launcher_overview.aconfig
@@ -97,3 +97,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enable_simultaneous_overview_trigger_on_extended_desktop"
+ namespace: "launcher_overview"
+ description: "Enable Overview to launch and exit simultaneously on default and external displays wherever it was triggered or quit from"
+ bug: "421128035"
+}
diff --git a/quickstep/dagger/com/android/launcher3/dagger/AppModule.kt b/quickstep/dagger/com/android/launcher3/dagger/AppModule.kt
index 5521c06..d88fc94 100644
--- a/quickstep/dagger/com/android/launcher3/dagger/AppModule.kt
+++ b/quickstep/dagger/com/android/launcher3/dagger/AppModule.kt
@@ -16,10 +16,8 @@
package com.android.launcher3.dagger
-import com.android.launcher3.backuprestore.LauncherRestoreEventLogger
import com.android.launcher3.model.ModelDelegate
import com.android.launcher3.model.QuickstepModelDelegate
-import com.android.quickstep.LauncherRestoreEventLoggerImpl
import dagger.Binds
import dagger.Module
@@ -31,9 +29,4 @@
abstract class AppModule {
@Binds abstract fun bindModelDelegate(impl: QuickstepModelDelegate): ModelDelegate
-
- @Binds
- abstract fun bindRestoreEventLogger(
- impl: LauncherRestoreEventLoggerImpl
- ): LauncherRestoreEventLogger
}
diff --git a/quickstep/src/com/android/launcher3/dagger/Modules.kt b/quickstep/src/com/android/launcher3/dagger/Modules.kt
index fccbf2b..5581d37 100644
--- a/quickstep/src/com/android/launcher3/dagger/Modules.kt
+++ b/quickstep/src/com/android/launcher3/dagger/Modules.kt
@@ -16,6 +16,7 @@
package com.android.launcher3.dagger
+import com.android.launcher3.backuprestore.LauncherRestoreEventLogger
import com.android.launcher3.icons.LauncherIconProvider
import com.android.launcher3.icons.LauncherIconProviderImpl
import com.android.launcher3.logging.StatsLogManager.StatsLogManagerFactory
@@ -29,6 +30,7 @@
import com.android.launcher3.util.window.WindowManagerProxy
import com.android.launcher3.widget.LauncherWidgetHolder.WidgetHolderFactory
import com.android.quickstep.InstantAppResolverImpl
+import com.android.quickstep.LauncherRestoreEventLoggerImpl
import com.android.quickstep.logging.StatsLogCompatManager.StatsLogCompatManagerFactory
import com.android.quickstep.util.ChoreographerFrameRateTracker
import com.android.quickstep.util.GestureExclusionManager
@@ -58,6 +60,11 @@
abstract fun bindIconProvider(iconProviderImpl: LauncherIconProviderImpl): LauncherIconProvider
@Binds abstract fun bindInstantAppResolver(impl: InstantAppResolverImpl): InstantAppResolver
+
+ @Binds
+ abstract fun bindRestoreEventLogger(
+ impl: LauncherRestoreEventLoggerImpl
+ ): LauncherRestoreEventLogger
}
@Module
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 5ab21f8..f7e760d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -1844,7 +1844,7 @@
return;
}
}
- if (shouldLaunchInDesktop(displayId)) {
+ if (shouldLaunchInDesktop(displayId, info)) {
launchDesktopApp(intent, info, displayId);
} else {
startActivity(intent, null);
@@ -1856,10 +1856,16 @@
}
}
- private boolean shouldLaunchInDesktop(int displayId) {
+ private boolean shouldLaunchInDesktop(int displayId, ItemInfo info) {
if (!DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue()) {
return false;
}
+ if (DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_FULLSCREEN_REFOCUS_BUGFIX.isTrue()
+ && DisplayController.isInDesktopFirstMode(this)
+ && mControllers.taskbarRecentAppsController.hasSingleTask(info)) {
+ // Keep the fullscreen mode in desktop-first mode.
+ return false;
+ }
// Always launch in freeform if in external display.
return (DesktopExperienceFlags.ENABLE_FREEFORM_DISPLAY_LAUNCH_PARAMS.isTrue()
&& isExternalDisplay(displayId)) || isTaskbarShowingDesktopTasks();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
index 8176920..f4d0f15 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
@@ -138,6 +138,19 @@
}
}
+ /**
+ * Returns `true` if recents has the single task (i.e., fullscreen) represented by the given
+ * [itemInfo].
+ */
+ fun hasSingleTask(itemInfo: ItemInfo?): Boolean {
+ val packageName = itemInfo?.targetPackage ?: return false
+ return allRecentTasks.any { task ->
+ task is SingleTask &&
+ packageName == task.task.key.packageName &&
+ task.task.key.userId == itemInfo.user.identifier
+ }
+ }
+
@VisibleForTesting
val runningTaskIds: Set<Int>
/**
diff --git a/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModel.kt b/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModel.kt
index 049556a..8e67c10 100644
--- a/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModel.kt
+++ b/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModel.kt
@@ -94,15 +94,16 @@
}
private val overlayEnabled =
- if (taskViewType == TaskViewType.DESKTOP) {
- flowOf(false)
- } else {
- combine(recentsViewData.overlayEnabled, recentsViewData.settledFullyVisibleTaskIds) {
- isOverlayEnabled,
- settledFullyVisibleTaskIds ->
- isOverlayEnabled && settledFullyVisibleTaskIds.any { it in taskIds.value }
- }
- .distinctUntilChanged()
+ when (taskViewType) {
+ TaskViewType.SINGLE ->
+ combine(
+ recentsViewData.overlayEnabled,
+ recentsViewData.settledFullyVisibleTaskIds,
+ ) { isOverlayEnabled, settledFullyVisibleTaskIds ->
+ isOverlayEnabled && settledFullyVisibleTaskIds.any { it in taskIds.value }
+ }
+ .distinctUntilChanged()
+ else -> flowOf(false)
}
private val preThreadingImprovedState: Flow<TaskTileUiState> =
@@ -126,10 +127,11 @@
val taskIds = taskModels.map { it.first }.toSet()
val isCentralTask = taskIds == centralTaskIds
val overlayEnabled =
- if (taskViewType == TaskViewType.DESKTOP) {
- false
- } else {
- isOverlayEnabled && settledFullyVisibleTaskIds.any { it in taskIds }
+ when (taskViewType) {
+ TaskViewType.SINGLE -> {
+ isOverlayEnabled && settledFullyVisibleTaskIds.any { it in taskIds }
+ }
+ else -> false
}
val isLiveTile = runningTaskIds == taskIds && !runningTaskShowScreenshot
val taskData = mapToTaskData(taskModels, isLiveTile)
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
index 0f1f1cd..d5ffe4b 100644
--- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -36,6 +36,7 @@
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.fallback.window.RecentsWindowFlags;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
+import com.android.wm.shell.shared.desktopmode.DesktopState;
import java.util.List;
import java.util.Set;
@@ -82,6 +83,15 @@
}
@Override
+ public boolean isDisplayDesktopFirst(Context displayInfoContext) {
+ if (!DesktopState.fromContext(displayInfoContext).canEnterDesktopMode()) {
+ return false;
+ }
+ return displayInfoContext.getResources().getConfiguration()
+ .windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
+ }
+
+ @Override
public boolean showLockedTaskbarOnHome(Context displayInfoContext) {
if (!DesktopModeStatus.canEnterDesktopMode(displayInfoContext)) {
return false;
@@ -89,9 +99,8 @@
if (!DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(displayInfoContext)) {
return false;
}
- final boolean isFreeformDisplay = displayInfoContext.getResources().getConfiguration()
- .windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
- return isFreeformDisplay;
+
+ return isDisplayDesktopFirst(displayInfoContext);
}
@Override
@@ -108,9 +117,7 @@
return false;
}
- final boolean isFreeformDisplay = displayInfoContext.getResources().getConfiguration()
- .windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
- return isFreeformDisplay;
+ return isDisplayDesktopFirst(displayInfoContext);
}
@Override
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
index c119572..f3d828a 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
@@ -1118,6 +1118,61 @@
.containsExactlyElementsIn(listOf(1, 2, 3, 4))
}
+ @Test
+ fun hasSingleTask_noTargetPackage_returnsFalse() {
+ prepareHotseatAndRunningAndRecentApps(
+ hotseatPackages = emptyList(),
+ runningTasks = emptyList(),
+ recentTaskPackages = listOf(RECENT_PACKAGE_1),
+ )
+ assertThat(recentAppsController.hasSingleTask(ItemInfo())).isFalse()
+ }
+
+ @Test
+ fun hasSingleTask_noRecentTasks_returnsFalse() {
+ prepareHotseatAndRunningAndRecentApps(
+ hotseatPackages = emptyList(),
+ runningTasks = emptyList(),
+ recentTaskPackages = emptyList(),
+ )
+ val itemInfo = createItemInfo(RECENT_PACKAGE_1)
+ assertThat(recentAppsController.hasSingleTask(itemInfo)).isFalse()
+ }
+
+ @Test
+ fun hasSingleTask_noMatchingSingleTask_returnsFalse() {
+ prepareHotseatAndRunningAndRecentApps(
+ hotseatPackages = emptyList(),
+ runningTasks = emptyList(),
+ recentTaskPackages = listOf(RECENT_PACKAGE_1),
+ )
+ val itemInfo = createItemInfo(RECENT_PACKAGE_2)
+ assertThat(recentAppsController.hasSingleTask(itemInfo)).isFalse()
+ }
+
+ @Test
+ fun hasSingleTask_matchingSingleTask_returnsTrue() {
+ prepareHotseatAndRunningAndRecentApps(
+ hotseatPackages = emptyList(),
+ runningTasks = emptyList(),
+ recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
+ )
+ val itemInfo = createItemInfo(RECENT_PACKAGE_1)
+ assertThat(recentAppsController.hasSingleTask(itemInfo)).isTrue()
+ }
+
+ @Test
+ fun hasSingleTask_matchingSingleTaskDifferentUser_returnsFalse() {
+ prepareHotseatAndRunningAndRecentApps(
+ hotseatPackages = emptyList(),
+ runningTasks = emptyList(),
+ recentTaskPackages = listOf(RECENT_PACKAGE_1),
+ )
+ // RECENT_PACKAGE_1 is created with myUserHandle in createRecentTasksFromPackageNames
+ val itemInfo = createItemInfo(RECENT_PACKAGE_1, USER_HANDLE_1)
+ assertThat(recentAppsController.hasSingleTask(itemInfo)).isFalse()
+ }
+
private fun prepareHotseatAndRunningAndRecentApps(
hotseatPackages: List<String>,
runningTasks: List<Task>,
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModelTest.kt
index 9eb1f11..b499a1d 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModelTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModelTest.kt
@@ -306,6 +306,17 @@
}
@Test
+ fun taskOverlayDisabled_when_OverlayIsEnabledForVisibleGroupedTask() =
+ testScope.runTest {
+ sut = createTaskViewModel(TaskViewType.GROUPED)
+ sut.bind(TASK_MODEL_1.id)
+ recentsViewData.overlayEnabled.value = true
+ recentsViewData.settledFullyVisibleTaskIds.value = setOf(1)
+
+ assertThat(sut.state.first().taskOverlayEnabled).isFalse()
+ }
+
+ @Test
fun isCentralTask_when_CentralTaskIdsMatchTaskIds() =
testScope.runTest {
sut.bind(TASK_MODEL_1.id, TASK_MODEL_2.id)
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 60c65e5..ab9ede6 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -258,6 +258,13 @@
}
/**
+ * Returns whether the display is in desktop-first mode.
+ */
+ public static boolean isInDesktopFirstMode(Context context) {
+ return getInfo(context).isInDesktopFirstMode();
+ }
+
+ /**
* Returns whether the taskbar is forced to be pinned when home is visible.
*/
public static boolean showLockedTaskbarOnHome(Context context) {
@@ -524,6 +531,7 @@
private final boolean mIsTaskbarPinned;
private final boolean mIsInDesktopMode;
+ private final boolean mIsInDesktopFirstMode;
private final boolean mShowLockedTaskbarOnHome;
private final boolean mIsHomeVisible;
@@ -600,6 +608,7 @@
mIsTaskbarPinned = LauncherPrefs.get(displayInfoContext).get(TASKBAR_PINNING);
mIsInDesktopMode = wmProxy.isInDesktopMode(DEFAULT_DISPLAY);
+ mIsInDesktopFirstMode = wmProxy.isDisplayDesktopFirst(displayInfoContext);
mShowLockedTaskbarOnHome = wmProxy.showLockedTaskbarOnHome(displayInfoContext);
mShowDesktopTaskbarForFreeformDisplay = wmProxy.showDesktopTaskbarForFreeformDisplay(
displayInfoContext);
@@ -653,6 +662,13 @@
}
/**
+ * Returns whether the display is in desktop-first mode.
+ */
+ public boolean isInDesktopFirstMode() {
+ return mIsInDesktopFirstMode;
+ }
+
+ /**
* Returns {@code true} if the bounds represent a tablet.
*/
public boolean isTablet(WindowBounds bounds) {
@@ -767,6 +783,7 @@
pw.println(" navigationMode=" + info.getNavigationMode().name());
pw.println(" isTaskbarPinned=" + info.mIsTaskbarPinned);
pw.println(" isInDesktopMode=" + info.mIsInDesktopMode);
+ pw.println(" isInDesktopFirstMode=" + info.isInDesktopFirstMode());
pw.println(" showLockedTaskbarOnHome=" + info.showLockedTaskbarOnHome());
pw.println(" currentSize=" + info.currentSize);
info.mPerDisplayBounds.forEach((key, value) -> pw.println(
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
index 43059b6..493aef2 100644
--- a/src/com/android/launcher3/util/window/WindowManagerProxy.java
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -116,6 +116,13 @@
}
/**
+ * Returns if the display is in desktop-first mode.
+ */
+ public boolean isDisplayDesktopFirst(Context displayInfoContext) {
+ return false;
+ }
+
+ /**
* Returns if the pinned taskbar should be shown when home is visible.
*/
public boolean showLockedTaskbarOnHome(Context displayInfoContext) {