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