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