OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 package org.appspot.apprtc; | |
12 | |
13 import static org.junit.Assert.assertEquals; | |
14 import static org.junit.Assert.assertNotNull; | |
15 import static org.junit.Assert.assertNull; | |
16 import static org.junit.Assert.assertFalse; | |
17 import static org.junit.Assert.assertTrue; | |
18 import static org.mockito.Mockito.doCallRealMethod; | |
19 import static org.mockito.Mockito.mock; | |
20 import static org.mockito.Mockito.never; | |
21 import static org.mockito.Mockito.times; | |
22 import static org.mockito.Mockito.verify; | |
23 import static org.mockito.Mockito.when; | |
24 | |
25 import android.bluetooth.BluetoothAdapter; | |
26 import android.bluetooth.BluetoothDevice; | |
27 import android.bluetooth.BluetoothHeadset; | |
28 import android.bluetooth.BluetoothProfile; | |
29 import android.content.BroadcastReceiver; | |
30 import android.content.Context; | |
31 import android.content.Intent; | |
32 import android.content.IntentFilter; | |
33 import android.media.AudioManager; | |
34 import android.util.Log; | |
35 import java.util.LinkedList; | |
36 import java.util.List; | |
37 import org.appspot.apprtc.AppRTCBluetoothManager.State; | |
38 import org.chromium.testing.local.LocalRobolectricTestRunner; | |
39 import org.junit.Before; | |
40 import org.junit.Test; | |
41 import org.junit.runner.RunWith; | |
42 import org.robolectric.annotation.Config; | |
43 import org.robolectric.shadows.ShadowApplication; | |
44 import org.robolectric.shadows.ShadowLog; | |
45 | |
46 /** | |
47 * Verifies basic behavior of the AppRTCBluetoothManager class. | |
48 * Note that the test object uses an AppRTCAudioManager (injected in ctor), | |
49 * but a mocked version is used instead. Hence, the parts "driven" by the AppRTC | |
50 * audio manager are not included in this test. | |
51 */ | |
52 @RunWith(LocalRobolectricTestRunner.class) | |
53 @Config(manifest = Config.NONE) | |
54 public class BluetoothManagerTest { | |
55 private static final String TAG = "BluetoothManagerTest"; | |
56 private static final String BLUETOOTH_TEST_DEVICE_NAME = "BluetoothTestDevice" ; | |
57 | |
58 private BroadcastReceiver bluetoothHeadsetStateReceiver; | |
59 private BluetoothProfile.ServiceListener bluetoothServiceListener; | |
60 private BluetoothHeadset mockedBluetoothHeadset; | |
61 private BluetoothDevice mockedBluetoothDevice; | |
62 private List<BluetoothDevice> mockedBluetoothDeviceList; | |
63 private AppRTCBluetoothManager bluetoothManager; | |
64 private AppRTCAudioManager mockedAppRtcAudioManager; | |
65 private AudioManager mockedAudioManager; | |
66 private Context context; | |
67 | |
68 @Before | |
69 public void setUp() { | |
70 ShadowLog.stream = System.out; | |
71 context = ShadowApplication.getInstance().getApplicationContext(); | |
72 mockedAppRtcAudioManager = mock(AppRTCAudioManager.class); | |
73 mockedAudioManager = mock(AudioManager.class); | |
74 mockedBluetoothHeadset = mock(BluetoothHeadset.class); | |
75 mockedBluetoothDevice = mock(BluetoothDevice.class); | |
76 mockedBluetoothDeviceList = new LinkedList<BluetoothDevice>(); | |
77 | |
78 // Simulate that bluetooth SCO audio is available by default. | |
79 when(mockedAudioManager.isBluetoothScoAvailableOffCall()).thenReturn(true); | |
80 | |
81 // Create the test object and override protected methods for this test. | |
82 bluetoothManager = new AppRTCBluetoothManager(context, mockedAppRtcAudioMana ger) { | |
83 @Override | |
84 protected AudioManager getAudioManager(Context context) { | |
85 Log.d(TAG, "getAudioManager"); | |
86 return mockedAudioManager; | |
87 } | |
88 | |
89 @Override | |
90 protected void registerReceiver(BroadcastReceiver receiver, IntentFilter f ilter) { | |
91 Log.d(TAG, "registerReceiver"); | |
92 if (filter.hasAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED) | |
93 && filter.hasAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { | |
94 // Gives access to the real broadcast receiver so the test can use it. | |
95 bluetoothHeadsetStateReceiver = receiver; | |
96 } | |
97 } | |
98 | |
99 @Override | |
100 protected void unregisterReceiver(BroadcastReceiver receiver) { | |
101 Log.d(TAG, "unregisterReceiver"); | |
102 if (receiver == bluetoothHeadsetStateReceiver) { | |
103 bluetoothHeadsetStateReceiver = null; | |
104 } | |
105 } | |
106 | |
107 @Override | |
108 protected boolean getBluetoothProfileProxy( | |
109 Context context, BluetoothProfile.ServiceListener listener, int profil e) { | |
110 Log.d(TAG, "getBluetoothProfileProxy"); | |
111 if (profile == BluetoothProfile.HEADSET) { | |
112 // Allows the test to access the real Bluetooth service listener objec t. | |
113 bluetoothServiceListener = listener; | |
114 } | |
115 return true; | |
116 } | |
117 | |
118 @Override | |
119 protected boolean hasPermission(Context context, String permission) { | |
120 Log.d(TAG, "hasPermission(" + permission + ")"); | |
121 // Ensure that the client asks for Bluetooth permission. | |
122 return (permission == android.Manifest.permission.BLUETOOTH); | |
123 } | |
124 | |
125 @Override | |
126 protected void logBluetoothAdapterInfo(BluetoothAdapter localAdapter) { | |
127 // Do nothing in tests. No need to mock BluetoothAdapter. | |
128 } | |
129 }; | |
130 } | |
131 | |
132 // Verify that Bluetooth service listener for headset profile is properly init ialized. | |
133 @Test | |
134 public void testBluetoothServiceListenerInitialized() { | |
135 bluetoothManager.start(); | |
136 assertNotNull(bluetoothServiceListener); | |
137 verify(mockedAppRtcAudioManager, never()).updateAudioDeviceState(); | |
138 } | |
139 | |
140 // Verify that broadcast receivers for Bluetooth SCO audio state and Bluetooth headset state | |
141 // are properly registered and unregistered. | |
142 @Test | |
143 public void testBluetoothBroadcastReceiversAreRegistered() { | |
144 bluetoothManager.start(); | |
145 assertNotNull(bluetoothHeadsetStateReceiver); | |
146 bluetoothManager.stop(); | |
147 assertNull(bluetoothHeadsetStateReceiver); | |
148 } | |
149 | |
150 // Verify that the Bluetooth manager starts and stops with correct states. | |
151 @Test | |
152 public void testBluetoothDefaultStartStopStates() { | |
153 bluetoothManager.start(); | |
154 assertEquals(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE); | |
155 bluetoothManager.stop(); | |
156 assertEquals(bluetoothManager.getState(), State.UNINITIALIZED); | |
157 } | |
158 | |
159 // Verify correct state after receiving BluetoothServiceListener.onServiceConn ected() | |
160 // when no BT device is enabled. | |
161 @Test | |
162 public void testBluetoothServiceListenerConnectedWithNoHeadset() { | |
163 bluetoothManager.start(); | |
164 assertEquals(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE); | |
165 simulateBluetoothServiceConnectedWithNoConnectedHeadset(); | |
166 verify(mockedAppRtcAudioManager, times(1)).updateAudioDeviceState(); | |
167 assertEquals(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE); | |
168 } | |
169 | |
170 // Verify correct state after receiving BluetoothServiceListener.onServiceConn ected() | |
171 // when one emulated (test) BT device is enabled. Android does not support mor e than | |
172 // one connected BT headset. | |
173 @Test | |
174 public void testBluetoothServiceListenerConnectedWithHeadset() { | |
175 bluetoothManager.start(); | |
176 assertEquals(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE); | |
177 simulateBluetoothServiceConnectedWithConnectedHeadset(); | |
178 verify(mockedAppRtcAudioManager, times(1)).updateAudioDeviceState(); | |
179 assertEquals(bluetoothManager.getState(), State.HEADSET_AVAILABLE); | |
180 } | |
181 | |
182 // Verify correct state after receiving BluetoothProfile.ServiceListener.onSer viceDisconnected(). | |
183 @Test | |
184 public void testBluetoothServiceListenerDisconnected() { | |
185 bluetoothManager.start(); | |
186 assertEquals(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE); | |
187 simulateBluetoothServiceDisconnected(); | |
188 verify(mockedAppRtcAudioManager, times(1)).updateAudioDeviceState(); | |
189 assertEquals(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE); | |
190 } | |
191 | |
192 // Verify correct state after BluetoothServiceListener.onServiceConnected() an d | |
193 // the intent indicating that the headset is actually connected. Both these ca llbacks | |
194 // results in calls to updateAudioDeviceState() on the AppRTC audio manager. | |
195 // No BT SCO is enabled here to keep the test limited. | |
196 @Test | |
197 public void testBluetoothHeadsetConnected() { | |
198 bluetoothManager.start(); | |
199 assertEquals(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE); | |
200 simulateBluetoothServiceConnectedWithConnectedHeadset(); | |
201 simulateBluetoothHeadsetConnected(); | |
202 verify(mockedAppRtcAudioManager, times(2)).updateAudioDeviceState(); | |
203 assertEquals(bluetoothManager.getState(), State.HEADSET_AVAILABLE); | |
204 } | |
205 | |
206 // Verify correct state sequence for a case when a BT headset is available, | |
207 // followed by BT SCO audio being enabled and then stopped. | |
208 @Test | |
209 public void testBluetoothScoAudioStartAndStop() { | |
magjed_webrtc
2016/12/10 19:34:45
This is exactly what I wanted. It looks very clean
henrika_webrtc
2016/12/12 14:13:25
Thanks. Agree that it was very useful to add and l
| |
210 bluetoothManager.start(); | |
211 assertEquals(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE); | |
212 simulateBluetoothServiceConnectedWithConnectedHeadset(); | |
213 assertEquals(bluetoothManager.getState(), State.HEADSET_AVAILABLE); | |
214 bluetoothManager.startScoAudio(); | |
215 assertEquals(bluetoothManager.getState(), State.SCO_CONNECTING); | |
216 simulateBluetoothScoConnectionConnected(); | |
217 assertEquals(bluetoothManager.getState(), State.SCO_CONNECTED); | |
218 bluetoothManager.stopScoAudio(); | |
219 simulateBluetoothScoConnectionDisconnected(); | |
220 assertEquals(bluetoothManager.getState(), State.SCO_DISCONNECTING); | |
221 bluetoothManager.stop(); | |
222 assertEquals(bluetoothManager.getState(), State.UNINITIALIZED); | |
223 verify(mockedAppRtcAudioManager, times(3)).updateAudioDeviceState(); | |
224 } | |
225 | |
226 /** | |
227 * Private helper methods. | |
228 */ | |
229 private void simulateBluetoothServiceConnectedWithNoConnectedHeadset() { | |
230 mockedBluetoothDeviceList.clear(); | |
231 when(mockedBluetoothHeadset.getConnectedDevices()).thenReturn(mockedBluetoot hDeviceList); | |
232 bluetoothServiceListener.onServiceConnected(BluetoothProfile.HEADSET, mocked BluetoothHeadset); | |
233 // In real life, the AppRTC audio manager makes this call. | |
234 bluetoothManager.updateDevice(); | |
235 } | |
236 | |
237 private void simulateBluetoothServiceConnectedWithConnectedHeadset() { | |
238 mockedBluetoothDeviceList.clear(); | |
239 mockedBluetoothDeviceList.add(mockedBluetoothDevice); | |
240 when(mockedBluetoothHeadset.getConnectedDevices()).thenReturn(mockedBluetoot hDeviceList); | |
241 when(mockedBluetoothDevice.getName()).thenReturn(BLUETOOTH_TEST_DEVICE_NAME) ; | |
242 bluetoothServiceListener.onServiceConnected(BluetoothProfile.HEADSET, mocked BluetoothHeadset); | |
243 // In real life, the AppRTC audio manager makes this call. | |
244 bluetoothManager.updateDevice(); | |
245 } | |
246 | |
247 private void simulateBluetoothServiceDisconnected() { | |
248 bluetoothServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET); | |
249 } | |
250 | |
251 private void simulateBluetoothHeadsetConnected() { | |
252 Intent intent = new Intent(); | |
253 intent.setAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); | |
254 intent.putExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_CONNECT ED); | |
255 bluetoothHeadsetStateReceiver.onReceive(context, intent); | |
256 } | |
257 | |
258 private void simulateBluetoothScoConnectionConnected() { | |
259 Intent intent = new Intent(); | |
260 intent.setAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); | |
261 intent.putExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_C ONNECTED); | |
262 bluetoothHeadsetStateReceiver.onReceive(context, intent); | |
263 } | |
264 | |
265 private void simulateBluetoothScoConnectionDisconnected() { | |
266 Intent intent = new Intent(); | |
267 intent.setAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); | |
268 intent.putExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_D ISCONNECTED); | |
269 bluetoothHeadsetStateReceiver.onReceive(context, intent); | |
270 } | |
271 } | |
OLD | NEW |