Home | History | Annotate | Download | only in hfp
      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
     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
    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
    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
    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, true);
    203         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDING,
    204                 BluetoothProfile.PRIORITY_OFF, false);
    205         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDING,
    206                 BluetoothProfile.PRIORITY_ON, true);
    207         testOkToAcceptConnectionCase(mCurrentDevice, BluetoothDevice.BOND_BONDING,
    208                 BluetoothProfile.PRIORITY_AUTO_CONNECT, true);
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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      */
    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