Merge changes I8411fb83,I5b757558 into main
* changes:
Move Desktop running apps support into TaskbarRecentAppsController
Add flag for Recents in Taskbar
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index 9147e4c..22fe82b 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -284,3 +284,10 @@
description: "Enables folders in all apps"
bug: "341582436"
}
+
+flag {
+ name: "enable_recents_in_taskbar"
+ namespace: "launcher"
+ description: "Replace hybrid hotseat app predictions with strictly Recent Apps"
+ bug: "315354060"
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 0de0550..61877f0 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -41,8 +41,6 @@
import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
-import static com.android.window.flags.Flags.enableDesktopWindowingMode;
-import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps;
import static com.android.wm.shell.Flags.enableTinyTaskbar;
import android.animation.AnimatorSet;
@@ -304,7 +302,9 @@
new VoiceInteractionWindowController(this),
new TaskbarTranslationController(this),
new TaskbarSpringOnStashController(this),
- createTaskbarRecentAppsController(),
+ new TaskbarRecentAppsController(
+ RecentsModel.INSTANCE.get(this),
+ LauncherActivityInterface.INSTANCE::getDesktopVisibilityController),
TaskbarEduTooltipController.newInstance(this),
new KeyboardQuickSwitchController(),
new TaskbarPinningController(this, () ->
@@ -314,16 +314,6 @@
mLauncherPrefs = LauncherPrefs.get(this);
}
- private TaskbarRecentAppsController createTaskbarRecentAppsController() {
- // TODO(b/335401172): unify DesktopMode checks in Launcher
- if (enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()) {
- return new DesktopTaskbarRunningAppsController(
- RecentsModel.INSTANCE.get(this),
- LauncherActivityInterface.INSTANCE::getDesktopVisibilityController);
- }
- return TaskbarRecentAppsController.DEFAULT;
- }
-
/** Updates {@link DeviceProfile} instances for any Taskbar windows. */
public void updateDeviceProfile(DeviceProfile launcherDp) {
applyDeviceProfile(launcherDp);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index f9ddc3d..58c5e83 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -180,8 +180,9 @@
taskbarUnfoldAnimationController, taskbarKeyguardController,
stashedHandleViewController, taskbarStashController,
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
- voiceInteractionWindowController, taskbarTranslationController,
- taskbarEduTooltipController, keyboardQuickSwitchController, taskbarPinningController
+ voiceInteractionWindowController, taskbarRecentAppsController,
+ taskbarTranslationController, taskbarEduTooltipController,
+ keyboardQuickSwitchController, taskbarPinningController,
};
mBackgroundRendererControllers = new BackgroundRendererController[] {
taskbarDragLayerController, taskbarScrimViewController,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index 35e1c7b..2b0e169 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -79,7 +79,7 @@
public void init(TaskbarControllers controllers) {
mControllers = controllers;
- if (mControllers.taskbarRecentAppsController.isEnabled()) {
+ if (mControllers.taskbarRecentAppsController.getCanShowRunningApps()) {
RecentsModel.INSTANCE.get(mContext).registerRunningTasksListener(this);
if (shouldShowRunningAppsInDesktopMode()) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java
deleted file mode 100644
index 606ba5b..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2022 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.launcher3.taskbar;
-
-import static java.util.Collections.emptySet;
-
-import androidx.annotation.CallSuper;
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
-
-import java.util.Set;
-
-/**
- * Base class for providing recent apps functionality
- */
-public class TaskbarRecentAppsController {
-
- public static final TaskbarRecentAppsController DEFAULT = new TaskbarRecentAppsController();
-
- // Initialized in init.
- protected TaskbarControllers mControllers;
-
- @CallSuper
- protected void init(TaskbarControllers taskbarControllers) {
- mControllers = taskbarControllers;
- }
-
- @CallSuper
- protected void onDestroy() {
- mControllers = null;
- }
-
- /** Stores the current {@link AppInfo} instances, no-op except in desktop environment. */
- protected void setApps(AppInfo[] apps) {
- }
-
- /**
- * Indicates whether recent apps functionality is enabled, should return false except in
- * desktop environment.
- */
- protected boolean isEnabled() {
- return false;
- }
-
- /** Called to update hotseatItems, no-op except in desktop environment. */
- protected ItemInfo[] updateHotseatItemInfos(@NonNull ItemInfo[] hotseatItems) {
- return hotseatItems;
- }
-
- /** Called to update the list of currently running apps, no-op except in desktop environment. */
- protected void updateRunningApps() {}
-
- /** Returns the currently running apps, or an empty Set if outside of Desktop environment. */
- public Set<String> getRunningApps() {
- return emptySet();
- }
-
- /** Returns the set of apps whose tasks are all minimized. */
- public Set<String> getMinimizedApps() {
- return emptySet();
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
similarity index 62%
rename from quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt
rename to quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
index d4bef28..0946caf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
@@ -13,37 +13,44 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.launcher3.taskbar
import android.app.ActivityManager.RunningTaskInfo
import android.app.WindowConfiguration
-import android.util.Log
-import android.util.SparseArray
import androidx.annotation.VisibleForTesting
-import androidx.core.util.valueIterator
+import com.android.launcher3.Flags.enableRecentsInTaskbar
import com.android.launcher3.model.data.AppInfo
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.statehandlers.DesktopVisibilityController
+import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
import com.android.quickstep.RecentsModel
-import kotlin.collections.filterNotNull
+import com.android.window.flags.Flags.enableDesktopWindowingMode
+import com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps
+import java.io.PrintWriter
/**
- * Shows running apps when in Desktop Mode.
- *
- * Users can enter and exit Desktop Mode at run-time, meaning this class falls back to the default
- * recent-apps behaviour when outside of Desktop Mode.
- *
- * This class should only be used if
- * [com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps] is enabled.
+ * Provides recent apps functionality, when the Taskbar Recent Apps section is enabled. Behavior:
+ * - When in Fullscreen mode: show the N most recent Tasks
+ * - When in Desktop Mode: show the currently running (open) Tasks
*/
-class DesktopTaskbarRunningAppsController(
+class TaskbarRecentAppsController(
private val recentsModel: RecentsModel,
// Pass a provider here instead of the actual DesktopVisibilityController instance since that
// instance might not be available when this constructor is called.
private val desktopVisibilityControllerProvider: () -> DesktopVisibilityController?,
-) : TaskbarRecentAppsController() {
+) : LoggableTaskbarController {
+
+ // TODO(b/335401172): unify DesktopMode checks in Launcher.
+ val canShowRunningApps =
+ enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()
+
+ // TODO(b/343532825): Add a setting to disable Recents even when the flag is on.
+ @VisibleForTesting
+ var isEnabled = enableRecentsInTaskbar() || canShowRunningApps
+
+ // Initialized in init.
+ private lateinit var controllers: TaskbarControllers
private var apps: Array<AppInfo>? = null
private var allRunningDesktopAppInfos: List<AppInfo>? = null
@@ -55,22 +62,40 @@
private val isInDesktopMode: Boolean
get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false
- override fun onDestroy() {
- super.onDestroy()
+ val runningApps: Set<String>
+ get() {
+ if (!isEnabled || !isInDesktopMode) {
+ return emptySet()
+ }
+ return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
+ }
+
+ val minimizedApps: Set<String>
+ get() {
+ if (!isInDesktopMode) {
+ return emptySet()
+ }
+ return allMinimizedDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet()
+ ?: emptySet()
+ }
+
+ fun init(taskbarControllers: TaskbarControllers) {
+ controllers = taskbarControllers
+ }
+
+ fun onDestroy() {
apps = null
}
- @VisibleForTesting
- public override fun setApps(apps: Array<AppInfo>?) {
+ /** Stores the current [AppInfo] instances, no-op except in desktop environment. */
+ fun setApps(apps: Array<AppInfo>?) {
this.apps = apps
}
- override fun isEnabled() = true
-
- @VisibleForTesting
- public override fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo?>): Array<ItemInfo?> {
- if (!isInDesktopMode) {
- Log.d(TAG, "updateHotseatItemInfos: not in Desktop Mode")
+ /** Called to update hotseatItems, in order to de-dupe them from Recent/Running tasks later. */
+ // TODO(next CL): add new section of Tasks instead of changing Hotseat items
+ fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo?>): Array<ItemInfo?> {
+ if (!isEnabled || !isInDesktopMode) {
return hotseatItems
}
val newHotseatItemInfos =
@@ -89,55 +114,6 @@
return newHotseatItemInfos.toTypedArray()
}
- override fun getRunningApps(): Set<String> {
- if (!isInDesktopMode) {
- return emptySet()
- }
- return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
- }
-
- override fun getMinimizedApps(): Set<String> {
- if (!isInDesktopMode) {
- return emptySet()
- }
- return allMinimizedDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
- }
-
- @VisibleForTesting
- public override fun updateRunningApps() {
- if (!isInDesktopMode) {
- Log.d(TAG, "updateRunningApps: not in Desktop Mode")
- mControllers.taskbarViewController.commitRunningAppsToUI()
- return
- }
- val runningTasks = getDesktopRunningTasks()
- val runningAppInfo = getAppInfosFromRunningTasks(runningTasks)
- allRunningDesktopAppInfos = runningAppInfo
- updateMinimizedApps(runningTasks, runningAppInfo)
- mControllers.taskbarViewController.commitRunningAppsToUI()
- }
-
- private fun updateMinimizedApps(
- runningTasks: List<RunningTaskInfo>,
- runningAppInfo: List<AppInfo>,
- ) {
- val allRunningAppTasks =
- runningAppInfo
- .mapNotNull { appInfo -> appInfo.targetPackage?.let { appInfo to it } }
- .associate { (appInfo, targetPackage) ->
- appInfo to
- runningTasks
- .filter { it.realActivity?.packageName == targetPackage }
- .map { it.taskId }
- }
- val minimizedTaskIds = runningTasks.associate { it.taskId to !it.isVisible }
- allMinimizedDesktopAppInfos =
- allRunningAppTasks
- .filterValues { taskIds -> taskIds.all { minimizedTaskIds[it] ?: false } }
- .keys
- .toList()
- }
-
private fun getRunningDesktopAppInfosExceptHotseatApps(
allRunningDesktopAppInfos: List<AppInfo>,
hotseatItems: List<ItemInfo>
@@ -165,12 +141,43 @@
.filterNotNull()
}
- private fun getAppInfosFromRunningTask(task: RunningTaskInfo): AppInfo? =
- apps?.firstOrNull { it.targetPackage == task.realActivity?.packageName }
+ /** Called to update the list of currently running apps, no-op except in desktop environment. */
+ fun updateRunningApps() {
+ if (!isEnabled || !isInDesktopMode) {
+ return controllers.taskbarViewController.commitRunningAppsToUI()
+ }
+ val runningTasks = getDesktopRunningTasks()
+ val runningAppInfo = getAppInfosFromRunningTasks(runningTasks)
+ allRunningDesktopAppInfos = runningAppInfo
+ updateMinimizedApps(runningTasks, runningAppInfo)
+ controllers.taskbarViewController.commitRunningAppsToUI()
+ }
- private fun <E> SparseArray<E>.toList(): List<E> = valueIterator().asSequence().toList()
+ private fun updateMinimizedApps(
+ runningTasks: List<RunningTaskInfo>,
+ runningAppInfo: List<AppInfo>,
+ ) {
+ val allRunningAppTasks =
+ runningAppInfo
+ .mapNotNull { appInfo -> appInfo.targetPackage?.let { appInfo to it } }
+ .associate { (appInfo, targetPackage) ->
+ appInfo to
+ runningTasks
+ .filter { it.realActivity?.packageName == targetPackage }
+ .map { it.taskId }
+ }
+ val minimizedTaskIds = runningTasks.associate { it.taskId to !it.isVisible }
+ allMinimizedDesktopAppInfos =
+ allRunningAppTasks
+ .filterValues { taskIds -> taskIds.all { minimizedTaskIds[it] ?: false } }
+ .keys
+ .toList()
+ }
- companion object {
- private const val TAG = "TabletDesktopTaskbarRunningAppsController"
+ override fun dumpLogs(prefix: String, pw: PrintWriter) {
+ pw.println("$prefix TaskbarRecentAppsController:")
+ pw.println("$prefix\tisEnabled=$isEnabled")
+ pw.println("$prefix\tcanShowRunningApps=$canShowRunningApps")
+ // TODO(next CL): add more logs
}
}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
similarity index 82%
rename from quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt
rename to quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
index 5b56710..104263a 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsControllerTest.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarRecentAppsControllerTest.kt
@@ -37,7 +37,7 @@
import org.mockito.kotlin.whenever
@RunWith(AndroidTestingRunner::class)
-class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
+class TaskbarRecentAppsControllerTest : TaskbarBaseTestCase() {
@get:Rule val mockitoRule = MockitoJUnit.rule()
@@ -46,19 +46,18 @@
private var nextTaskId: Int = 500
- private lateinit var taskbarRunningAppsController: DesktopTaskbarRunningAppsController
+ private lateinit var recentAppsController: TaskbarRecentAppsController
private lateinit var userHandle: UserHandle
@Before
fun setUp() {
super.setup()
userHandle = Process.myUserHandle()
- taskbarRunningAppsController =
- DesktopTaskbarRunningAppsController(mockRecentsModel) {
- mockDesktopVisibilityController
- }
- taskbarRunningAppsController.init(taskbarControllers)
- taskbarRunningAppsController.setApps(
+ recentAppsController =
+ TaskbarRecentAppsController(mockRecentsModel) { mockDesktopVisibilityController }
+ recentAppsController.init(taskbarControllers)
+ recentAppsController.isEnabled = true
+ recentAppsController.setApps(
ALL_APP_PACKAGES.map { createTestAppInfo(packageName = it) }.toTypedArray()
)
}
@@ -69,7 +68,7 @@
val hotseatItems =
createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2))
- assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
+ assertThat(recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
.isEqualTo(hotseatItems.toTypedArray())
}
@@ -81,10 +80,10 @@
val runningTasks =
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
val newHotseatItems =
- taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
+ recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
assertThat(newHotseatItems.map { it?.targetPackage })
.containsExactlyElementsIn(hotseatPackages)
@@ -96,7 +95,7 @@
val hotseatItems =
createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2))
- assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
+ assertThat(recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
.isEqualTo(hotseatItems.toTypedArray())
}
@@ -108,10 +107,10 @@
val runningTasks =
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
val newHotseatItems =
- taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
+ recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
val expectedPackages =
listOf(
@@ -134,10 +133,10 @@
listOf(HOTSEAT_PACKAGE_1, RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
)
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
val newHotseatItems =
- taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
+ recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
val expectedPackages =
listOf(
@@ -156,10 +155,10 @@
val runningTasks =
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
- assertThat(taskbarRunningAppsController.runningApps).isEmpty()
- assertThat(taskbarRunningAppsController.minimizedApps).isEmpty()
+ assertThat(recentAppsController.runningApps).isEmpty()
+ assertThat(recentAppsController.minimizedApps).isEmpty()
}
@Test
@@ -168,11 +167,11 @@
val runningTasks =
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
- assertThat(taskbarRunningAppsController.runningApps)
+ assertThat(recentAppsController.runningApps)
.containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
- assertThat(taskbarRunningAppsController.minimizedApps).isEmpty()
+ assertThat(recentAppsController.minimizedApps).isEmpty()
}
@Test
@@ -187,12 +186,11 @@
)
)
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
- taskbarRunningAppsController.updateRunningApps()
+ recentAppsController.updateRunningApps()
- assertThat(taskbarRunningAppsController.runningApps)
+ assertThat(recentAppsController.runningApps)
.containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2, RUNNING_APP_PACKAGE_3)
- assertThat(taskbarRunningAppsController.minimizedApps)
- .containsExactly(RUNNING_APP_PACKAGE_3)
+ assertThat(recentAppsController.minimizedApps).containsExactly(RUNNING_APP_PACKAGE_3)
}
private fun createHotseatItemsFromPackageNames(packageNames: List<String>): List<ItemInfo> {