• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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.bluetooth.hfp;
18 
19 import static org.mockito.Mockito.*;
20 
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothDevice;
23 import android.bluetooth.BluetoothHeadset;
24 import android.bluetooth.BluetoothProfile;
25 import android.bluetooth.BluetoothUuid;
26 import android.bluetooth.IBluetoothHeadset;
27 import android.content.Context;
28 import android.media.AudioManager;
29 import android.os.ParcelUuid;
30 import android.os.RemoteException;
31 import android.os.SystemClock;
32 import android.support.test.InstrumentationRegistry;
33 import android.support.test.filters.MediumTest;
34 import android.support.test.rule.ServiceTestRule;
35 import android.support.test.runner.AndroidJUnit4;
36 
37 import com.android.bluetooth.R;
38 import com.android.bluetooth.TestUtils;
39 import com.android.bluetooth.btservice.AdapterService;
40 
41 import org.hamcrest.Matchers;
42 import org.junit.After;
43 import org.junit.Assert;
44 import org.junit.Assume;
45 import org.junit.Before;
46 import org.junit.Rule;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 import org.mockito.Mock;
50 import org.mockito.MockitoAnnotations;
51 import org.mockito.Spy;
52 
53 import java.lang.reflect.Method;
54 import java.util.ArrayList;
55 import java.util.Collections;
56 import java.util.HashMap;
57 import java.util.Set;
58 
59 /**
60  * Tests for {@link HeadsetService}
61  */
62 @MediumTest
63 @RunWith(AndroidJUnit4.class)
64 public class HeadsetServiceTest {
65     private static final int MAX_HEADSET_CONNECTIONS = 5;
66     private static final ParcelUuid[] FAKE_HEADSET_UUID = {BluetoothUuid.Handsfree};
67     private static final int ASYNC_CALL_TIMEOUT_MILLIS = 250;
68     private static final String TEST_PHONE_NUMBER = "1234567890";
69 
70     private Context mTargetContext;
71     private HeadsetService mHeadsetService;
72     private IBluetoothHeadset.Stub mHeadsetServiceBinder;
73     private BluetoothAdapter mAdapter;
74     private HeadsetNativeInterface mNativeInterface;
75     private BluetoothDevice mCurrentDevice;
76     private final HashMap<BluetoothDevice, HeadsetStateMachine> mStateMachines = new HashMap<>();
77 
78     @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
79 
80     @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance();
81     @Mock private AdapterService mAdapterService;
82     @Mock private HeadsetSystemInterface mSystemInterface;
83     @Mock private AudioManager mAudioManager;
84     @Mock private HeadsetPhoneState mPhoneState;
85 
86     @Before
setUp()87     public void setUp() throws Exception {
88         mTargetContext = InstrumentationRegistry.getTargetContext();
89         Assume.assumeTrue("Ignore test when HeadsetService is not enabled",
90                 mTargetContext.getResources().getBoolean(R.bool.profile_supported_hs_hfp));
91         MockitoAnnotations.initMocks(this);
92         TestUtils.setAdapterService(mAdapterService);
93         // We cannot mock HeadsetObjectsFactory.getInstance() with Mockito.
94         // Hence we need to use reflection to call a private method to
95         // initialize properly the HeadsetObjectsFactory.sInstance field.
96         Method method = HeadsetObjectsFactory.class.getDeclaredMethod("setInstanceForTesting",
97                 HeadsetObjectsFactory.class);
98         method.setAccessible(true);
99         method.invoke(null, mObjectsFactory);
100         doReturn(true).when(mAdapterService).isEnabled();
101         doReturn(MAX_HEADSET_CONNECTIONS).when(mAdapterService).getMaxConnectedAudioDevices();
102         doReturn(new ParcelUuid[]{BluetoothUuid.Handsfree}).when(mAdapterService)
103                 .getRemoteUuids(any(BluetoothDevice.class));
104         // This line must be called to make sure relevant objects are initialized properly
105         mAdapter = BluetoothAdapter.getDefaultAdapter();
106         // Mock methods in AdapterService
107         doReturn(FAKE_HEADSET_UUID).when(mAdapterService)
108                 .getRemoteUuids(any(BluetoothDevice.class));
109         doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService)
110                 .getBondState(any(BluetoothDevice.class));
111         doAnswer(invocation -> {
112             Set<BluetoothDevice> keys = mStateMachines.keySet();
113             return keys.toArray(new BluetoothDevice[keys.size()]);
114         }).when(mAdapterService).getBondedDevices();
115         // Mock system interface
116         doNothing().when(mSystemInterface).init();
117         doNothing().when(mSystemInterface).stop();
118         when(mSystemInterface.getHeadsetPhoneState()).thenReturn(mPhoneState);
119         when(mSystemInterface.getAudioManager()).thenReturn(mAudioManager);
120         when(mSystemInterface.isCallIdle()).thenReturn(true);
121         // Mock methods in HeadsetNativeInterface
122         mNativeInterface = spy(HeadsetNativeInterface.getInstance());
123         doNothing().when(mNativeInterface).init(anyInt(), anyBoolean());
124         doNothing().when(mNativeInterface).cleanup();
125         doReturn(true).when(mNativeInterface).connectHfp(any(BluetoothDevice.class));
126         doReturn(true).when(mNativeInterface).disconnectHfp(any(BluetoothDevice.class));
127         doReturn(true).when(mNativeInterface).connectAudio(any(BluetoothDevice.class));
128         doReturn(true).when(mNativeInterface).disconnectAudio(any(BluetoothDevice.class));
129         doReturn(true).when(mNativeInterface).setActiveDevice(any(BluetoothDevice.class));
130         doReturn(true).when(mNativeInterface).sendBsir(any(BluetoothDevice.class), anyBoolean());
131         // Mock methods in HeadsetObjectsFactory
132         doAnswer(invocation -> {
133             Assert.assertNotNull(mCurrentDevice);
134             final HeadsetStateMachine stateMachine = mock(HeadsetStateMachine.class);
135             doReturn(BluetoothProfile.STATE_DISCONNECTED).when(stateMachine).getConnectionState();
136             doReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED).when(stateMachine).getAudioState();
137             mStateMachines.put(mCurrentDevice, stateMachine);
138             return stateMachine;
139         }).when(mObjectsFactory).makeStateMachine(any(), any(), any(), any(), any(), any());
140         doReturn(mSystemInterface).when(mObjectsFactory).makeSystemInterface(any());
141         doReturn(mNativeInterface).when(mObjectsFactory).getNativeInterface();
142         TestUtils.startService(mServiceRule, HeadsetService.class);
143         mHeadsetService = HeadsetService.getHeadsetService();
144         Assert.assertNotNull(mHeadsetService);
145         verify(mObjectsFactory).makeSystemInterface(mHeadsetService);
146         verify(mObjectsFactory).getNativeInterface();
147         mHeadsetServiceBinder = (IBluetoothHeadset.Stub) mHeadsetService.initBinder();
148         Assert.assertNotNull(mHeadsetServiceBinder);
149         mHeadsetServiceBinder.setForceScoAudio(true);
150     }
151 
152     @After
tearDown()153     public void tearDown() throws Exception {
154         if (!mTargetContext.getResources().getBoolean(R.bool.profile_supported_hs_hfp)) {
155             return;
156         }
157         TestUtils.stopService(mServiceRule, HeadsetService.class);
158         mHeadsetService = HeadsetService.getHeadsetService();
159         Assert.assertNull(mHeadsetService);
160         mStateMachines.clear();
161         mCurrentDevice = null;
162         Method method = HeadsetObjectsFactory.class.getDeclaredMethod("setInstanceForTesting",
163                 HeadsetObjectsFactory.class);
164         method.setAccessible(true);
165         method.invoke(null, (HeadsetObjectsFactory) null);
166         TestUtils.clearAdapterService(mAdapterService);
167     }
168 
169     /**
170      * Test to verify that HeadsetService can be successfully started
171      */
172     @Test
testGetHeadsetService()173     public void testGetHeadsetService() {
174         Assert.assertEquals(mHeadsetService, HeadsetService.getHeadsetService());
175         // Verify default connection and audio states
176         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
177         Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED,
178                 mHeadsetService.getConnectionState(mCurrentDevice));
179         Assert.assertEquals(BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
180                 mHeadsetService.getAudioState(mCurrentDevice));
181     }
182 
183     /**
184      *  Test okToAcceptConnection method using various test cases
185      */
186     @Test
testOkToAcceptConnection()187     public void testOkToAcceptConnection() {
188         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
189         int badPriorityValue = 1024;
190         int badBondState = 42;
191         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_NONE,
192                 BluetoothProfile.PRIORITY_UNDEFINED, false);
193         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_NONE,
194                 BluetoothProfile.PRIORITY_OFF, false);
195         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_NONE,
196                 BluetoothProfile.PRIORITY_ON, false);
197         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_NONE,
198                 BluetoothProfile.PRIORITY_AUTO_CONNECT, false);
199         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_NONE, badPriorityValue,
200                 false);
201         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDING,
202                 BluetoothProfile.PRIORITY_UNDEFINED, false);
203         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDING,
204                 BluetoothProfile.PRIORITY_OFF, false);
205         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDING,
206                 BluetoothProfile.PRIORITY_ON, false);
207         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDING,
208                 BluetoothProfile.PRIORITY_AUTO_CONNECT, false);
209         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDING, badPriorityValue,
210                 false);
211         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDED,
212                 BluetoothProfile.PRIORITY_UNDEFINED, true);
213         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDED,
214                 BluetoothProfile.PRIORITY_OFF, false);
215         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDED,
216                 BluetoothProfile.PRIORITY_ON, true);
217         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDED,
218                 BluetoothProfile.PRIORITY_AUTO_CONNECT, true);
219         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDED, badPriorityValue,
220                 false);
221         testOkToAcceptConnectionCase(mCurrentDevice, badBondState,
222                 BluetoothProfile.PRIORITY_UNDEFINED, false);
223         testOkToAcceptConnectionCase(mCurrentDevice, badBondState, BluetoothProfile.PRIORITY_OFF,
224                 false);
225         testOkToAcceptConnectionCase(mCurrentDevice, badBondState, BluetoothProfile.PRIORITY_ON,
226                 false);
227         testOkToAcceptConnectionCase(mCurrentDevice, badBondState,
228                 BluetoothProfile.PRIORITY_AUTO_CONNECT, false);
229         testOkToAcceptConnectionCase(mCurrentDevice, badBondState, badPriorityValue, false);
230         // Restore prirority to undefined for this test device
231         Assert.assertTrue(
232                 mHeadsetService.setPriority(mCurrentDevice, BluetoothProfile.PRIORITY_UNDEFINED));
233     }
234 
235     /**
236      * Test to verify that {@link HeadsetService#connect(BluetoothDevice)} returns true when the
237      * device was not connected and number of connected devices is less than
238      * {@link #MAX_HEADSET_CONNECTIONS}
239      */
240     @Test
testConnectDevice_connectDeviceBelowLimit()241     public void testConnectDevice_connectDeviceBelowLimit() {
242         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
243         Assert.assertTrue(mHeadsetService.connect(mCurrentDevice));
244         verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
245                 mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService, mAdapterService,
246                 mNativeInterface, mSystemInterface);
247         verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT,
248                 mCurrentDevice);
249         when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
250         when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
251                 BluetoothProfile.STATE_CONNECTING);
252         Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
253                 mHeadsetService.getConnectionState(mCurrentDevice));
254         when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
255                 BluetoothProfile.STATE_CONNECTED);
256         Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
257                 mHeadsetService.getConnectionState(mCurrentDevice));
258         Assert.assertEquals(Collections.singletonList(mCurrentDevice),
259                 mHeadsetService.getConnectedDevices());
260         // 2nd connection attempt will fail
261         Assert.assertFalse(mHeadsetService.connect(mCurrentDevice));
262         // Verify makeStateMachine is only called once
263         verify(mObjectsFactory).makeStateMachine(any(), any(), any(), any(), any(), any());
264         // Verify CONNECT is only sent once
265         verify(mStateMachines.get(mCurrentDevice)).sendMessage(eq(HeadsetStateMachine.CONNECT),
266                 any());
267     }
268 
269     /**
270      * Test that {@link HeadsetService#messageFromNative(HeadsetStackEvent)} will send correct
271      * message to the underlying state machine
272      */
273     @Test
testMessageFromNative_deviceConnected()274     public void testMessageFromNative_deviceConnected() {
275         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
276         // Test connect from native
277         HeadsetStackEvent connectedEvent =
278                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
279                         HeadsetHalConstants.CONNECTION_STATE_CONNECTED, mCurrentDevice);
280         mHeadsetService.messageFromNative(connectedEvent);
281         verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
282                 mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService, mAdapterService,
283                 mNativeInterface, mSystemInterface);
284         verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.STACK_EVENT,
285                 connectedEvent);
286         when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
287         when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
288                 BluetoothProfile.STATE_CONNECTED);
289         Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
290                 mHeadsetService.getConnectionState(mCurrentDevice));
291         Assert.assertEquals(Collections.singletonList(mCurrentDevice),
292                 mHeadsetService.getConnectedDevices());
293         // Test disconnect from native
294         HeadsetStackEvent disconnectEvent =
295                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
296                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mCurrentDevice);
297         mHeadsetService.messageFromNative(disconnectEvent);
298         verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.STACK_EVENT,
299                 disconnectEvent);
300         when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
301                 BluetoothProfile.STATE_DISCONNECTED);
302         Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED,
303                 mHeadsetService.getConnectionState(mCurrentDevice));
304         Assert.assertEquals(Collections.EMPTY_LIST, mHeadsetService.getConnectedDevices());
305     }
306 
307     /**
308      * Stack connection event to {@link HeadsetHalConstants#CONNECTION_STATE_CONNECTING} should
309      * create new state machine
310      */
311     @Test
testMessageFromNative_deviceConnectingUnknown()312     public void testMessageFromNative_deviceConnectingUnknown() {
313         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
314         HeadsetStackEvent connectingEvent =
315                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
316                         HeadsetHalConstants.CONNECTION_STATE_CONNECTING, mCurrentDevice);
317         mHeadsetService.messageFromNative(connectingEvent);
318         verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
319                 mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService, mAdapterService,
320                 mNativeInterface, mSystemInterface);
321         verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.STACK_EVENT,
322                 connectingEvent);
323     }
324 
325     /**
326      * Stack connection event to {@link HeadsetHalConstants#CONNECTION_STATE_DISCONNECTED} should
327      * crash by throwing {@link IllegalStateException} if the device is unknown
328      */
329     @Test
testMessageFromNative_deviceDisconnectedUnknown()330     public void testMessageFromNative_deviceDisconnectedUnknown() {
331         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
332         HeadsetStackEvent connectingEvent =
333                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
334                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mCurrentDevice);
335         try {
336             mHeadsetService.messageFromNative(connectingEvent);
337             Assert.fail("Expect an IllegalStateException");
338         } catch (IllegalStateException exception) {
339             // Do nothing
340         }
341         verifyNoMoreInteractions(mObjectsFactory);
342     }
343 
344     /**
345      * Test to verify that {@link HeadsetService#connect(BluetoothDevice)} fails after
346      * {@link #MAX_HEADSET_CONNECTIONS} connection requests
347      */
348     @Test
testConnectDevice_connectDeviceAboveLimit()349     public void testConnectDevice_connectDeviceAboveLimit() {
350         ArrayList<BluetoothDevice> connectedDevices = new ArrayList<>();
351         for (int i = 0; i < MAX_HEADSET_CONNECTIONS; ++i) {
352             mCurrentDevice = TestUtils.getTestDevice(mAdapter, i);
353             Assert.assertTrue(mHeadsetService.connect(mCurrentDevice));
354             verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
355                     mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService,
356                     mAdapterService, mNativeInterface, mSystemInterface);
357             verify(mObjectsFactory, times(i + 1)).makeStateMachine(any(BluetoothDevice.class),
358                     eq(mHeadsetService.getStateMachinesThreadLooper()), eq(mHeadsetService),
359                     eq(mAdapterService), eq(mNativeInterface), eq(mSystemInterface));
360             verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT,
361                     mCurrentDevice);
362             verify(mStateMachines.get(mCurrentDevice)).sendMessage(eq(HeadsetStateMachine.CONNECT),
363                     any(BluetoothDevice.class));
364             // Put device to connecting
365             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
366                     BluetoothProfile.STATE_CONNECTING);
367             Assert.assertThat(mHeadsetService.getConnectedDevices(),
368                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
369             // Put device to connected
370             connectedDevices.add(mCurrentDevice);
371             when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
372             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
373                     BluetoothProfile.STATE_CONNECTED);
374             Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
375                     mHeadsetService.getConnectionState(mCurrentDevice));
376             Assert.assertThat(mHeadsetService.getConnectedDevices(),
377                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
378         }
379         // Connect the next device will fail
380         mCurrentDevice = TestUtils.getTestDevice(mAdapter, MAX_HEADSET_CONNECTIONS);
381         Assert.assertFalse(mHeadsetService.connect(mCurrentDevice));
382         // Though connection failed, a new state machine is still lazily created for the device
383         verify(mObjectsFactory, times(MAX_HEADSET_CONNECTIONS + 1)).makeStateMachine(
384                 any(BluetoothDevice.class), eq(mHeadsetService.getStateMachinesThreadLooper()),
385                 eq(mHeadsetService), eq(mAdapterService), eq(mNativeInterface),
386                 eq(mSystemInterface));
387         Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED,
388                 mHeadsetService.getConnectionState(mCurrentDevice));
389         Assert.assertThat(mHeadsetService.getConnectedDevices(),
390                 Matchers.containsInAnyOrder(connectedDevices.toArray()));
391     }
392 
393     /**
394      * Test to verify that {@link HeadsetService#connectAudio(BluetoothDevice)} return true when
395      * the device is connected and audio is not connected and returns false when audio is already
396      * connecting
397      */
398     @Test
testConnectAudio_withOneDevice()399     public void testConnectAudio_withOneDevice() {
400         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
401         Assert.assertTrue(mHeadsetService.connect(mCurrentDevice));
402         verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
403                 mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService, mAdapterService,
404                 mNativeInterface, mSystemInterface);
405         verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT,
406                 mCurrentDevice);
407         when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
408         when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
409                 BluetoothProfile.STATE_CONNECTED);
410         when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()).thenReturn(
411                 SystemClock.uptimeMillis());
412         Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
413                 mHeadsetService.getConnectionState(mCurrentDevice));
414         Assert.assertEquals(Collections.singletonList(mCurrentDevice),
415                 mHeadsetService.getConnectedDevices());
416         mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
417                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED);
418         // Test connect audio - set the device first as the active device
419         Assert.assertTrue(mHeadsetService.setActiveDevice(mCurrentDevice));
420         Assert.assertTrue(mHeadsetService.connectAudio(mCurrentDevice));
421         verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT_AUDIO,
422                 mCurrentDevice);
423         when(mStateMachines.get(mCurrentDevice).getAudioState()).thenReturn(
424                 BluetoothHeadset.STATE_AUDIO_CONNECTING);
425         // 2nd connection attempt for the same device will succeed as well
426         Assert.assertTrue(mHeadsetService.connectAudio(mCurrentDevice));
427         // Verify CONNECT_AUDIO is only sent once
428         verify(mStateMachines.get(mCurrentDevice)).sendMessage(
429                 eq(HeadsetStateMachine.CONNECT_AUDIO), any());
430         // Test disconnect audio
431         Assert.assertTrue(mHeadsetService.disconnectAudio(mCurrentDevice));
432         verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO,
433                 mCurrentDevice);
434         when(mStateMachines.get(mCurrentDevice).getAudioState()).thenReturn(
435                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
436         // Further disconnection requests will fail
437         Assert.assertFalse(mHeadsetService.disconnectAudio(mCurrentDevice));
438         verify(mStateMachines.get(mCurrentDevice)).sendMessage(
439                 eq(HeadsetStateMachine.DISCONNECT_AUDIO), any(BluetoothDevice.class));
440     }
441 
442     /**
443      * Test to verify that HFP audio connection can be initiated when multiple devices are connected
444      * and can be canceled or disconnected as well
445      */
446     @Test
testConnectAudio_withMultipleDevices()447     public void testConnectAudio_withMultipleDevices() {
448         ArrayList<BluetoothDevice> connectedDevices = new ArrayList<>();
449         for (int i = 0; i < MAX_HEADSET_CONNECTIONS; ++i) {
450             mCurrentDevice = TestUtils.getTestDevice(mAdapter, i);
451             Assert.assertTrue(mHeadsetService.connect(mCurrentDevice));
452             verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
453                     mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService,
454                     mAdapterService, mNativeInterface, mSystemInterface);
455             verify(mObjectsFactory, times(i + 1)).makeStateMachine(any(BluetoothDevice.class),
456                     eq(mHeadsetService.getStateMachinesThreadLooper()), eq(mHeadsetService),
457                     eq(mAdapterService), eq(mNativeInterface), eq(mSystemInterface));
458             verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT,
459                     mCurrentDevice);
460             verify(mStateMachines.get(mCurrentDevice)).sendMessage(eq(HeadsetStateMachine.CONNECT),
461                     any(BluetoothDevice.class));
462             // Put device to connecting
463             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
464                     BluetoothProfile.STATE_CONNECTING);
465             mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
466                     BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING);
467             Assert.assertThat(mHeadsetService.getConnectedDevices(),
468                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
469             // Put device to connected
470             connectedDevices.add(mCurrentDevice);
471             when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
472             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
473                     BluetoothProfile.STATE_CONNECTED);
474             when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()).thenReturn(
475                     SystemClock.uptimeMillis());
476             Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
477                     mHeadsetService.getConnectionState(mCurrentDevice));
478             mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
479                     BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED);
480             Assert.assertThat(mHeadsetService.getConnectedDevices(),
481                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
482             // Try to connect audio
483             // Should fail
484             Assert.assertFalse(mHeadsetService.connectAudio(mCurrentDevice));
485             // Should succeed after setActiveDevice()
486             Assert.assertTrue(mHeadsetService.setActiveDevice(mCurrentDevice));
487             Assert.assertTrue(mHeadsetService.connectAudio(mCurrentDevice));
488             verify(mStateMachines.get(mCurrentDevice)).sendMessage(
489                     HeadsetStateMachine.CONNECT_AUDIO, mCurrentDevice);
490             // Put device to audio connecting state
491             when(mStateMachines.get(mCurrentDevice).getAudioState()).thenReturn(
492                     BluetoothHeadset.STATE_AUDIO_CONNECTING);
493             // 2nd connection attempt will also succeed
494             Assert.assertTrue(mHeadsetService.connectAudio(mCurrentDevice));
495             // Verify CONNECT_AUDIO is only sent once
496             verify(mStateMachines.get(mCurrentDevice)).sendMessage(
497                     eq(HeadsetStateMachine.CONNECT_AUDIO), any());
498             // Put device to audio connected state
499             when(mStateMachines.get(mCurrentDevice).getAudioState()).thenReturn(
500                     BluetoothHeadset.STATE_AUDIO_CONNECTED);
501             // Disconnect audio
502             Assert.assertTrue(mHeadsetService.disconnectAudio(mCurrentDevice));
503             verify(mStateMachines.get(mCurrentDevice)).sendMessage(
504                     HeadsetStateMachine.DISCONNECT_AUDIO, mCurrentDevice);
505             when(mStateMachines.get(mCurrentDevice).getAudioState()).thenReturn(
506                     BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
507             // Further disconnection requests will fail
508             Assert.assertFalse(mHeadsetService.disconnectAudio(mCurrentDevice));
509             verify(mStateMachines.get(mCurrentDevice)).sendMessage(
510                     eq(HeadsetStateMachine.DISCONNECT_AUDIO), any(BluetoothDevice.class));
511         }
512     }
513 
514     /**
515      * Verify that only one device can be in audio connecting or audio connected state, further
516      * attempt to call {@link HeadsetService#connectAudio(BluetoothDevice)} should fail by returning
517      * false
518      */
519     @Test
testConnectAudio_connectTwoAudioChannelsShouldFail()520     public void testConnectAudio_connectTwoAudioChannelsShouldFail() {
521         ArrayList<BluetoothDevice> connectedDevices = new ArrayList<>();
522         for (int i = 0; i < MAX_HEADSET_CONNECTIONS; ++i) {
523             mCurrentDevice = TestUtils.getTestDevice(mAdapter, i);
524             Assert.assertTrue(mHeadsetService.connect(mCurrentDevice));
525             verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
526                     mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService,
527                     mAdapterService, mNativeInterface, mSystemInterface);
528             verify(mObjectsFactory, times(i + 1)).makeStateMachine(any(BluetoothDevice.class),
529                     eq(mHeadsetService.getStateMachinesThreadLooper()), eq(mHeadsetService),
530                     eq(mAdapterService), eq(mNativeInterface), eq(mSystemInterface));
531             verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT,
532                     mCurrentDevice);
533             verify(mStateMachines.get(mCurrentDevice)).sendMessage(eq(HeadsetStateMachine.CONNECT),
534                     any(BluetoothDevice.class));
535             // Put device to connecting
536             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
537                     BluetoothProfile.STATE_CONNECTING);
538             mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
539                     BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING);
540             Assert.assertThat(mHeadsetService.getConnectedDevices(),
541                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
542             // Put device to connected
543             connectedDevices.add(mCurrentDevice);
544             when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
545             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
546                     BluetoothProfile.STATE_CONNECTED);
547             when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()).thenReturn(
548                     SystemClock.uptimeMillis());
549             mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
550                     BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED);
551             Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
552                     mHeadsetService.getConnectionState(mCurrentDevice));
553             Assert.assertThat(mHeadsetService.getConnectedDevices(),
554                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
555         }
556         if (MAX_HEADSET_CONNECTIONS >= 2) {
557             // Try to connect audio
558             BluetoothDevice firstDevice = connectedDevices.get(0);
559             BluetoothDevice secondDevice = connectedDevices.get(1);
560             // Set the first device as the active device
561             Assert.assertTrue(mHeadsetService.setActiveDevice(firstDevice));
562             Assert.assertTrue(mHeadsetService.connectAudio(firstDevice));
563             verify(mStateMachines.get(firstDevice)).sendMessage(HeadsetStateMachine.CONNECT_AUDIO,
564                     firstDevice);
565             // Put device to audio connecting state
566             when(mStateMachines.get(firstDevice).getAudioState()).thenReturn(
567                     BluetoothHeadset.STATE_AUDIO_CONNECTING);
568             // 2nd connection attempt will succeed for the same device
569             Assert.assertTrue(mHeadsetService.connectAudio(firstDevice));
570             // Connect to 2nd device will fail
571             Assert.assertFalse(mHeadsetService.connectAudio(secondDevice));
572             verify(mStateMachines.get(secondDevice), never()).sendMessage(
573                     HeadsetStateMachine.CONNECT_AUDIO, secondDevice);
574             // Put device to audio connected state
575             when(mStateMachines.get(firstDevice).getAudioState()).thenReturn(
576                     BluetoothHeadset.STATE_AUDIO_CONNECTED);
577             // Connect to 2nd device will fail
578             Assert.assertFalse(mHeadsetService.connectAudio(secondDevice));
579             verify(mStateMachines.get(secondDevice), never()).sendMessage(
580                     HeadsetStateMachine.CONNECT_AUDIO, secondDevice);
581         }
582     }
583 
584     /**
585      * Verify that {@link HeadsetService#connectAudio()} will connect to first connected/connecting
586      * device
587      */
588     @Test
testConnectAudio_firstConnectedAudioDevice()589     public void testConnectAudio_firstConnectedAudioDevice() {
590         ArrayList<BluetoothDevice> connectedDevices = new ArrayList<>();
591         doAnswer(invocation -> {
592             BluetoothDevice[] devicesArray = new BluetoothDevice[connectedDevices.size()];
593             return connectedDevices.toArray(devicesArray);
594         }).when(mAdapterService).getBondedDevices();
595         for (int i = 0; i < MAX_HEADSET_CONNECTIONS; ++i) {
596             mCurrentDevice = TestUtils.getTestDevice(mAdapter, i);
597             Assert.assertTrue(mHeadsetService.connect(mCurrentDevice));
598             verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
599                     mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService,
600                     mAdapterService, mNativeInterface, mSystemInterface);
601             verify(mObjectsFactory, times(i + 1)).makeStateMachine(any(BluetoothDevice.class),
602                     eq(mHeadsetService.getStateMachinesThreadLooper()), eq(mHeadsetService),
603                     eq(mAdapterService), eq(mNativeInterface), eq(mSystemInterface));
604             verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT,
605                     mCurrentDevice);
606             verify(mStateMachines.get(mCurrentDevice)).sendMessage(eq(HeadsetStateMachine.CONNECT),
607                     any(BluetoothDevice.class));
608             // Put device to connecting
609             when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()).thenReturn(
610                     SystemClock.uptimeMillis());
611             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
612                     BluetoothProfile.STATE_CONNECTING);
613             mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
614                     BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING);
615             Assert.assertThat(mHeadsetService.getConnectedDevices(),
616                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
617             // Put device to connected
618             connectedDevices.add(mCurrentDevice);
619             when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
620             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
621                     BluetoothProfile.STATE_CONNECTED);
622             when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()).thenReturn(
623                     SystemClock.uptimeMillis());
624             Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
625                     mHeadsetService.getConnectionState(mCurrentDevice));
626             Assert.assertThat(mHeadsetService.getConnectedDevices(),
627                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
628             mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
629                     BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED);
630         }
631         // Try to connect audio
632         BluetoothDevice firstDevice = connectedDevices.get(0);
633         Assert.assertTrue(mHeadsetService.setActiveDevice(firstDevice));
634         Assert.assertTrue(mHeadsetService.connectAudio());
635         verify(mStateMachines.get(firstDevice)).sendMessage(HeadsetStateMachine.CONNECT_AUDIO,
636                 firstDevice);
637     }
638 
639     /**
640      * Test to verify that {@link HeadsetService#connectAudio(BluetoothDevice)} fails if device
641      * was never connected
642      */
643     @Test
testConnectAudio_deviceNeverConnected()644     public void testConnectAudio_deviceNeverConnected() {
645         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
646         Assert.assertFalse(mHeadsetService.connectAudio(mCurrentDevice));
647     }
648 
649     /**
650      * Test to verify that {@link HeadsetService#connectAudio(BluetoothDevice)} fails if device
651      * is disconnected
652      */
653     @Test
testConnectAudio_deviceDisconnected()654     public void testConnectAudio_deviceDisconnected() {
655         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
656         HeadsetCallState headsetCallState =
657                 new HeadsetCallState(1, 0, HeadsetHalConstants.CALL_STATE_ALERTING,
658                         TEST_PHONE_NUMBER, 128);
659         Assert.assertTrue(mHeadsetService.connect(mCurrentDevice));
660         verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
661                 mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService, mAdapterService,
662                 mNativeInterface, mSystemInterface);
663         verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT,
664                 mCurrentDevice);
665         when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
666         // Put device in disconnected state
667         when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
668                 BluetoothProfile.STATE_DISCONNECTED);
669         Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED,
670                 mHeadsetService.getConnectionState(mCurrentDevice));
671         Assert.assertEquals(Collections.EMPTY_LIST, mHeadsetService.getConnectedDevices());
672         mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
673                 BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED);
674         // connectAudio should fail
675         Assert.assertFalse(mHeadsetService.connectAudio(mCurrentDevice));
676         verify(mStateMachines.get(mCurrentDevice), never()).sendMessage(
677                 eq(HeadsetStateMachine.CONNECT_AUDIO), any());
678     }
679 
680     /**
681      * Verifies that phone state change will trigger a system-wide saving of call state even when
682      * no device is connected
683      *
684      * @throws RemoteException if binder call fails
685      */
686     @Test
testPhoneStateChange_noDeviceSaveState()687     public void testPhoneStateChange_noDeviceSaveState() throws RemoteException {
688         HeadsetCallState headsetCallState =
689                 new HeadsetCallState(1, 0, HeadsetHalConstants.CALL_STATE_ALERTING,
690                         TEST_PHONE_NUMBER, 128);
691         mHeadsetServiceBinder.phoneStateChanged(headsetCallState.mNumActive,
692                 headsetCallState.mNumHeld, headsetCallState.mCallState, headsetCallState.mNumber,
693                 headsetCallState.mType);
694         HeadsetTestUtils.verifyPhoneStateChangeSetters(mPhoneState, headsetCallState,
695                 ASYNC_CALL_TIMEOUT_MILLIS);
696     }
697 
698     /**
699      * Verifies that phone state change will trigger a system-wide saving of call state and send
700      * state change to connected devices
701      *
702      * @throws RemoteException if binder call fails
703      */
704     @Test
testPhoneStateChange_oneDeviceSaveState()705     public void testPhoneStateChange_oneDeviceSaveState() throws RemoteException {
706         HeadsetCallState headsetCallState =
707                 new HeadsetCallState(1, 0, HeadsetHalConstants.CALL_STATE_ALERTING,
708                         TEST_PHONE_NUMBER, 128);
709         mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0);
710         final ArrayList<BluetoothDevice> connectedDevices = new ArrayList<>();
711         // Connect one device
712         Assert.assertTrue(mHeadsetService.connect(mCurrentDevice));
713         verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
714                 mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService, mAdapterService,
715                 mNativeInterface, mSystemInterface);
716         verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT,
717                 mCurrentDevice);
718         when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
719         // Put device to connecting
720         when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()).thenReturn(
721                 SystemClock.uptimeMillis());
722         when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
723                 BluetoothProfile.STATE_CONNECTING);
724         mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
725                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING);
726         Assert.assertThat(mHeadsetService.getConnectedDevices(),
727                 Matchers.containsInAnyOrder(connectedDevices.toArray()));
728         // Put device to connected
729         connectedDevices.add(mCurrentDevice);
730         when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
731         when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
732                 BluetoothProfile.STATE_CONNECTED);
733         when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()).thenReturn(
734                 SystemClock.uptimeMillis());
735         Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
736                 mHeadsetService.getConnectionState(mCurrentDevice));
737         Assert.assertThat(mHeadsetService.getConnectedDevices(),
738                 Matchers.containsInAnyOrder(connectedDevices.toArray()));
739         mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
740                 BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED);
741         // Change phone state
742         mHeadsetServiceBinder.phoneStateChanged(headsetCallState.mNumActive,
743                 headsetCallState.mNumHeld, headsetCallState.mCallState, headsetCallState.mNumber,
744                 headsetCallState.mType);
745         // Make sure we notify device about this change
746         verify(mStateMachines.get(mCurrentDevice)).sendMessage(
747                 HeadsetStateMachine.CALL_STATE_CHANGED, headsetCallState);
748         // Make sure state is updated once in phone state holder
749         HeadsetTestUtils.verifyPhoneStateChangeSetters(mPhoneState, headsetCallState,
750                 ASYNC_CALL_TIMEOUT_MILLIS);
751     }
752 
753     /**
754      * Verifies that phone state change will trigger a system-wide saving of call state and send
755      * state change to connected devices
756      *
757      * @throws RemoteException if binder call fails
758      */
759     @Test
testPhoneStateChange_multipleDevicesSaveState()760     public void testPhoneStateChange_multipleDevicesSaveState() throws RemoteException {
761         HeadsetCallState headsetCallState =
762                 new HeadsetCallState(1, 0, HeadsetHalConstants.CALL_STATE_ALERTING,
763                         TEST_PHONE_NUMBER, 128);
764         final ArrayList<BluetoothDevice> connectedDevices = new ArrayList<>();
765         for (int i = 0; i < MAX_HEADSET_CONNECTIONS; ++i) {
766             mCurrentDevice = TestUtils.getTestDevice(mAdapter, i);
767             Assert.assertTrue(mHeadsetService.connect(mCurrentDevice));
768             verify(mObjectsFactory).makeStateMachine(mCurrentDevice,
769                     mHeadsetService.getStateMachinesThreadLooper(), mHeadsetService,
770                     mAdapterService, mNativeInterface, mSystemInterface);
771             verify(mObjectsFactory, times(i + 1)).makeStateMachine(any(BluetoothDevice.class),
772                     eq(mHeadsetService.getStateMachinesThreadLooper()), eq(mHeadsetService),
773                     eq(mAdapterService), eq(mNativeInterface), eq(mSystemInterface));
774             verify(mStateMachines.get(mCurrentDevice)).sendMessage(HeadsetStateMachine.CONNECT,
775                     mCurrentDevice);
776             verify(mStateMachines.get(mCurrentDevice)).sendMessage(eq(HeadsetStateMachine.CONNECT),
777                     any(BluetoothDevice.class));
778             // Put device to connecting
779             when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()).thenReturn(
780                     SystemClock.uptimeMillis());
781             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
782                     BluetoothProfile.STATE_CONNECTING);
783             mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
784                     BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING);
785             Assert.assertThat(mHeadsetService.getConnectedDevices(),
786                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
787             // Put device to connected
788             connectedDevices.add(mCurrentDevice);
789             when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice);
790             when(mStateMachines.get(mCurrentDevice).getConnectionState()).thenReturn(
791                     BluetoothProfile.STATE_CONNECTED);
792             when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()).thenReturn(
793                     SystemClock.uptimeMillis());
794             Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
795                     mHeadsetService.getConnectionState(mCurrentDevice));
796             Assert.assertThat(mHeadsetService.getConnectedDevices(),
797                     Matchers.containsInAnyOrder(connectedDevices.toArray()));
798             mHeadsetService.onConnectionStateChangedFromStateMachine(mCurrentDevice,
799                     BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED);
800         }
801         // Change phone state
802         mHeadsetServiceBinder.phoneStateChanged(headsetCallState.mNumActive,
803                 headsetCallState.mNumHeld, headsetCallState.mCallState, headsetCallState.mNumber,
804                 headsetCallState.mType);
805         // Make sure we notify devices about this change
806         for (BluetoothDevice device : connectedDevices) {
807             verify(mStateMachines.get(device)).sendMessage(HeadsetStateMachine.CALL_STATE_CHANGED,
808                     headsetCallState);
809         }
810         // Make sure state is updated once in phone state holder
811         HeadsetTestUtils.verifyPhoneStateChangeSetters(mPhoneState, headsetCallState,
812                 ASYNC_CALL_TIMEOUT_MILLIS);
813     }
814 
815     /*
816      *  Helper function to test okToAcceptConnection() method
817      *
818      *  @param device test device
819      *  @param bondState bond state value, could be invalid
820      *  @param priority value, could be invalid, coudl be invalid
821      *  @param expected expected result from okToAcceptConnection()
822      */
testOkToAcceptConnectionCase(BluetoothDevice device, int bondState, int priority, boolean expected)823     private void testOkToAcceptConnectionCase(BluetoothDevice device, int bondState, int priority,
824             boolean expected) {
825         doReturn(bondState).when(mAdapterService).getBondState(device);
826         Assert.assertTrue(mHeadsetService.setPriority(device, priority));
827         Assert.assertEquals(expected, mHeadsetService.okToAcceptConnection(device));
828     }
829 
830 }
831