1 package com.android.systemui.mediaprojection.appselector 2 3 import android.content.ComponentName 4 import android.os.UserHandle 5 import android.testing.AndroidTestingRunner 6 import androidx.test.filters.SmallTest 7 import com.android.systemui.SysuiTestCase 8 import com.android.systemui.mediaprojection.appselector.data.RecentTask 9 import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider 10 import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver 11 import com.android.systemui.util.mockito.any 12 import com.android.systemui.util.mockito.mock 13 import com.android.systemui.util.mockito.whenever 14 import kotlinx.coroutines.CoroutineScope 15 import kotlinx.coroutines.Dispatchers 16 import org.junit.Before 17 import org.junit.Test 18 import org.junit.runner.RunWith 19 import org.mockito.Mockito.verify 20 21 @RunWith(AndroidTestingRunner::class) 22 @SmallTest 23 class MediaProjectionAppSelectorControllerTest : SysuiTestCase() { 24 25 private val taskListProvider = TestRecentTaskListProvider() 26 private val scope = CoroutineScope(Dispatchers.Unconfined) 27 private val appSelectorComponentName = ComponentName("com.test", "AppSelector") 28 private val callerPackageName = "com.test.caller" 29 private val callerComponentName = ComponentName(callerPackageName, "Caller") 30 31 private val personalUserHandle = UserHandle.of(123) 32 private val workUserHandle = UserHandle.of(456) 33 34 private val view: MediaProjectionAppSelectorView = mock() 35 private val policyResolver: ScreenCaptureDevicePolicyResolver = mock() 36 37 private val controller = 38 MediaProjectionAppSelectorController( 39 taskListProvider, 40 view, 41 policyResolver, 42 personalUserHandle, 43 scope, 44 appSelectorComponentName, 45 callerPackageName 46 ) 47 48 @Before 49 fun setup() { 50 givenCaptureAllowed(isAllow = true) 51 } 52 53 @Test 54 fun initNoRecentTasks_bindsEmptyList() { 55 taskListProvider.tasks = emptyList() 56 57 controller.init() 58 59 verify(view).bind(emptyList()) 60 } 61 62 @Test 63 fun initOneRecentTask_bindsList() { 64 taskListProvider.tasks = listOf(createRecentTask(taskId = 1)) 65 66 controller.init() 67 68 verify(view).bind(listOf(createRecentTask(taskId = 1))) 69 } 70 71 @Test 72 fun initMultipleRecentTasksWithoutAppSelectorTask_bindsListInTheSameOrder() { 73 val tasks = 74 listOf( 75 createRecentTask(taskId = 1), 76 createRecentTask(taskId = 2), 77 createRecentTask(taskId = 3), 78 ) 79 taskListProvider.tasks = tasks 80 81 controller.init() 82 83 verify(view) 84 .bind( 85 listOf( 86 createRecentTask(taskId = 1), 87 createRecentTask(taskId = 2), 88 createRecentTask(taskId = 3), 89 ) 90 ) 91 } 92 93 @Test 94 fun initRecentTasksWithAppSelectorTasks_removeAppSelector() { 95 val tasks = 96 listOf( 97 createRecentTask(taskId = 1), 98 createRecentTask(taskId = 2, topActivityComponent = appSelectorComponentName), 99 createRecentTask(taskId = 3), 100 createRecentTask(taskId = 4), 101 ) 102 taskListProvider.tasks = tasks 103 104 controller.init() 105 106 verify(view) 107 .bind( 108 listOf( 109 createRecentTask(taskId = 1), 110 createRecentTask(taskId = 3), 111 createRecentTask(taskId = 4), 112 ) 113 ) 114 } 115 116 @Test 117 fun initRecentTasksWithAppSelectorTasks_bindsCallerTasksAtTheEnd() { 118 val tasks = 119 listOf( 120 createRecentTask(taskId = 1), 121 createRecentTask(taskId = 2, topActivityComponent = callerComponentName), 122 createRecentTask(taskId = 3), 123 createRecentTask(taskId = 4), 124 ) 125 taskListProvider.tasks = tasks 126 127 controller.init() 128 129 verify(view) 130 .bind( 131 listOf( 132 createRecentTask(taskId = 1), 133 createRecentTask(taskId = 3), 134 createRecentTask(taskId = 4), 135 createRecentTask(taskId = 2, topActivityComponent = callerComponentName), 136 ) 137 ) 138 } 139 140 @Test 141 fun initRecentTasksWithAppSelectorTasks_withEnterprisePolicies_bindsAllTasks() { 142 val tasks = 143 listOf( 144 createRecentTask(taskId = 1, userId = personalUserHandle.identifier), 145 createRecentTask(taskId = 2, userId = workUserHandle.identifier), 146 createRecentTask(taskId = 3, userId = personalUserHandle.identifier), 147 createRecentTask(taskId = 4, userId = workUserHandle.identifier), 148 createRecentTask(taskId = 5, userId = personalUserHandle.identifier), 149 ) 150 taskListProvider.tasks = tasks 151 152 controller.init() 153 154 verify(view) 155 .bind( 156 listOf( 157 createRecentTask(taskId = 1, userId = personalUserHandle.identifier), 158 createRecentTask(taskId = 2, userId = workUserHandle.identifier), 159 createRecentTask(taskId = 3, userId = personalUserHandle.identifier), 160 createRecentTask(taskId = 4, userId = workUserHandle.identifier), 161 createRecentTask(taskId = 5, userId = personalUserHandle.identifier), 162 ) 163 ) 164 } 165 166 @Test 167 fun initRecentTasksWithAppSelectorTasks_withEnterprisePolicies_blocksAllTasks() { 168 val tasks = 169 listOf( 170 createRecentTask(taskId = 1, userId = personalUserHandle.identifier), 171 createRecentTask(taskId = 2, userId = workUserHandle.identifier), 172 createRecentTask(taskId = 3, userId = personalUserHandle.identifier), 173 createRecentTask(taskId = 4, userId = workUserHandle.identifier), 174 createRecentTask(taskId = 5, userId = personalUserHandle.identifier), 175 ) 176 taskListProvider.tasks = tasks 177 178 givenCaptureAllowed(isAllow = false) 179 controller.init() 180 181 verify(view).bind(emptyList()) 182 } 183 184 private fun givenCaptureAllowed(isAllow: Boolean) { 185 whenever(policyResolver.isScreenCaptureAllowed(any(), any())).thenReturn(isAllow) 186 } 187 188 private fun createRecentTask( 189 taskId: Int, 190 topActivityComponent: ComponentName? = null, 191 userId: Int = personalUserHandle.identifier 192 ): RecentTask { 193 return RecentTask( 194 taskId = taskId, 195 topActivityComponent = topActivityComponent, 196 baseIntentComponent = ComponentName("com", "Test"), 197 userId = userId, 198 colorBackground = 0 199 ) 200 } 201 202 private class TestRecentTaskListProvider : RecentTaskListProvider { 203 204 var tasks: List<RecentTask> = emptyList() 205 206 override suspend fun loadRecentTasks(): List<RecentTask> = tasks 207 } 208 } 209