mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-03 09:26:51 +00:00
Fixes two issues:
1. TaskbarRecentAppsController was reflecting tasks from the first
DesktopTasks it found in the RecentsModel - this does not work in
multi-display environemnt where each display may have a separate
DesktopTask. The CL updates the logic to gather tasks from all
available DesktopTasks.
2. RecentsModel supported a single recent apps changed listener. In
multi-display, each display has its own taskbar, and thus its own
TaskbarRecentAppsController, each of which needs to listen for
RecentsModel changes. This meant that second taskbar that registered
a listener was clearing out the listener set by the first taskbar.
Bug: 406183146
Flag: com.android.window.flags.enable_taskbar_connected_displays
Test: On multidisplay, open apps on different displays. Taskbar reflects
all running desktop tasks regardless of the display on which
they're open.
Change-Id: I1dd750e5bcd58d8d90b7b859053e2616c7d18441
1178 lines
50 KiB
Kotlin
1178 lines
50 KiB
Kotlin
/*
|
|
* 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.launcher3.taskbar
|
|
|
|
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
|
|
import android.content.ComponentName
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.res.Resources
|
|
import android.graphics.Rect
|
|
import android.os.Process
|
|
import android.os.UserHandle
|
|
import android.platform.test.annotations.EnableFlags
|
|
import android.view.Display.DEFAULT_DISPLAY
|
|
import androidx.test.annotation.UiThreadTest
|
|
import com.android.internal.R
|
|
import com.android.launcher3.BubbleTextView.RunningAppState
|
|
import com.android.launcher3.Flags
|
|
import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
|
|
import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION
|
|
import com.android.launcher3.model.data.AppInfo
|
|
import com.android.launcher3.model.data.ItemInfo
|
|
import com.android.launcher3.model.data.TaskItemInfo
|
|
import com.android.launcher3.model.data.WorkspaceItemInfo
|
|
import com.android.launcher3.taskbar.TaskbarRecentAppsController.TaskState
|
|
import com.android.launcher3.util.LauncherMultivalentJUnit
|
|
import com.android.quickstep.RecentsModel
|
|
import com.android.quickstep.RecentsModel.RecentTasksChangedListener
|
|
import com.android.quickstep.TaskIconCache
|
|
import com.android.quickstep.util.DesktopTask
|
|
import com.android.quickstep.util.GroupTask
|
|
import com.android.quickstep.util.SingleTask
|
|
import com.android.quickstep.util.SplitTask
|
|
import com.android.systemui.shared.recents.model.Task
|
|
import com.android.wm.shell.shared.split.SplitBounds
|
|
import com.android.wm.shell.shared.split.SplitScreenConstants
|
|
import com.google.common.truth.Truth.assertThat
|
|
import java.util.function.Consumer
|
|
import org.junit.Before
|
|
import org.junit.Rule
|
|
import org.junit.Test
|
|
import org.junit.rules.TestWatcher
|
|
import org.junit.runner.Description
|
|
import org.junit.runner.RunWith
|
|
import org.mockito.ArgumentCaptor
|
|
import org.mockito.Mock
|
|
import org.mockito.junit.MockitoJUnit
|
|
import org.mockito.kotlin.any
|
|
import org.mockito.kotlin.doAnswer
|
|
import org.mockito.kotlin.never
|
|
import org.mockito.kotlin.times
|
|
import org.mockito.kotlin.verify
|
|
import org.mockito.kotlin.whenever
|
|
|
|
@UiThreadTest
|
|
@RunWith(LauncherMultivalentJUnit::class)
|
|
@EnableFlags(Flags.FLAG_ENABLE_MULTI_INSTANCE_MENU_TASKBAR)
|
|
class TaskbarRecentAppsControllerTest : TaskbarBaseTestCase() {
|
|
|
|
@get:Rule val mockitoRule = MockitoJUnit.rule()
|
|
@get:Rule
|
|
val disableControllerForCertainTestsWatcher =
|
|
object : TestWatcher() {
|
|
override fun starting(description: Description) {
|
|
// Update canShowRunningAndRecentAppsAtInit before setUp() is called for each test.
|
|
canShowRunningAndRecentAppsAtInit =
|
|
description.methodName !in
|
|
listOf("canShowRunningAndRecentAppsAtInitIsFalse_getTasksNeverCalled")
|
|
}
|
|
}
|
|
|
|
@Mock private lateinit var mockIconCache: TaskIconCache
|
|
@Mock private lateinit var mockRecentsModel: RecentsModel
|
|
@Mock private lateinit var mockContext: Context
|
|
@Mock private lateinit var mockResources: Resources
|
|
|
|
private var taskListChangeId: Int = 1
|
|
|
|
private lateinit var recentAppsController: TaskbarRecentAppsController
|
|
private lateinit var myUserHandle: UserHandle
|
|
private val USER_HANDLE_1 = UserHandle.of(1)
|
|
private val USER_HANDLE_2 = UserHandle.of(2)
|
|
|
|
private var canShowRunningAndRecentAppsAtInit = true
|
|
private var recentTasksChangedListener: RecentTasksChangedListener? = null
|
|
|
|
val recentShownTasks: List<Task>
|
|
get() = recentAppsController.shownTasks.flatMap { it.tasks }
|
|
|
|
@Before
|
|
fun setUp() {
|
|
super.setup()
|
|
myUserHandle = Process.myUserHandle()
|
|
|
|
// Set desktop mode supported
|
|
whenever(mockContext.getResources()).thenReturn(mockResources)
|
|
whenever(mockResources.getBoolean(R.bool.config_isDesktopModeSupported)).thenReturn(true)
|
|
|
|
whenever(mockRecentsModel.iconCache).thenReturn(mockIconCache)
|
|
whenever(mockRecentsModel.unregisterRecentTasksChangedListener(any())).then {
|
|
recentTasksChangedListener = null
|
|
it
|
|
}
|
|
recentAppsController = TaskbarRecentAppsController(mockContext, mockRecentsModel)
|
|
recentAppsController.canShowRunningApps = canShowRunningAndRecentAppsAtInit
|
|
recentAppsController.canShowRecentApps = canShowRunningAndRecentAppsAtInit
|
|
recentAppsController.init(taskbarControllers, emptyList())
|
|
taskbarControllers.onPostInit()
|
|
|
|
recentTasksChangedListener =
|
|
if (canShowRunningAndRecentAppsAtInit) {
|
|
val listenerCaptor = ArgumentCaptor.forClass(RecentTasksChangedListener::class.java)
|
|
verify(mockRecentsModel)
|
|
.registerRecentTasksChangedListener(listenerCaptor.capture())
|
|
listenerCaptor.value
|
|
} else {
|
|
verify(mockRecentsModel, never()).registerRecentTasksChangedListener(any())
|
|
null
|
|
}
|
|
|
|
// Make sure updateHotseatItemInfos() is called after commitRunningAppsToUI()
|
|
whenever(taskbarViewController.commitRunningAppsToUI()).then {
|
|
recentAppsController.updateHotseatItemInfos(
|
|
recentAppsController.shownHotseatItems.toTypedArray()
|
|
)
|
|
}
|
|
}
|
|
|
|
// See the TestWatcher rule at the top which sets canShowRunningAndRecentAppsAtInit = false.
|
|
@Test
|
|
fun canShowRunningAndRecentAppsAtInitIsFalse_getTasksNeverCalled() {
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2),
|
|
runningTasks = listOf(createTask(1, RUNNING_APP_PACKAGE_1)),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
|
)
|
|
verify(mockRecentsModel, never()).getTasks(any<Consumer<List<GroupTask>>>())
|
|
}
|
|
|
|
@Test
|
|
fun canShowRunningAndRecentAppsIsFalseAfterInit_getTasksOnlyCalledInInit() {
|
|
// getTasks() should have been called once from init().
|
|
verify(mockRecentsModel, times(1)).getTasks(any<Consumer<List<GroupTask>>>(), any())
|
|
recentAppsController.canShowRunningApps = false
|
|
recentAppsController.canShowRecentApps = false
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2),
|
|
runningTasks = listOf(createTask(1, RUNNING_APP_PACKAGE_1)),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
|
)
|
|
// Verify that getTasks() was not called again after the init().
|
|
verify(mockRecentsModel, times(1)).getTasks(any<Consumer<List<GroupTask>>>(), any())
|
|
}
|
|
|
|
@Test
|
|
fun getDesktopItemState_nullItemInfo_returnsNotRunning() {
|
|
setInDesktopMode(true)
|
|
val taskState = recentAppsController.getDesktopItemState(/* itemInfo= */ null)
|
|
assertThat(taskState).isEqualTo(TaskState(RunningAppState.NOT_RUNNING))
|
|
}
|
|
|
|
@Test
|
|
fun getDesktopItemState_noItemPackage_returnsNotRunning() {
|
|
setInDesktopMode(true)
|
|
val taskState = recentAppsController.getDesktopItemState(ItemInfo())
|
|
assertThat(taskState).isEqualTo(TaskState(RunningAppState.NOT_RUNNING))
|
|
}
|
|
|
|
@Test
|
|
fun getDesktopItemState_noMatchingTasks_returnsNotRunning() {
|
|
setInDesktopMode(true)
|
|
val taskState = recentAppsController.getDesktopItemState(createItemInfo("package"))
|
|
assertThat(taskState).isEqualTo(TaskState(RunningAppState.NOT_RUNNING))
|
|
}
|
|
|
|
@Test
|
|
fun getDesktopItemState_matchingVisibleTask_returnsVisible() {
|
|
setInDesktopMode(true)
|
|
val visibleTask =
|
|
PerDisplayRunningApps(
|
|
listOf(createTask(id = 1, "visiblePackage", isVisible = true)),
|
|
DEFAULT_DISPLAY,
|
|
)
|
|
updateRecentTasks(runningTasks = listOf(visibleTask), recentTaskPackages = emptyList())
|
|
|
|
val taskState = recentAppsController.getDesktopItemState(createItemInfo("visiblePackage"))
|
|
|
|
assertThat(taskState).isEqualTo(TaskState(RunningAppState.RUNNING, taskId = 1))
|
|
}
|
|
|
|
@Test
|
|
fun getDesktopItemState_matchingVisibleTaskOnSecondaryDisplay_returnsVisible() {
|
|
setInDesktopMode(true)
|
|
val visibleTask1 =
|
|
PerDisplayRunningApps(
|
|
listOf(createTask(id = 1, "visiblePackage1", isVisible = false)),
|
|
DEFAULT_DISPLAY,
|
|
)
|
|
val visibleTask2 =
|
|
PerDisplayRunningApps(
|
|
listOf(createTask(id = 2, "visiblePackage2", isVisible = true)),
|
|
DEFAULT_DISPLAY + 1,
|
|
)
|
|
updateRecentTasks(
|
|
runningTasks = listOf(visibleTask1, visibleTask2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
val taskState = recentAppsController.getDesktopItemState(createItemInfo("visiblePackage2"))
|
|
|
|
assertThat(taskState).isEqualTo(TaskState(RunningAppState.RUNNING, taskId = 2))
|
|
}
|
|
|
|
@Test
|
|
fun getDesktopItemState_matchingMinimizedTask_returnsMinimized() {
|
|
setInDesktopMode(true)
|
|
val minimizedTask =
|
|
PerDisplayRunningApps(
|
|
listOf(createTask(id = 1, "minimizedPackage", isVisible = false)),
|
|
DEFAULT_DISPLAY,
|
|
)
|
|
updateRecentTasks(runningTasks = listOf(minimizedTask), recentTaskPackages = emptyList())
|
|
|
|
val taskState = recentAppsController.getDesktopItemState(createItemInfo("minimizedPackage"))
|
|
|
|
assertThat(taskState).isEqualTo(TaskState(RunningAppState.MINIMIZED, taskId = 1))
|
|
}
|
|
|
|
@Test
|
|
fun getDesktopItemState_matchingMinimizedTaskOnSecondaryDisplay_returnsVisible() {
|
|
setInDesktopMode(true)
|
|
val visibleTask1 =
|
|
PerDisplayRunningApps(
|
|
listOf(createTask(id = 1, "visiblePackage1", isVisible = false)),
|
|
DEFAULT_DISPLAY,
|
|
)
|
|
val visibleTask2 =
|
|
PerDisplayRunningApps(
|
|
listOf(createTask(id = 2, "visiblePackage2", isVisible = false)),
|
|
DEFAULT_DISPLAY + 1,
|
|
)
|
|
updateRecentTasks(
|
|
runningTasks = listOf(visibleTask1, visibleTask2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
val taskState = recentAppsController.getDesktopItemState(createItemInfo("visiblePackage2"))
|
|
|
|
assertThat(taskState).isEqualTo(TaskState(RunningAppState.MINIMIZED, taskId = 2))
|
|
}
|
|
|
|
@Test
|
|
fun getDesktopItemState_matchingMinimizedAndRunningTask_returnsVisible() {
|
|
setInDesktopMode(true)
|
|
updateRecentTasks(
|
|
runningTasks =
|
|
listOf(
|
|
PerDisplayRunningApps(
|
|
listOf(
|
|
createTask(id = 1, "package", isVisible = false),
|
|
createTask(id = 2, "package", isVisible = true),
|
|
),
|
|
DEFAULT_DISPLAY,
|
|
)
|
|
),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
val taskState = recentAppsController.getDesktopItemState(createItemInfo("package"))
|
|
|
|
assertThat(taskState).isEqualTo(TaskState(RunningAppState.RUNNING, taskId = 2))
|
|
}
|
|
|
|
@Test
|
|
fun getDesktopItemState_noMatchingUserId_returnsNotRunning() {
|
|
setInDesktopMode(true)
|
|
updateRecentTasks(
|
|
runningTasks =
|
|
listOf(
|
|
PerDisplayRunningApps(
|
|
listOf(
|
|
createTask(id = 1, "package", isVisible = false, USER_HANDLE_1),
|
|
createTask(id = 2, "package", isVisible = true, USER_HANDLE_1),
|
|
),
|
|
DEFAULT_DISPLAY,
|
|
)
|
|
),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
val taskState =
|
|
recentAppsController.getDesktopItemState(createItemInfo("package", USER_HANDLE_2))
|
|
|
|
assertThat(taskState).isEqualTo(TaskState(RunningAppState.NOT_RUNNING))
|
|
}
|
|
|
|
@Test
|
|
fun getRunningAppState_taskNotRunningOrMinimized_returnsNotRunning() {
|
|
setInDesktopMode(true)
|
|
updateRecentTasks(runningTasks = emptyList(), recentTaskPackages = emptyList())
|
|
|
|
assertThat(recentAppsController.getRunningAppState(taskId = 1))
|
|
.isEqualTo(RunningAppState.NOT_RUNNING)
|
|
}
|
|
|
|
@Test
|
|
fun getRunningAppState_taskNotVisible_returnsMinimized() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, packageName = RUNNING_APP_PACKAGE_1, isVisible = false)
|
|
val task2 = createTask(id = 2, packageName = RUNNING_APP_PACKAGE_1, isVisible = true)
|
|
updateRecentTasks(
|
|
runningTasks = listOf(PerDisplayRunningApps(listOf(task1, task2), DEFAULT_DISPLAY)),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
assertThat(recentAppsController.getRunningAppState(taskId = 1))
|
|
.isEqualTo(RunningAppState.MINIMIZED)
|
|
}
|
|
|
|
@Test
|
|
fun getRunningAppState_taskNotVisible_returnsMinimizedForSecondaryDisplay() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, packageName = RUNNING_APP_PACKAGE_1, isVisible = false)
|
|
val task2 = createTask(id = 2, packageName = RUNNING_APP_PACKAGE_1, isVisible = true)
|
|
val task3 = createTask(id = 3, packageName = RUNNING_APP_PACKAGE_3, isVisible = false)
|
|
updateRecentTasks(
|
|
runningTasks =
|
|
listOf(
|
|
PerDisplayRunningApps(listOf(task1, task2), DEFAULT_DISPLAY),
|
|
PerDisplayRunningApps(listOf(task3), DEFAULT_DISPLAY + 1),
|
|
),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
assertThat(recentAppsController.getRunningAppState(taskId = 3))
|
|
.isEqualTo(RunningAppState.MINIMIZED)
|
|
}
|
|
|
|
@Test
|
|
fun getRunningAppState_taskVisible_returnsRunningForSecondaryDisplay() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, packageName = RUNNING_APP_PACKAGE_1, isVisible = false)
|
|
val task2 = createTask(id = 2, packageName = RUNNING_APP_PACKAGE_1, isVisible = true)
|
|
val task3 = createTask(id = 3, packageName = RUNNING_APP_PACKAGE_3, isVisible = true)
|
|
updateRecentTasks(
|
|
runningTasks =
|
|
listOf(
|
|
PerDisplayRunningApps(listOf(task1, task2), DEFAULT_DISPLAY),
|
|
PerDisplayRunningApps(listOf(task3), DEFAULT_DISPLAY + 1),
|
|
),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
assertThat(recentAppsController.getRunningAppState(taskId = 3))
|
|
.isEqualTo(RunningAppState.RUNNING)
|
|
}
|
|
|
|
@Test
|
|
fun updateHotseatItemInfos_cantShowRunning_inDesktopMode_returnsAllHotseatItems() {
|
|
recentAppsController.canShowRunningApps = false
|
|
setInDesktopMode(true)
|
|
val hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2, PREDICTED_PACKAGE_1)
|
|
val newHotseatItems =
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = hotseatPackages,
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(newHotseatItems.map { it?.targetPackage })
|
|
.containsExactlyElementsIn(hotseatPackages)
|
|
}
|
|
|
|
@Test
|
|
fun updateHotseatItemInfos_cantShowRecent_notInDesktopMode_returnsAllHotseatItems() {
|
|
recentAppsController.canShowRecentApps = false
|
|
setInDesktopMode(false)
|
|
val hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2, PREDICTED_PACKAGE_1)
|
|
val newHotseatItems =
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = hotseatPackages,
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(newHotseatItems.map { it?.targetPackage })
|
|
.containsExactlyElementsIn(hotseatPackages)
|
|
}
|
|
|
|
@Test
|
|
fun updateHotseatItemInfos_canShowRunning_inDesktopMode_returnsNonPredictedHotseatItems() {
|
|
recentAppsController.canShowRunningApps = true
|
|
setInDesktopMode(true)
|
|
val newHotseatItems =
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2, PREDICTED_PACKAGE_1),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
val expectedPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2)
|
|
assertThat(newHotseatItems.map { it?.targetPackage })
|
|
.containsExactlyElementsIn(expectedPackages)
|
|
}
|
|
|
|
@Test
|
|
fun updateHotseatItemInfos_inDesktopMode_hotseatPackageHasRunningTask_hotseatItemLinksToTask() {
|
|
setInDesktopMode(true)
|
|
|
|
val newHotseatItems =
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2),
|
|
runningTasks = listOf(createTask(id = 1, HOTSEAT_PACKAGE_1)),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
assertThat(newHotseatItems).hasLength(2)
|
|
assertThat(newHotseatItems[0]).isInstanceOf(TaskItemInfo::class.java)
|
|
assertThat(newHotseatItems[1]).isNotInstanceOf(TaskItemInfo::class.java)
|
|
val hotseatItem1 = newHotseatItems[0] as TaskItemInfo
|
|
assertThat(hotseatItem1.taskId).isEqualTo(1)
|
|
}
|
|
|
|
/**
|
|
* Tests that in desktop mode, when two tasks have the same package name and one is in the
|
|
* hotseat, only the hotseat item represents the app, and no duplicate is shown in recent apps.
|
|
*/
|
|
@Test
|
|
fun updateHotseatItemInfos_inDesktopMode_twoRunningTasksSamePackage_onlyHotseatCoversTask() {
|
|
setInDesktopMode(true)
|
|
|
|
val newHotseatItems =
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2),
|
|
runningTasks =
|
|
listOf(
|
|
createTask(id = 1, HOTSEAT_PACKAGE_1),
|
|
createTask(id = 2, HOTSEAT_PACKAGE_1),
|
|
),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
// The task is in Hotseat Items
|
|
assertThat(newHotseatItems).hasLength(2)
|
|
assertThat(newHotseatItems[0]).isInstanceOf(TaskItemInfo::class.java)
|
|
assertThat(newHotseatItems[1]).isNotInstanceOf(TaskItemInfo::class.java)
|
|
val hotseatItem1 = newHotseatItems[0] as TaskItemInfo
|
|
assertThat(hotseatItem1.targetPackage).isEqualTo(HOTSEAT_PACKAGE_1)
|
|
|
|
// The other task of the same package is not in recentShownTasks
|
|
assertThat(recentShownTasks).isEmpty()
|
|
}
|
|
|
|
@Test
|
|
fun updateHotseatItemInfos_canShowRecent_notInDesktopMode_returnsNonPredictedHotseatItems() {
|
|
recentAppsController.canShowRecentApps = true
|
|
setInDesktopMode(false)
|
|
val newHotseatItems =
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2, PREDICTED_PACKAGE_1),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
val expectedPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2)
|
|
assertThat(newHotseatItems.map { it?.targetPackage })
|
|
.containsExactlyElementsIn(expectedPackages)
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_cantShowRunning_inDesktopMode_shownTasks_returnsEmptyList() {
|
|
recentAppsController.canShowRunningApps = false
|
|
setInDesktopMode(true)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2, PREDICTED_PACKAGE_1),
|
|
runningTasks =
|
|
listOf(
|
|
createTask(id = 1, RUNNING_APP_PACKAGE_1),
|
|
createTask(id = 2, RUNNING_APP_PACKAGE_2),
|
|
),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentAppsController.shownTasks).isEmpty()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_cantShowRecent_notInDesktopMode_shownTasks_returnsEmptyList() {
|
|
recentAppsController.canShowRecentApps = false
|
|
setInDesktopMode(false)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2, PREDICTED_PACKAGE_1),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
|
)
|
|
assertThat(recentAppsController.shownTasks).isEmpty()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_notInDesktopMode_noRecentTasks_shownTasks_returnsEmptyList() {
|
|
setInDesktopMode(false)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks =
|
|
listOf(
|
|
createTask(id = 1, RUNNING_APP_PACKAGE_1),
|
|
createTask(id = 2, RUNNING_APP_PACKAGE_2),
|
|
),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentAppsController.shownTasks).isEmpty()
|
|
assertThat(recentAppsController.minimizedTaskIds).isEmpty()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_noRunningApps_shownTasks_returnsEmptyList() {
|
|
setInDesktopMode(true)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
|
)
|
|
assertThat(recentAppsController.shownTasks).isEmpty()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_shownTasks_returnsRunningTasks() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val task2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1, task2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentShownTasks).containsExactlyElementsIn(listOf(task1, task2))
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_notInDesktopMode_getRunningApps_returnsEmptySet() {
|
|
setInDesktopMode(false)
|
|
val task1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val task2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1, task2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentAppsController.runningTaskIds).isEmpty()
|
|
assertThat(recentAppsController.minimizedTaskIds).isEmpty()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_getRunningApps_returnsAllDesktopTasks() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val task2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1, task2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentAppsController.runningTaskIds).containsExactlyElementsIn(listOf(1, 2))
|
|
assertThat(recentAppsController.minimizedTaskIds).isEmpty()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_getRunningApps_includesHotseat() {
|
|
setInDesktopMode(true)
|
|
val runningTasks =
|
|
listOf(
|
|
createTask(id = 1, HOTSEAT_PACKAGE_1),
|
|
createTask(id = 2, RUNNING_APP_PACKAGE_1),
|
|
createTask(id = 3, RUNNING_APP_PACKAGE_2),
|
|
)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2),
|
|
runningTasks = runningTasks,
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
|
)
|
|
assertThat(recentAppsController.runningTaskIds).containsExactlyElementsIn(listOf(1, 2, 3))
|
|
assertThat(recentAppsController.minimizedTaskIds).isEmpty()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_allAppsRunningAndInvisibleAppsMinimized() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val task2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
val task3Minimized = createTask(id = 3, RUNNING_APP_PACKAGE_3, isVisible = false)
|
|
val runningTasks = listOf(task1, task2, task3Minimized)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = runningTasks,
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentAppsController.runningTaskIds).containsExactly(1, 2, 3)
|
|
assertThat(recentAppsController.minimizedTaskIds).containsExactly(3)
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_samePackage_differentTasks_severalRunningTasks() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val task2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1, task2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentAppsController.runningTaskIds).containsExactlyElementsIn(listOf(1, 2))
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_shownTasks_maintainsOrder() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val task2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1, task2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task2, task1),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
assertThat(recentShownTasks).isEqualTo(listOf(task1, task2))
|
|
}
|
|
|
|
/**
|
|
* Tests that when multiple instances of the same app are running in desktop mode and the app is
|
|
* not in the hotseat, only one instance is shown in the recent apps section.
|
|
*/
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_multiInstance_noHotseat_shownTasksHasOneInstance() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val task2 = createTask(id = 2, RUNNING_APP_PACKAGE_1)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1, task2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
// Assert that recentShownTasks contains only one instance of the app
|
|
assertThat(recentShownTasks).hasSize(1)
|
|
assertThat(recentShownTasks[0].key.packageName).isEqualTo(RUNNING_APP_PACKAGE_1)
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_notInDesktopMode_shownTasks_maintainsRecency() {
|
|
setInDesktopMode(false)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2, RECENT_PACKAGE_3),
|
|
)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_2, RECENT_PACKAGE_3, RECENT_PACKAGE_1),
|
|
)
|
|
val shownPackages = recentAppsController.shownTasks.flatMap { it.packageNames }
|
|
// Most recent packages, minus the currently running one (RECENT_PACKAGE_1).
|
|
assertThat(shownPackages).isEqualTo(listOf(RECENT_PACKAGE_2, RECENT_PACKAGE_3))
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_addTask_shownTasks_maintainsOrder() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val task2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
val task3 = createTask(id = 3, RUNNING_APP_PACKAGE_3)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1, task2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task2, task1, task3),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
val shownPackages = recentAppsController.shownTasks.flatMap { it.packageNames }
|
|
val expectedOrder =
|
|
listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2, RUNNING_APP_PACKAGE_3)
|
|
assertThat(shownPackages).isEqualTo(expectedOrder)
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_notInDesktopMode_addTask_shownTasks_maintainsRecency() {
|
|
setInDesktopMode(false)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_3, RECENT_PACKAGE_2),
|
|
)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_2, RECENT_PACKAGE_3, RECENT_PACKAGE_1),
|
|
)
|
|
val shownPackages = recentAppsController.shownTasks.flatMap { it.packageNames }
|
|
// Most recent packages, minus the currently running one (RECENT_PACKAGE_1).
|
|
assertThat(shownPackages).isEqualTo(listOf(RECENT_PACKAGE_2, RECENT_PACKAGE_3))
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_removeTask_shownTasks_maintainsOrder() {
|
|
setInDesktopMode(true)
|
|
val task1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val task2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
val task3 = createTask(id = 3, RUNNING_APP_PACKAGE_3)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1, task2, task3),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task2, task1),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
val shownPackages = recentAppsController.shownTasks.flatMap { it.packageNames }
|
|
assertThat(shownPackages).isEqualTo(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_notInDesktopMode_removeTask_shownTasks_maintainsRecency() {
|
|
setInDesktopMode(false)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2, RECENT_PACKAGE_3),
|
|
)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_2, RECENT_PACKAGE_3),
|
|
)
|
|
val shownPackages = recentAppsController.shownTasks.flatMap { it.packageNames }
|
|
// Most recent packages, minus the currently running one (RECENT_PACKAGE_3).
|
|
assertThat(shownPackages).isEqualTo(listOf(RECENT_PACKAGE_2))
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_enterDesktopMode_shownTasks_onlyIncludesRunningTasks() {
|
|
setInDesktopMode(false)
|
|
val runningTask1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val runningTask2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
val recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2)
|
|
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(runningTask1, runningTask2),
|
|
recentTaskPackages = recentTaskPackages,
|
|
)
|
|
|
|
setInDesktopMode(true)
|
|
recentTasksChangedListener!!.onRecentTasksChanged()
|
|
val shownPackages = recentAppsController.shownTasks.flatMap { it.packageNames }
|
|
assertThat(shownPackages).containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_exitDesktopMode_shownTasks_onlyIncludesRecentTasks() {
|
|
setInDesktopMode(true)
|
|
val runningTask1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val runningTask2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
val recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2, RECENT_PACKAGE_3)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(runningTask1, runningTask2),
|
|
recentTaskPackages = recentTaskPackages,
|
|
)
|
|
setInDesktopMode(false)
|
|
recentTasksChangedListener!!.onRecentTasksChanged()
|
|
val shownPackages = recentAppsController.shownTasks.flatMap { it.packageNames }
|
|
// Don't expect RECENT_PACKAGE_3 because it is currently running.
|
|
val expectedPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2)
|
|
assertThat(shownPackages).containsExactlyElementsIn(expectedPackages)
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_notInDesktopMode_hasRecentTasks_shownTasks_returnsRecentTasks() {
|
|
setInDesktopMode(false)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2, RECENT_PACKAGE_3),
|
|
)
|
|
val shownPackages = recentAppsController.shownTasks.flatMap { it.packageNames }
|
|
// RECENT_PACKAGE_3 is the top task (visible to user) so should be excluded.
|
|
val expectedPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2)
|
|
assertThat(shownPackages).containsExactlyElementsIn(expectedPackages)
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_notInDesktopMode_hasRecentAndRunningTasks_shownTasks_returnsRecentTaskAndDesktopTile() {
|
|
setInDesktopMode(false)
|
|
val runningTask1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val runningTask2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(runningTask1, runningTask2),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
|
)
|
|
val shownPackages = recentAppsController.shownTasks.map { it.packageNames }
|
|
// Only 2 recent tasks shown: Desktop Tile + 1 Recent Task
|
|
val desktopTilePackages = listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
|
|
val recentTaskPackages = listOf(RECENT_PACKAGE_1)
|
|
val expectedPackages = listOf(desktopTilePackages, recentTaskPackages)
|
|
assertThat(shownPackages).containsExactlyElementsIn(expectedPackages)
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_notInDesktopMode_hasRecentAndSplitTasks_shownTasks_returnsRecentTaskAndPair() {
|
|
setInDesktopMode(false)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_SPLIT_PACKAGES_1, RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
|
)
|
|
val shownPackages = recentAppsController.shownTasks.map { it.packageNames }
|
|
// Only 2 recent tasks shown: Pair + 1 Recent Task
|
|
val pairPackages = RECENT_SPLIT_PACKAGES_1.split("_")
|
|
val recentTaskPackages = listOf(RECENT_PACKAGE_1)
|
|
val expectedPackages = listOf(pairPackages, recentTaskPackages)
|
|
assertThat(shownPackages).containsExactlyElementsIn(expectedPackages)
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_notInDesktopMode_noActualChangeToRecents_commitRunningAppsToUI_notCalled() {
|
|
setInDesktopMode(false)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
|
)
|
|
verify(taskbarViewController, times(1)).commitRunningAppsToUI()
|
|
// Call onRecentTasksChanged() again with the same tasks, verify it's a no-op.
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = emptyList(),
|
|
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
|
)
|
|
verify(taskbarViewController, times(1)).commitRunningAppsToUI()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_noActualChangeToRunning_commitRunningAppsToUI_notCalled() {
|
|
setInDesktopMode(true)
|
|
val runningTask1 = createTask(id = 1, RUNNING_APP_PACKAGE_1)
|
|
val runningTask2 = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(runningTask1, runningTask2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
verify(taskbarViewController, times(1)).commitRunningAppsToUI()
|
|
// Call onRecentTasksChanged() again with the same tasks, verify it's a no-op.
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(runningTask1, runningTask2),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
verify(taskbarViewController, times(1)).commitRunningAppsToUI()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_onlyMinimizedChanges_commitRunningAppsToUI_isCalled() {
|
|
setInDesktopMode(true)
|
|
val task1Minimized = createTask(id = 1, RUNNING_APP_PACKAGE_1, isVisible = false)
|
|
val task2Visible = createTask(id = 2, RUNNING_APP_PACKAGE_2)
|
|
val task2Minimized = createTask(id = 2, RUNNING_APP_PACKAGE_2, isVisible = false)
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1Minimized, task2Visible),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
verify(taskbarViewController, times(1)).commitRunningAppsToUI()
|
|
|
|
// Call onRecentTasksChanged() again with a new minimized app, verify we update UI.
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = emptyList(),
|
|
runningTasks = listOf(task1Minimized, task2Minimized),
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
verify(taskbarViewController, times(2)).commitRunningAppsToUI()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_hotseatAppStartsRunning_commitRunningAppsToUI_isCalled() {
|
|
setInDesktopMode(true)
|
|
val hotseatPackages = listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2)
|
|
val originalTasks = listOf(createTask(id = 1, RUNNING_APP_PACKAGE_1))
|
|
val newTasks =
|
|
listOf(createTask(id = 1, RUNNING_APP_PACKAGE_1), createTask(id = 2, HOTSEAT_PACKAGE_1))
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = hotseatPackages,
|
|
runningTasks = originalTasks,
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
verify(taskbarViewController, times(1)).commitRunningAppsToUI()
|
|
|
|
// Call onRecentTasksChanged() again with a new running app, verify we update UI.
|
|
prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages = hotseatPackages,
|
|
runningTasks = newTasks,
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
verify(taskbarViewController, times(2)).commitRunningAppsToUI()
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_sameHotseatPackage_differentUser_isInShownTasks() {
|
|
setInDesktopMode(true)
|
|
val hotseatPackageUser = PackageUser(HOTSEAT_PACKAGE_1, USER_HANDLE_2)
|
|
val hotseatPackageUsers = listOf(hotseatPackageUser)
|
|
val runningTask = createTask(id = 1, HOTSEAT_PACKAGE_1, localUserHandle = USER_HANDLE_1)
|
|
val runningTasks = listOf(PerDisplayRunningApps(listOf(runningTask), DEFAULT_DISPLAY))
|
|
prepareHotseatAndRunningAndRecentAppsInternal(
|
|
hotseatPackageUsers = hotseatPackageUsers,
|
|
runningTasks = runningTasks,
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentShownTasks).contains(runningTask)
|
|
assertThat(recentAppsController.runningTaskIds).containsExactlyElementsIn(listOf(1))
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_multipleDesktops() {
|
|
setInDesktopMode(true)
|
|
val hotseatPackageUsers = listOf(PackageUser(HOTSEAT_PACKAGE_1, USER_HANDLE_1))
|
|
val defaultDisplayRunningTask =
|
|
createTask(id = 1, HOTSEAT_PACKAGE_1, localUserHandle = USER_HANDLE_1)
|
|
val secondaryDisplayRunningTask =
|
|
createTask(id = 2, RUNNING_APP_PACKAGE_1, localUserHandle = USER_HANDLE_1)
|
|
val runningTasks =
|
|
listOf(
|
|
PerDisplayRunningApps(listOf(defaultDisplayRunningTask), DEFAULT_DISPLAY),
|
|
PerDisplayRunningApps(listOf(secondaryDisplayRunningTask), DEFAULT_DISPLAY + 1),
|
|
)
|
|
prepareHotseatAndRunningAndRecentAppsInternal(
|
|
hotseatPackageUsers = hotseatPackageUsers,
|
|
runningTasks = runningTasks,
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentShownTasks).containsExactly(secondaryDisplayRunningTask)
|
|
assertThat(recentAppsController.runningTaskIds).containsExactlyElementsIn(listOf(1, 2))
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_multipleDesktops_appsNotInHotseat() {
|
|
setInDesktopMode(true)
|
|
val hotseatPackageUsers = listOf(PackageUser(HOTSEAT_PACKAGE_1, USER_HANDLE_1))
|
|
val defaultDisplayRunningTask =
|
|
createTask(id = 1, RUNNING_APP_PACKAGE_1, localUserHandle = USER_HANDLE_1)
|
|
val secondaryDisplayRunningTask =
|
|
createTask(id = 2, RUNNING_APP_PACKAGE_2, localUserHandle = USER_HANDLE_1)
|
|
val runningTasks =
|
|
listOf(
|
|
PerDisplayRunningApps(listOf(defaultDisplayRunningTask), DEFAULT_DISPLAY),
|
|
PerDisplayRunningApps(listOf(secondaryDisplayRunningTask), DEFAULT_DISPLAY + 1),
|
|
)
|
|
prepareHotseatAndRunningAndRecentAppsInternal(
|
|
hotseatPackageUsers = hotseatPackageUsers,
|
|
runningTasks = runningTasks,
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
assertThat(recentShownTasks)
|
|
.containsExactly(defaultDisplayRunningTask, secondaryDisplayRunningTask)
|
|
assertThat(recentAppsController.runningTaskIds).containsExactlyElementsIn(listOf(1, 2))
|
|
}
|
|
|
|
@Test
|
|
fun onRecentTasksChanged_inDesktopMode_multipleDesktops_multipleAppInstances() {
|
|
setInDesktopMode(true)
|
|
val hotseatPackageUsers = listOf(PackageUser(HOTSEAT_PACKAGE_1, USER_HANDLE_1))
|
|
val defaultDisplayRunningTask1 =
|
|
createTask(id = 1, HOTSEAT_PACKAGE_1, localUserHandle = USER_HANDLE_1)
|
|
val defaultDisplayRunningTask2 =
|
|
createTask(id = 2, RUNNING_APP_PACKAGE_1, localUserHandle = USER_HANDLE_1)
|
|
|
|
val secondaryDisplayRunningTask1 =
|
|
createTask(id = 3, RUNNING_APP_PACKAGE_1, localUserHandle = USER_HANDLE_1)
|
|
val secondaryDisplayRunningTask2 =
|
|
createTask(id = 4, HOTSEAT_PACKAGE_1, localUserHandle = USER_HANDLE_1)
|
|
|
|
val runningTasks =
|
|
listOf(
|
|
PerDisplayRunningApps(
|
|
listOf(defaultDisplayRunningTask1, defaultDisplayRunningTask2),
|
|
DEFAULT_DISPLAY,
|
|
),
|
|
PerDisplayRunningApps(
|
|
listOf(secondaryDisplayRunningTask1, secondaryDisplayRunningTask2),
|
|
DEFAULT_DISPLAY + 1,
|
|
),
|
|
)
|
|
prepareHotseatAndRunningAndRecentAppsInternal(
|
|
hotseatPackageUsers = hotseatPackageUsers,
|
|
runningTasks = runningTasks,
|
|
recentTaskPackages = emptyList(),
|
|
)
|
|
|
|
assertThat(recentShownTasks).hasSize(1)
|
|
assertThat(recentShownTasks)
|
|
.containsAnyOf(defaultDisplayRunningTask2, secondaryDisplayRunningTask1)
|
|
|
|
assertThat(recentAppsController.runningTaskIds)
|
|
.containsExactlyElementsIn(listOf(1, 2, 3, 4))
|
|
}
|
|
|
|
private fun prepareHotseatAndRunningAndRecentApps(
|
|
hotseatPackages: List<String>,
|
|
runningTasks: List<Task>,
|
|
recentTaskPackages: List<String>,
|
|
): Array<ItemInfo?> {
|
|
val hotseatPackageUsers = hotseatPackages.map { PackageUser(it, myUserHandle) }
|
|
return prepareHotseatAndRunningAndRecentAppsInternal(
|
|
hotseatPackageUsers,
|
|
listOf(PerDisplayRunningApps(runningTasks, DEFAULT_DISPLAY)),
|
|
recentTaskPackages,
|
|
)
|
|
}
|
|
|
|
private fun prepareHotseatAndRunningAndRecentAppsInternal(
|
|
hotseatPackageUsers: List<PackageUser>,
|
|
runningTasks: List<PerDisplayRunningApps>,
|
|
recentTaskPackages: List<String>,
|
|
): Array<ItemInfo?> {
|
|
val hotseatItems = createHotseatItemsFromPackageUsers(hotseatPackageUsers)
|
|
recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
|
|
updateRecentTasks(runningTasks, recentTaskPackages)
|
|
return recentAppsController.shownHotseatItems.toTypedArray()
|
|
}
|
|
|
|
private fun updateRecentTasks(
|
|
runningTasks: List<PerDisplayRunningApps>,
|
|
recentTaskPackages: List<String>,
|
|
) {
|
|
val recentTasks = createRecentTasksFromPackageNames(recentTaskPackages)
|
|
val allTasks =
|
|
ArrayList<GroupTask>().apply {
|
|
runningTasks.forEach {
|
|
add(DesktopTask(deskId = 0, it.displayId, ArrayList(it.tasks)))
|
|
}
|
|
addAll(recentTasks)
|
|
}
|
|
doAnswer {
|
|
val callback: Consumer<ArrayList<GroupTask>> = it.getArgument(0)
|
|
callback.accept(allTasks)
|
|
taskListChangeId
|
|
}
|
|
.whenever(mockRecentsModel)
|
|
.getTasks(any<Consumer<List<GroupTask>>>(), any())
|
|
recentTasksChangedListener?.onRecentTasksChanged()
|
|
}
|
|
|
|
private fun createHotseatItemsFromPackageUsers(
|
|
packageUsers: List<PackageUser>
|
|
): List<ItemInfo> {
|
|
return packageUsers
|
|
.map {
|
|
createTestAppInfo(packageName = it.packageName, userHandle = it.userHandle).apply {
|
|
container =
|
|
if (it.packageName.startsWith("predicted")) {
|
|
CONTAINER_HOTSEAT_PREDICTION
|
|
} else {
|
|
CONTAINER_HOTSEAT
|
|
}
|
|
}
|
|
}
|
|
.map { it.makeWorkspaceItem(taskbarActivityContext) }
|
|
}
|
|
|
|
private fun createTestAppInfo(
|
|
packageName: String = "testPackageName",
|
|
className: String = "testClassName",
|
|
userHandle: UserHandle,
|
|
) = AppInfo(ComponentName(packageName, className), className /* title */, userHandle, Intent())
|
|
|
|
private fun createRecentTasksFromPackageNames(packageNames: List<String>): List<GroupTask> {
|
|
return packageNames.map { packageName ->
|
|
if (packageName.startsWith("split")) {
|
|
val splitPackages = packageName.split("_")
|
|
SplitTask(
|
|
createTask(100, splitPackages[0]),
|
|
createTask(101, splitPackages[1]),
|
|
SplitBounds(
|
|
/* leftTopBounds = */ Rect(),
|
|
/* rightBottomBounds = */ Rect(),
|
|
/* leftTopTaskId = */ -1,
|
|
/* rightBottomTaskId = */ -1,
|
|
/* snapPosition = */ SplitScreenConstants.SNAP_TO_2_50_50,
|
|
),
|
|
)
|
|
} else {
|
|
// Use the number at the end of the test packageName as the id.
|
|
val id = 1000 + packageName[packageName.length - 1].code
|
|
SingleTask(createTask(id, packageName))
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun createTask(
|
|
id: Int,
|
|
packageName: String,
|
|
isVisible: Boolean = true,
|
|
localUserHandle: UserHandle? = null,
|
|
): Task {
|
|
return Task(
|
|
Task.TaskKey(
|
|
id,
|
|
WINDOWING_MODE_FREEFORM,
|
|
Intent().apply { `package` = packageName },
|
|
ComponentName(packageName, "TestActivity"),
|
|
localUserHandle?.identifier ?: myUserHandle.identifier,
|
|
0,
|
|
)
|
|
)
|
|
.apply { this.isVisible = isVisible }
|
|
}
|
|
|
|
private fun setInDesktopMode(inDesktopMode: Boolean) {
|
|
whenever(taskbarControllers.taskbarDesktopModeController.shouldShowDesktopTasksInTaskbar())
|
|
.thenReturn(inDesktopMode)
|
|
whenever(taskbarControllers.taskbarDesktopModeController.isInDesktopMode(DEFAULT_DISPLAY))
|
|
.thenReturn(inDesktopMode)
|
|
}
|
|
|
|
private fun createItemInfo(
|
|
packageName: String,
|
|
userHandle: UserHandle = myUserHandle,
|
|
): ItemInfo {
|
|
val appInfo = AppInfo()
|
|
appInfo.intent = Intent().setComponent(ComponentName(packageName, "className"))
|
|
appInfo.user = userHandle
|
|
return WorkspaceItemInfo(appInfo)
|
|
}
|
|
|
|
private val GroupTask.packageNames: List<String>
|
|
get() = tasks.map { task -> task.key.packageName }
|
|
|
|
private companion object {
|
|
const val HOTSEAT_PACKAGE_1 = "hotseat1"
|
|
const val HOTSEAT_PACKAGE_2 = "hotseat2"
|
|
const val PREDICTED_PACKAGE_1 = "predicted1"
|
|
const val RUNNING_APP_PACKAGE_1 = "running1"
|
|
const val RUNNING_APP_PACKAGE_2 = "running2"
|
|
const val RUNNING_APP_PACKAGE_3 = "running3"
|
|
const val RECENT_PACKAGE_1 = "recent1"
|
|
const val RECENT_PACKAGE_2 = "recent2"
|
|
const val RECENT_PACKAGE_3 = "recent3"
|
|
const val RECENT_SPLIT_PACKAGES_1 = "split1_split2"
|
|
}
|
|
|
|
data class PackageUser(val packageName: String, val userHandle: UserHandle)
|
|
|
|
data class PerDisplayRunningApps(val tasks: List<Task>, val displayId: Int)
|
|
}
|