1 package com.android.systemui.media.nearby
2 
3 import android.media.INearbyMediaDevicesProvider
4 import android.media.INearbyMediaDevicesUpdateCallback
5 import androidx.test.filters.SmallTest
6 import com.android.systemui.SysuiTestCase
7 import android.media.NearbyDevice
8 import android.os.IBinder
9 import com.android.systemui.statusbar.CommandQueue
10 import com.google.common.truth.Truth.assertThat
11 import org.junit.Before
12 import org.junit.Test
13 import org.mockito.ArgumentCaptor
14 import org.mockito.Mock
15 import org.mockito.Mockito.anyInt
16 import org.mockito.Mockito.never
17 import org.mockito.Mockito.reset
18 import org.mockito.Mockito.times
19 import org.mockito.Mockito.verify
20 import org.mockito.MockitoAnnotations
21 
22 @SmallTest
23 class NearbyMediaDevicesManagerTest : SysuiTestCase() {
24 
25     private lateinit var manager: NearbyMediaDevicesManager
26     @Mock
27     private lateinit var logger: NearbyMediaDevicesLogger
28     @Mock
29     private lateinit var commandQueue: CommandQueue
30     private lateinit var commandQueueCallbacks: CommandQueue.Callbacks
31 
32     @Before
33     fun setUp() {
34         MockitoAnnotations.initMocks(this)
35         manager = NearbyMediaDevicesManager(commandQueue, logger)
36 
37         val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
38         verify(commandQueue).addCallback(callbackCaptor.capture())
39         commandQueueCallbacks = callbackCaptor.value!!
40     }
41 
42     @Test
43     fun registerNearbyDevicesCallback_noProviderRegistered_noCrash() {
44         // No assert, just needs no crash
45         manager.registerNearbyDevicesCallback(object : INearbyMediaDevicesUpdateCallback.Stub() {
46             override fun onDevicesUpdated(nearbyDevices: List<NearbyDevice>) {}
47         })
48     }
49 
50     @Test
51     fun registerNearbyDevicesCallback_providerRegistered_providerReceivesCallback() {
52         val provider = TestProvider()
53         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
54 
55         val callback = object : INearbyMediaDevicesUpdateCallback.Stub() {
56             override fun onDevicesUpdated(nearbyDevices: List<NearbyDevice>) {}
57         }
58 
59         manager.registerNearbyDevicesCallback(callback)
60 
61         assertThat(provider.lastRegisteredCallback).isEqualTo(callback)
62     }
63 
64     @Test
65     fun registerNearbyDevicesCallback_multipleProviders_allProvidersReceiveCallback() {
66         val provider1 = TestProvider()
67         val provider2 = TestProvider()
68         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider1)
69         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider2)
70 
71         val callback = object : INearbyMediaDevicesUpdateCallback.Stub() {
72             override fun onDevicesUpdated(nearbyDevices: List<NearbyDevice>) {}
73         }
74 
75         manager.registerNearbyDevicesCallback(callback)
76 
77         assertThat(provider1.lastRegisteredCallback).isEqualTo(callback)
78         assertThat(provider2.lastRegisteredCallback).isEqualTo(callback)
79     }
80 
81     @Test
82     fun unregisterNearbyDevicesCallback_noProviderRegistered_noCrash() {
83         // No assert, just needs no crash
84         manager.unregisterNearbyDevicesCallback(object : INearbyMediaDevicesUpdateCallback.Stub() {
85             override fun onDevicesUpdated(nearbyDevices: List<NearbyDevice>) {}
86         })
87     }
88 
89     @Test
90     fun unregisterNearbyDevicesCallback_providerRegistered_providerReceivesCallback() {
91         val provider = TestProvider()
92         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
93 
94         val callback = object : INearbyMediaDevicesUpdateCallback.Stub() {
95             override fun onDevicesUpdated(nearbyDevices: List<NearbyDevice>) {}
96         }
97 
98         manager.unregisterNearbyDevicesCallback(callback)
99 
100         assertThat(provider.lastUnregisteredCallback).isEqualTo(callback)
101     }
102 
103     @Test
104     fun unregisterNearbyDevicesCallback_multipleProviders_allProvidersReceiveCallback() {
105         val provider1 = TestProvider()
106         val provider2 = TestProvider()
107         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider1)
108         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider2)
109 
110         val callback = object : INearbyMediaDevicesUpdateCallback.Stub() {
111             override fun onDevicesUpdated(nearbyDevices: List<NearbyDevice>) {}
112         }
113 
114         manager.unregisterNearbyDevicesCallback(callback)
115 
116         assertThat(provider1.lastUnregisteredCallback).isEqualTo(callback)
117         assertThat(provider2.lastUnregisteredCallback).isEqualTo(callback)
118     }
119 
120     @Test
121     fun newProviderRegisteredAfterCallbacksRegistered_providerGetsPreviouslyRegisteredCallbacks() {
122         // Start off with an existing provider and callback
123         val provider1 = TestProvider()
124         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider1)
125         val callback = object : INearbyMediaDevicesUpdateCallback.Stub() {
126             override fun onDevicesUpdated(nearbyDevices: List<NearbyDevice>) {}
127         }
128         manager.registerNearbyDevicesCallback(callback)
129 
130         // Add a new provider
131         val provider2 = TestProvider()
132         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider2)
133 
134         // Verify the new provider received the previously-registered callbacks
135         assertThat(provider2.lastRegisteredCallback).isEqualTo(callback)
136     }
137 
138     @Test
139     fun providerUnregistered_doesNotReceiveNewCallback() {
140         val provider = TestProvider()
141         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
142         commandQueueCallbacks.unregisterNearbyMediaDevicesProvider(provider)
143 
144         val callback = object : INearbyMediaDevicesUpdateCallback.Stub() {
145             override fun onDevicesUpdated(nearbyDevices: List<NearbyDevice>) {}
146         }
147         manager.registerNearbyDevicesCallback(callback)
148 
149         assertThat(provider.lastRegisteredCallback).isEqualTo(null)
150     }
151 
152     @Test
153     fun providerRegistered_isLogged() {
154         commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
155 
156         verify(logger).logProviderRegistered(numProviders = 1)
157     }
158 
159     @Test
160     fun providerRegisteredTwice_onlyLoggedOnce() {
161         val provider = TestProvider()
162 
163         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
164         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
165 
166         verify(logger, times(1)).logProviderRegistered(numProviders = 1)
167     }
168 
169     @Test
170     fun multipleProvidersRegistered_isLogged() {
171         commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
172         commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
173         reset(logger)
174 
175         commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
176 
177         verify(logger).logProviderRegistered(numProviders = 3)
178     }
179 
180     @Test
181     fun providerUnregistered_isLogged() {
182         val provider = TestProvider()
183         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
184 
185         commandQueueCallbacks.unregisterNearbyMediaDevicesProvider(provider)
186 
187         verify(logger).logProviderUnregistered(numProviders = 0)
188     }
189 
190     @Test
191     fun multipleProvidersRegisteredThenUnregistered_isLogged() {
192         val provider = TestProvider()
193         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
194         commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
195         commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
196 
197         commandQueueCallbacks.unregisterNearbyMediaDevicesProvider(provider)
198 
199         verify(logger).logProviderUnregistered(numProviders = 2)
200     }
201 
202     @Test
203     fun providerUnregisteredButNeverRegistered_notLogged() {
204         commandQueueCallbacks.unregisterNearbyMediaDevicesProvider(TestProvider())
205 
206         verify(logger, never()).logProviderRegistered(anyInt())
207     }
208 
209     @Test
210     fun providerBinderDied_isLogged() {
211         val provider = TestProvider()
212         commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
213 
214         provider.deathRecipient!!.binderDied(provider)
215 
216         verify(logger).logProviderBinderDied(numProviders = 0)
217     }
218 
219     private class TestProvider : INearbyMediaDevicesProvider.Stub() {
220         var lastRegisteredCallback: INearbyMediaDevicesUpdateCallback? = null
221         var lastUnregisteredCallback: INearbyMediaDevicesUpdateCallback? = null
222         var deathRecipient: IBinder.DeathRecipient? = null
223 
224         override fun registerNearbyDevicesCallback(
225             callback: INearbyMediaDevicesUpdateCallback
226         ) {
227             lastRegisteredCallback = callback
228         }
229 
230         override fun unregisterNearbyDevicesCallback(
231             callback: INearbyMediaDevicesUpdateCallback
232         ) {
233             lastUnregisteredCallback = callback
234         }
235 
236         override fun asBinder(): IBinder {
237             return this
238         }
239 
240         override fun linkToDeath(recipient: IBinder.DeathRecipient, flags: Int) {
241             deathRecipient = recipient
242         }
243     }
244 }
245