1 /* 2 * Copyright (C) 2019 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.systemui.broadcast 18 19 import android.content.BroadcastReceiver 20 import android.content.Context 21 import android.content.Intent 22 import android.content.IntentFilter 23 import android.os.Handler 24 import android.os.Looper 25 import android.os.PatternMatcher 26 import android.os.UserHandle 27 import android.test.suitebuilder.annotation.SmallTest 28 import android.testing.AndroidTestingRunner 29 import android.testing.TestableLooper 30 import com.android.systemui.SysuiTestCase 31 import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger 32 import com.android.systemui.dump.DumpManager 33 import com.android.systemui.settings.UserTracker 34 import com.android.systemui.util.concurrency.FakeExecutor 35 import com.android.systemui.util.mockito.eq 36 import com.android.systemui.util.mockito.mock 37 import com.android.systemui.util.time.FakeSystemClock 38 import com.google.common.truth.Truth.assertThat 39 import java.util.concurrent.Executor 40 import junit.framework.Assert.assertSame 41 import kotlinx.coroutines.flow.collect 42 import kotlinx.coroutines.launch 43 import kotlinx.coroutines.test.advanceUntilIdle 44 import kotlinx.coroutines.test.runBlockingTest 45 import org.junit.Before 46 import org.junit.Test 47 import org.junit.runner.RunWith 48 import org.mockito.ArgumentCaptor 49 import org.mockito.Captor 50 import org.mockito.Mock 51 import org.mockito.Mockito.anyInt 52 import org.mockito.Mockito.inOrder 53 import org.mockito.Mockito.mock 54 import org.mockito.Mockito.never 55 import org.mockito.Mockito.verify 56 import org.mockito.Mockito.`when` 57 import org.mockito.MockitoAnnotations 58 59 @RunWith(AndroidTestingRunner::class) 60 @TestableLooper.RunWithLooper 61 @SmallTest 62 class BroadcastDispatcherTest : SysuiTestCase() { 63 64 companion object { 65 val user0 = UserHandle.of(0) 66 val user1 = UserHandle.of(1) 67 const val DEFAULT_FLAG = Context.RECEIVER_EXPORTED 68 val DEFAULT_PERMISSION: String? = null 69 70 fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture() 71 const val TEST_ACTION = "TEST_ACTION" 72 const val TEST_SCHEME = "TEST_SCHEME" 73 const val TEST_PATH = "TEST_PATH" 74 const val TEST_TYPE = "test/type" 75 } 76 77 @Mock 78 private lateinit var mockContext: Context 79 @Mock 80 private lateinit var mockUBRUser0: UserBroadcastDispatcher 81 @Mock 82 private lateinit var mockUBRUser1: UserBroadcastDispatcher 83 @Mock 84 private lateinit var broadcastReceiver: BroadcastReceiver 85 @Mock 86 private lateinit var broadcastReceiverOther: BroadcastReceiver 87 @Mock 88 private lateinit var intentFilter: IntentFilter 89 @Mock 90 private lateinit var intentFilterOther: IntentFilter 91 @Mock 92 private lateinit var mockHandler: Handler 93 @Mock 94 private lateinit var logger: BroadcastDispatcherLogger 95 @Mock 96 private lateinit var userTracker: UserTracker 97 @Mock 98 private lateinit var removalPendingStore: PendingRemovalStore 99 100 private lateinit var mainExecutor: Executor 101 102 @Captor 103 private lateinit var argumentCaptor: ArgumentCaptor<ReceiverData> 104 105 private lateinit var testableLooper: TestableLooper 106 private lateinit var broadcastDispatcher: BroadcastDispatcher 107 108 @Before 109 fun setUp() { 110 MockitoAnnotations.initMocks(this) 111 testableLooper = TestableLooper.get(this) 112 mainExecutor = FakeExecutor(FakeSystemClock()) 113 `when`(mockContext.mainExecutor).thenReturn(mainExecutor) 114 115 broadcastDispatcher = TestBroadcastDispatcher( 116 mockContext, 117 mainExecutor, 118 testableLooper.looper, 119 mock(Executor::class.java), 120 mock(DumpManager::class.java), 121 logger, 122 userTracker, 123 removalPendingStore, 124 mapOf(0 to mockUBRUser0, 1 to mockUBRUser1)) 125 126 // These should be valid filters 127 `when`(intentFilter.countActions()).thenReturn(1) 128 `when`(intentFilterOther.countActions()).thenReturn(1) 129 setUserMock(mockContext, user0) 130 } 131 132 @Test 133 fun testAddingReceiverToCorrectUBR() { 134 broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, 135 mockHandler, user0) 136 broadcastDispatcher.registerReceiverWithHandler( 137 broadcastReceiverOther, intentFilterOther, mockHandler, user1) 138 139 testableLooper.processAllMessages() 140 141 verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) 142 143 assertSame(broadcastReceiver, argumentCaptor.value.receiver) 144 assertSame(intentFilter, argumentCaptor.value.filter) 145 146 verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) 147 assertSame(broadcastReceiverOther, argumentCaptor.value.receiver) 148 assertSame(intentFilterOther, argumentCaptor.value.filter) 149 } 150 151 @Test 152 fun testAddingReceiverToCorrectUBR_executor() { 153 broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mainExecutor, user0) 154 broadcastDispatcher.registerReceiver( 155 broadcastReceiverOther, intentFilterOther, mainExecutor, user1) 156 157 testableLooper.processAllMessages() 158 159 verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) 160 161 assertSame(broadcastReceiver, argumentCaptor.value.receiver) 162 assertSame(intentFilter, argumentCaptor.value.filter) 163 164 verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) 165 assertSame(broadcastReceiverOther, argumentCaptor.value.receiver) 166 assertSame(intentFilterOther, argumentCaptor.value.filter) 167 } 168 169 @Test 170 fun testAddReceiverDefaultFlag_handler() { 171 broadcastDispatcher.registerReceiverWithHandler( 172 broadcastReceiver, intentFilter, mockHandler) 173 testableLooper.processAllMessages() 174 175 verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) 176 177 assertSame(broadcastReceiver, argumentCaptor.value.receiver) 178 assertSame(intentFilter, argumentCaptor.value.filter) 179 } 180 181 @Test 182 fun testAddReceiverCorrectFlag_handler() { 183 val flag = 3 184 185 broadcastDispatcher.registerReceiverWithHandler( 186 broadcastReceiver, intentFilter, mockHandler, flags = flag) 187 testableLooper.processAllMessages() 188 189 verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(flag)) 190 191 assertSame(broadcastReceiver, argumentCaptor.value.receiver) 192 assertSame(intentFilter, argumentCaptor.value.filter) 193 } 194 195 @Test 196 fun testAddReceiverDefaultFlag_executor() { 197 broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter) 198 testableLooper.processAllMessages() 199 200 verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) 201 202 assertSame(broadcastReceiver, argumentCaptor.value.receiver) 203 assertSame(intentFilter, argumentCaptor.value.filter) 204 } 205 206 @Test 207 fun testAddReceiverCorrectPermission_executor() { 208 val flag = 3 209 val permission = "CUSTOM_PERMISSION" 210 211 broadcastDispatcher.registerReceiver( 212 broadcastReceiver, 213 intentFilter, 214 flags = flag, 215 permission = permission 216 ) 217 testableLooper.processAllMessages() 218 219 verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(flag)) 220 221 assertSame(broadcastReceiver, argumentCaptor.value.receiver) 222 assertSame(intentFilter, argumentCaptor.value.filter) 223 assertSame(permission, argumentCaptor.value.permission) 224 } 225 226 @Test 227 fun testAddReceiverDefaultPermission_executor() { 228 broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter) 229 testableLooper.processAllMessages() 230 231 verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) 232 233 assertSame(broadcastReceiver, argumentCaptor.value.receiver) 234 assertSame(intentFilter, argumentCaptor.value.filter) 235 assertSame(DEFAULT_PERMISSION, argumentCaptor.value.permission) 236 } 237 238 @Test 239 fun testAddReceiverCorrectFlag_executor() { 240 val flag = 3 241 242 broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, flags = flag) 243 testableLooper.processAllMessages() 244 245 verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(flag)) 246 247 assertSame(broadcastReceiver, argumentCaptor.value.receiver) 248 assertSame(intentFilter, argumentCaptor.value.filter) 249 } 250 251 @Test 252 fun testRemovingReceiversRemovesFromAllUBR() { 253 broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, 254 mockHandler, user0) 255 broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, 256 mockHandler, user1) 257 258 broadcastDispatcher.unregisterReceiver(broadcastReceiver) 259 260 testableLooper.processAllMessages() 261 262 verify(mockUBRUser0).unregisterReceiver(broadcastReceiver) 263 verify(mockUBRUser1).unregisterReceiver(broadcastReceiver) 264 } 265 266 @Test 267 fun testRemoveReceiverFromUser() { 268 broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, 269 mockHandler, user0) 270 broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, 271 mockHandler, user1) 272 273 broadcastDispatcher.unregisterReceiverForUser(broadcastReceiver, user0) 274 275 testableLooper.processAllMessages() 276 277 verify(mockUBRUser0).unregisterReceiver(broadcastReceiver) 278 verify(mockUBRUser1, never()).unregisterReceiver(broadcastReceiver) 279 } 280 281 @Test 282 fun testRegisterCurrentAsActualUser() { 283 `when`(userTracker.userId).thenReturn(user1.identifier) 284 285 broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, 286 mockHandler, UserHandle.CURRENT) 287 288 testableLooper.processAllMessages() 289 290 verify(mockUBRUser1).registerReceiver( 291 capture(argumentCaptor), eq(Context.RECEIVER_EXPORTED)) 292 assertSame(broadcastReceiver, argumentCaptor.value.receiver) 293 } 294 295 @Test(expected = IllegalArgumentException::class) 296 fun testFilterMustContainActions() { 297 val testFilter = IntentFilter() 298 broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) 299 } 300 301 @Test(expected = IllegalArgumentException::class) 302 fun testFilterMustNotContainDataScheme() { 303 val testFilter = IntentFilter(TEST_ACTION).apply { 304 addDataScheme(TEST_SCHEME) 305 } 306 broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) 307 } 308 309 @Test(expected = IllegalArgumentException::class) 310 fun testFilterMustNotContainDataAuthority() { 311 val testFilter = IntentFilter(TEST_ACTION).apply { 312 addDataAuthority(mock(IntentFilter.AuthorityEntry::class.java)) 313 } 314 broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) 315 } 316 317 @Test(expected = IllegalArgumentException::class) 318 fun testFilterMustNotContainDataPath() { 319 val testFilter = IntentFilter(TEST_ACTION).apply { 320 addDataPath(TEST_PATH, PatternMatcher.PATTERN_LITERAL) 321 } 322 broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) 323 } 324 325 @Test(expected = IllegalArgumentException::class) 326 fun testFilterMustNotContainDataType() { 327 val testFilter = IntentFilter(TEST_ACTION).apply { 328 addDataType(TEST_TYPE) 329 } 330 broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) 331 } 332 333 @Test(expected = IllegalArgumentException::class) 334 fun testFilterMustNotSetPriority() { 335 val testFilter = IntentFilter(TEST_ACTION).apply { 336 priority = IntentFilter.SYSTEM_HIGH_PRIORITY 337 } 338 broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) 339 } 340 341 @Test 342 fun testTaggedReceiverForRemovalImmediately_allUsers() { 343 broadcastDispatcher.unregisterReceiver(broadcastReceiver) 344 345 verify(removalPendingStore).tagForRemoval(broadcastReceiver, UserHandle.USER_ALL) 346 verify(removalPendingStore, never()).clearPendingRemoval(eq(broadcastReceiver), anyInt()) 347 } 348 349 @Test 350 fun testTaggedReceiverForRemovalImmediately_singleUser() { 351 val user = 0 352 broadcastDispatcher.unregisterReceiverForUser(broadcastReceiver, UserHandle.of(user)) 353 354 verify(removalPendingStore).tagForRemoval(broadcastReceiver, user) 355 verify(removalPendingStore, never()).clearPendingRemoval(eq(broadcastReceiver), anyInt()) 356 } 357 358 @Test 359 fun testUnregisterReceiverClearsPendingRemovalAfterRemoving_allUsers() { 360 broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, null, user0) 361 broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, null, user1) 362 363 broadcastDispatcher.unregisterReceiver(broadcastReceiver) 364 365 testableLooper.processAllMessages() 366 367 val inOrderUser0 = inOrder(mockUBRUser0, removalPendingStore) 368 inOrderUser0.verify(mockUBRUser0).unregisterReceiver(broadcastReceiver) 369 inOrderUser0.verify(removalPendingStore) 370 .clearPendingRemoval(broadcastReceiver, UserHandle.USER_ALL) 371 372 val inOrderUser1 = inOrder(mockUBRUser1, removalPendingStore) 373 inOrderUser1.verify(mockUBRUser1).unregisterReceiver(broadcastReceiver) 374 inOrderUser1.verify(removalPendingStore) 375 .clearPendingRemoval(broadcastReceiver, UserHandle.USER_ALL) 376 } 377 378 @Test 379 fun testUnregisterReceiverclearPendingRemovalAfterRemoving_singleUser() { 380 broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, null, user1) 381 382 broadcastDispatcher.unregisterReceiverForUser(broadcastReceiver, user1) 383 384 testableLooper.processAllMessages() 385 386 val inOrderUser1 = inOrder(mockUBRUser1, removalPendingStore) 387 inOrderUser1.verify(mockUBRUser1).unregisterReceiver(broadcastReceiver) 388 inOrderUser1.verify(removalPendingStore) 389 .clearPendingRemoval(broadcastReceiver, user1.identifier) 390 } 391 392 @Test 393 fun testBroadcastFlow() = runBlockingTest { 394 val flow = broadcastDispatcher.broadcastFlow(intentFilter, user1) { intent, receiver -> 395 intent to receiver 396 } 397 398 // Collect the values into collectedValues. 399 val collectedValues = mutableListOf<Pair<Intent, BroadcastReceiver>>() 400 val job = launch { 401 flow.collect { collectedValues.add(it) } 402 } 403 404 testableLooper.processAllMessages() 405 verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG)) 406 val receiver = argumentCaptor.value.receiver 407 408 // Simulate fake broadcasted intents. 409 val fakeIntents = listOf<Intent>(mock(), mock(), mock()) 410 fakeIntents.forEach { receiver.onReceive(mockContext, it) } 411 412 // The intents should have been collected. 413 advanceUntilIdle() 414 415 val expectedValues = fakeIntents.map { it to receiver } 416 assertThat(collectedValues).containsExactlyElementsIn(expectedValues) 417 418 // Stop the collection. 419 job.cancel() 420 421 testableLooper.processAllMessages() 422 verify(mockUBRUser1).unregisterReceiver(receiver) 423 } 424 425 private fun setUserMock(mockContext: Context, user: UserHandle) { 426 `when`(mockContext.user).thenReturn(user) 427 `when`(mockContext.userId).thenReturn(user.identifier) 428 } 429 430 private class TestBroadcastDispatcher( 431 context: Context, 432 mainExecutor: Executor, 433 backgroundRunningLooper: Looper, 434 backgroundRunningExecutor: Executor, 435 dumpManager: DumpManager, 436 logger: BroadcastDispatcherLogger, 437 userTracker: UserTracker, 438 removalPendingStore: PendingRemovalStore, 439 var mockUBRMap: Map<Int, UserBroadcastDispatcher> 440 ) : BroadcastDispatcher( 441 context, 442 mainExecutor, 443 backgroundRunningLooper, 444 backgroundRunningExecutor, 445 dumpManager, 446 logger, 447 userTracker, 448 removalPendingStore 449 ) { 450 override fun createUBRForUser(userId: Int): UserBroadcastDispatcher { 451 return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java)) 452 } 453 } 454 } 455