1 package com.android.systemui.mediaprojection.appselector.data
2 
3 import android.app.ActivityManager.RecentTaskInfo
4 import android.testing.AndroidTestingRunner
5 import androidx.test.filters.SmallTest
6 import com.android.systemui.SysuiTestCase
7 import com.android.systemui.settings.UserTracker
8 import com.android.systemui.util.mockito.any
9 import com.android.systemui.util.mockito.mock
10 import com.android.systemui.util.mockito.whenever
11 import com.android.wm.shell.recents.RecentTasks
12 import com.android.wm.shell.util.GroupedRecentTaskInfo
13 import com.google.common.truth.Truth.assertThat
14 import java.util.*
15 import java.util.function.Consumer
16 import kotlinx.coroutines.Dispatchers
17 import kotlinx.coroutines.runBlocking
18 import org.junit.Test
19 import org.junit.runner.RunWith
20 
21 @RunWith(AndroidTestingRunner::class)
22 @SmallTest
23 class ShellRecentTaskListProviderTest : SysuiTestCase() {
24 
25     private val dispatcher = Dispatchers.Unconfined
26     private val recentTasks: RecentTasks = mock()
27     private val userTracker: UserTracker = mock()
28     private val recentTaskListProvider =
29         ShellRecentTaskListProvider(
30             dispatcher,
31             Runnable::run,
32             Optional.of(recentTasks),
33             userTracker
34         )
35 
36     @Test
37     fun loadRecentTasks_oneTask_returnsTheSameTask() {
38         givenRecentTasks(createSingleTask(taskId = 1))
39 
40         val result = runBlocking { recentTaskListProvider.loadRecentTasks() }
41 
42         assertThat(result).containsExactly(createRecentTask(taskId = 1))
43     }
44 
45     @Test
46     fun loadRecentTasks_multipleTasks_returnsTheSameTasks() {
47         givenRecentTasks(
48             createSingleTask(taskId = 1),
49             createSingleTask(taskId = 2),
50             createSingleTask(taskId = 3),
51         )
52 
53         val result = runBlocking { recentTaskListProvider.loadRecentTasks() }
54 
55         assertThat(result)
56             .containsExactly(
57                 createRecentTask(taskId = 1),
58                 createRecentTask(taskId = 2),
59                 createRecentTask(taskId = 3),
60             )
61     }
62 
63     @Test
64     fun loadRecentTasks_groupedTask_returnsUngroupedTasks() {
65         givenRecentTasks(createTaskPair(taskId1 = 1, taskId2 = 2))
66 
67         val result = runBlocking { recentTaskListProvider.loadRecentTasks() }
68 
69         assertThat(result)
70             .containsExactly(createRecentTask(taskId = 1), createRecentTask(taskId = 2))
71     }
72 
73     @Test
74     fun loadRecentTasks_mixedSingleAndGroupedTask_returnsUngroupedTasks() {
75         givenRecentTasks(
76             createSingleTask(taskId = 1),
77             createTaskPair(taskId1 = 2, taskId2 = 3),
78             createSingleTask(taskId = 4),
79             createTaskPair(taskId1 = 5, taskId2 = 6),
80         )
81 
82         val result = runBlocking { recentTaskListProvider.loadRecentTasks() }
83 
84         assertThat(result)
85             .containsExactly(
86                 createRecentTask(taskId = 1),
87                 createRecentTask(taskId = 2),
88                 createRecentTask(taskId = 3),
89                 createRecentTask(taskId = 4),
90                 createRecentTask(taskId = 5),
91                 createRecentTask(taskId = 6),
92             )
93     }
94 
95     @Suppress("UNCHECKED_CAST")
96     private fun givenRecentTasks(vararg tasks: GroupedRecentTaskInfo) {
97         whenever(recentTasks.getRecentTasks(any(), any(), any(), any(), any())).thenAnswer {
98             val consumer = it.arguments.last() as Consumer<List<GroupedRecentTaskInfo>>
99             consumer.accept(tasks.toList())
100         }
101     }
102 
103     private fun createRecentTask(taskId: Int): RecentTask =
104         RecentTask(
105             taskId = taskId,
106             userId = 0,
107             topActivityComponent = null,
108             baseIntentComponent = null,
109             colorBackground = null
110         )
111 
112     private fun createSingleTask(taskId: Int): GroupedRecentTaskInfo =
113         GroupedRecentTaskInfo.forSingleTask(createTaskInfo(taskId))
114 
115     private fun createTaskPair(taskId1: Int, taskId2: Int): GroupedRecentTaskInfo =
116         GroupedRecentTaskInfo.forSplitTasks(createTaskInfo(taskId1), createTaskInfo(taskId2), null)
117 
118     private fun createTaskInfo(taskId: Int) = RecentTaskInfo().apply { this.taskId = taskId }
119 }
120