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> {