1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.launcher3.model.data
18 
19 import android.content.ComponentName
20 import android.content.Intent
21 import androidx.test.ext.junit.runners.AndroidJUnit4
22 import androidx.test.platform.app.InstrumentationRegistry
23 import com.android.launcher3.Flags.enableRefactorTaskThumbnail
24 import com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE
25 import com.android.launcher3.model.data.TaskViewItemInfo.Companion.createTaskViewAtom
26 import com.android.launcher3.pm.UserCache
27 import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext
28 import com.android.launcher3.util.SplitConfigurationOptions
29 import com.android.launcher3.util.TransformingTouchDelegate
30 import com.android.launcher3.util.UserIconInfo
31 import com.android.quickstep.TaskOverlayFactory
32 import com.android.quickstep.TaskOverlayFactory.TaskOverlay
33 import com.android.quickstep.recents.di.RecentsDependencies
34 import com.android.quickstep.task.thumbnail.TaskThumbnailView
35 import com.android.quickstep.views.RecentsView
36 import com.android.quickstep.views.TaskContainer
37 import com.android.quickstep.views.TaskThumbnailViewDeprecated
38 import com.android.quickstep.views.TaskView
39 import com.android.quickstep.views.TaskViewIcon
40 import com.android.quickstep.views.TaskViewType
41 import com.android.systemui.shared.recents.model.Task
42 import com.android.systemui.shared.recents.model.Task.TaskKey
43 import com.google.common.truth.Truth.assertThat
44 import org.junit.Before
45 import org.junit.Test
46 import org.junit.runner.RunWith
47 import org.mockito.kotlin.any
48 import org.mockito.kotlin.mock
49 import org.mockito.kotlin.whenever
50 
51 /** Test for [TaskViewItemInfo] */
52 @RunWith(AndroidJUnit4::class)
53 class TaskViewItemInfoTest {
54     private val context = SandboxContext(InstrumentationRegistry.getInstrumentation().targetContext)
55     private val taskView = mock<TaskView>()
56     private val recentsView = mock<RecentsView<*, *>>()
57     private val overlayFactory = mock<TaskOverlayFactory>()
58     private val userCache = mock<UserCache>()
59     private val userInfo = mock<UserIconInfo>()
60 
61     @Before
setUpnull62     fun setUp() {
63         whenever(overlayFactory.createOverlay(any())).thenReturn(mock<TaskOverlay<*>>())
64         whenever(taskView.context).thenReturn(context)
65         whenever(taskView.recentsView).thenReturn(recentsView)
66         whenever(recentsView.indexOfChild(taskView)).thenReturn(TASK_VIEW_INDEX)
67         whenever(userInfo.isPrivate).thenReturn(false)
68         whenever(userCache.getUserInfo(any())).thenReturn(userInfo)
69         context.putObject(UserCache.INSTANCE, userCache)
70         RecentsDependencies.initialize(context)
71     }
72 
73     @Test
singleTasknull74     fun singleTask() {
75         val taskContainers = listOf(createTaskContainer(createTask(1)))
76         whenever(taskView.type).thenReturn(TaskViewType.SINGLE)
77         whenever(taskView.taskContainers).thenReturn(taskContainers)
78 
79         val taskViewItemInfo = TaskViewItemInfo(taskContainers[0])
80 
81         assertThat(taskViewItemInfo.taskViewAtom)
82             .isEqualTo(
83                 createTaskViewAtom(
84                     type = 0,
85                     index = TASK_VIEW_INDEX,
86                     componentName = "${PACKAGE}/${CLASS}",
87                     cardinality = 1,
88                 )
89             )
90         assertThat(taskViewItemInfo.runtimeStatusFlags and FLAG_NOT_PINNABLE).isEqualTo(0)
91     }
92 
93     @Test
splitTasknull94     fun splitTask() {
95         val taskContainers =
96             listOf(createTaskContainer(createTask(1)), createTaskContainer(createTask(2)))
97         whenever(taskView.type).thenReturn(TaskViewType.GROUPED)
98         whenever(taskView.taskContainers).thenReturn(taskContainers)
99 
100         val taskViewItemInfo = TaskViewItemInfo(taskContainers[0])
101 
102         assertThat(taskViewItemInfo.taskViewAtom)
103             .isEqualTo(
104                 createTaskViewAtom(
105                     type = 1,
106                     index = TASK_VIEW_INDEX,
107                     componentName = "${PACKAGE}/${CLASS}",
108                     cardinality = 2,
109                 )
110             )
111         assertThat(taskViewItemInfo.runtimeStatusFlags and FLAG_NOT_PINNABLE).isEqualTo(0)
112     }
113 
114     @Test
desktopTasknull115     fun desktopTask() {
116         val taskContainers =
117             listOf(
118                 createTaskContainer(createTask(1)),
119                 createTaskContainer(createTask(2)),
120                 createTaskContainer(createTask(3)),
121             )
122         whenever(taskView.type).thenReturn(TaskViewType.DESKTOP)
123         whenever(taskView.taskContainers).thenReturn(taskContainers)
124 
125         val taskViewItemInfo = TaskViewItemInfo(taskContainers[0])
126 
127         assertThat(taskViewItemInfo.taskViewAtom)
128             .isEqualTo(
129                 createTaskViewAtom(
130                     type = 2,
131                     index = TASK_VIEW_INDEX,
132                     componentName = "${PACKAGE}/${CLASS}",
133                     cardinality = 3,
134                 )
135             )
136         assertThat(taskViewItemInfo.runtimeStatusFlags and FLAG_NOT_PINNABLE).isEqualTo(0)
137     }
138 
139     @Test
privateTasknull140     fun privateTask() {
141         val taskContainers = listOf(createTaskContainer(createTask(1)))
142         whenever(taskView.type).thenReturn(TaskViewType.SINGLE)
143         whenever(taskView.taskContainers).thenReturn(taskContainers)
144         whenever(userInfo.isPrivate).thenReturn(true)
145 
146         val taskViewItemInfo = TaskViewItemInfo(taskContainers[0])
147 
148         assertThat(taskViewItemInfo.taskViewAtom)
149             .isEqualTo(
150                 createTaskViewAtom(
151                     type = 0,
152                     index = TASK_VIEW_INDEX,
153                     componentName = "${PACKAGE}/${CLASS}",
154                     cardinality = 1,
155                 )
156             )
157         assertThat(taskViewItemInfo.runtimeStatusFlags and FLAG_NOT_PINNABLE)
158             .isEqualTo(FLAG_NOT_PINNABLE)
159     }
160 
createTasknull161     private fun createTask(id: Int) =
162         Task(TaskKey(id, 0, Intent(), ComponentName(PACKAGE, CLASS), 0, 2000))
163 
164     private fun createTaskContainer(task: Task): TaskContainer {
165         return TaskContainer(
166             taskView,
167             task,
168             if (enableRefactorTaskThumbnail()) mock<TaskThumbnailView>()
169             else mock<TaskThumbnailViewDeprecated>(),
170             mock<TaskViewIcon>(),
171             mock<TransformingTouchDelegate>(),
172             SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
173             digitalWellBeingToast = null,
174             showWindowsView = null,
175             overlayFactory,
176         )
177     }
178 
179     companion object {
180         const val PACKAGE = "package"
181         const val CLASS = "class"
182         const val TASK_VIEW_INDEX = 4
183     }
184 }
185