Home | History | Annotate | Download | only in hfp
      1 /*
      2  * Copyright 2017 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.content.Context;
     26 import android.content.Intent;
     27 import android.content.ServiceConnection;
     28 import android.database.Cursor;
     29 import android.media.AudioManager;
     30 import android.net.Uri;
     31 import android.os.HandlerThread;
     32 import android.os.UserHandle;
     33 import android.provider.CallLog;
     34 import android.support.test.InstrumentationRegistry;
     35 import android.support.test.filters.MediumTest;
     36 import android.support.test.runner.AndroidJUnit4;
     37 import android.telephony.PhoneStateListener;
     38 import android.test.mock.MockContentProvider;
     39 import android.test.mock.MockContentResolver;
     40 
     41 import com.android.bluetooth.R;
     42 import com.android.bluetooth.TestUtils;
     43 import com.android.bluetooth.btservice.AdapterService;
     44 
     45 import org.hamcrest.core.IsInstanceOf;
     46 import org.junit.After;
     47 import org.junit.Assert;
     48 import org.junit.Assume;
     49 import org.junit.Before;
     50 import org.junit.Test;
     51 import org.junit.runner.RunWith;
     52 import org.mockito.ArgumentCaptor;
     53 import org.mockito.Mock;
     54 import org.mockito.MockitoAnnotations;
     55 
     56 /**
     57  * Tests for {@link HeadsetStateMachine}
     58  */
     59 @MediumTest
     60 @RunWith(AndroidJUnit4.class)
     61 public class HeadsetStateMachineTest {
     62     private static final int CONNECT_TIMEOUT_TEST_MILLIS = 1000;
     63     private static final int CONNECT_TIMEOUT_TEST_WAIT_MILLIS = CONNECT_TIMEOUT_TEST_MILLIS * 3 / 2;
     64     private static final int ASYNC_CALL_TIMEOUT_MILLIS = 250;
     65     private static final String TEST_PHONE_NUMBER = "1234567890";
     66     private Context mTargetContext;
     67     private BluetoothAdapter mAdapter;
     68     private HandlerThread mHandlerThread;
     69     private HeadsetStateMachine mHeadsetStateMachine;
     70     private BluetoothDevice mTestDevice;
     71     private ArgumentCaptor<Intent> mIntentArgument = ArgumentCaptor.forClass(Intent.class);
     72 
     73     @Mock private AdapterService mAdapterService;
     74     @Mock private HeadsetService mHeadsetService;
     75     @Mock private HeadsetSystemInterface mSystemInterface;
     76     @Mock private AudioManager mAudioManager;
     77     @Mock private HeadsetPhoneState mPhoneState;
     78     private MockContentResolver mMockContentResolver;
     79     private HeadsetNativeInterface mNativeInterface;
     80 
     81     @Before
     82     public void setUp() throws Exception {
     83         mTargetContext = InstrumentationRegistry.getTargetContext();
     84         Assume.assumeTrue("Ignore test when HeadsetService is not enabled",
     85                 mTargetContext.getResources().getBoolean(R.bool.profile_supported_hs_hfp));
     86         // Setup mocks and test assets
     87         MockitoAnnotations.initMocks(this);
     88         TestUtils.setAdapterService(mAdapterService);
     89         // Stub system interface
     90         when(mSystemInterface.getHeadsetPhoneState()).thenReturn(mPhoneState);
     91         when(mSystemInterface.getAudioManager()).thenReturn(mAudioManager);
     92         // This line must be called to make sure relevant objects are initialized properly
     93         mAdapter = BluetoothAdapter.getDefaultAdapter();
     94         // Get a device for testing
     95         mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05");
     96         // Spy on native interface
     97         mNativeInterface = spy(HeadsetNativeInterface.getInstance());
     98         doNothing().when(mNativeInterface).init(anyInt(), anyBoolean());
     99         doReturn(true).when(mNativeInterface).connectHfp(mTestDevice);
    100         doReturn(true).when(mNativeInterface).disconnectHfp(mTestDevice);
    101         doReturn(true).when(mNativeInterface).connectAudio(mTestDevice);
    102         doReturn(true).when(mNativeInterface).disconnectAudio(mTestDevice);
    103         // Stub headset service
    104         mMockContentResolver = new MockContentResolver();
    105         when(mHeadsetService.getContentResolver()).thenReturn(mMockContentResolver);
    106         doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService)
    107                 .getBondState(any(BluetoothDevice.class));
    108         when(mHeadsetService.bindService(any(Intent.class), any(ServiceConnection.class), anyInt()))
    109                 .thenReturn(true);
    110         when(mHeadsetService.getResources()).thenReturn(
    111                 InstrumentationRegistry.getTargetContext().getResources());
    112         when(mHeadsetService.getPackageManager()).thenReturn(
    113                 InstrumentationRegistry.getContext().getPackageManager());
    114         when(mHeadsetService.getPriority(any(BluetoothDevice.class))).thenReturn(
    115                 BluetoothProfile.PRIORITY_ON);
    116         when(mHeadsetService.getForceScoAudio()).thenReturn(true);
    117         when(mHeadsetService.okToAcceptConnection(any(BluetoothDevice.class))).thenReturn(true);
    118         when(mHeadsetService.isScoAcceptable(any(BluetoothDevice.class))).thenReturn(true);
    119         // Setup thread and looper
    120         mHandlerThread = new HandlerThread("HeadsetStateMachineTestHandlerThread");
    121         mHandlerThread.start();
    122         // Modify CONNECT timeout to a smaller value for test only
    123         HeadsetStateMachine.sConnectTimeoutMs = CONNECT_TIMEOUT_TEST_MILLIS;
    124         mHeadsetStateMachine = HeadsetObjectsFactory.getInstance()
    125                 .makeStateMachine(mTestDevice, mHandlerThread.getLooper(), mHeadsetService,
    126                         mAdapterService, mNativeInterface, mSystemInterface);
    127     }
    128 
    129     @After
    130     public void tearDown() throws Exception {
    131         if (!mTargetContext.getResources().getBoolean(R.bool.profile_supported_hs_hfp)) {
    132             return;
    133         }
    134         HeadsetObjectsFactory.getInstance().destroyStateMachine(mHeadsetStateMachine);
    135         mHandlerThread.quit();
    136         TestUtils.clearAdapterService(mAdapterService);
    137     }
    138 
    139     /**
    140      * Test that default state is Disconnected
    141      */
    142     @Test
    143     public void testDefaultDisconnectedState() {
    144         Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED,
    145                 mHeadsetStateMachine.getConnectionState());
    146         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    147                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class));
    148     }
    149 
    150     /**
    151      * Test that state is Connected after calling setUpConnectedState()
    152      */
    153     @Test
    154     public void testSetupConnectedState() {
    155         setUpConnectedState();
    156         Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
    157                 mHeadsetStateMachine.getConnectionState());
    158         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    159                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class));
    160     }
    161 
    162     /**
    163      * Test state transition from Disconnected to Connecting state via CONNECT message
    164      */
    165     @Test
    166     public void testStateTransition_DisconnectedToConnecting_Connect() {
    167         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.CONNECT, mTestDevice);
    168         verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser(
    169                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    170         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    171                 BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED,
    172                 mIntentArgument.getValue());
    173         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    174                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class));
    175     }
    176 
    177     /**
    178      * Test state transition from Disconnected to Connecting state via StackEvent.CONNECTED message
    179      */
    180     @Test
    181     public void testStateTransition_DisconnectedToConnecting_StackConnected() {
    182         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    183                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    184                         HeadsetHalConstants.CONNECTION_STATE_CONNECTED, mTestDevice));
    185         verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser(
    186                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    187         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    188                 BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED,
    189                 mIntentArgument.getValue());
    190         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    191                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class));
    192     }
    193 
    194     /**
    195      * Test state transition from Disconnected to Connecting state via StackEvent.CONNECTING message
    196      */
    197     @Test
    198     public void testStateTransition_DisconnectedToConnecting_StackConnecting() {
    199         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    200                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    201                         HeadsetHalConstants.CONNECTION_STATE_CONNECTING, mTestDevice));
    202         verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser(
    203                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    204         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    205                 BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED,
    206                 mIntentArgument.getValue());
    207         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    208                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class));
    209     }
    210 
    211     /**
    212      * Test state transition from Connecting to Disconnected state via StackEvent.DISCONNECTED
    213      * message
    214      */
    215     @Test
    216     public void testStateTransition_ConnectingToDisconnected_StackDisconnected() {
    217         int numBroadcastsSent = setUpConnectingState();
    218         // Indicate disconnecting to test state machine, which should do nothing
    219         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    220                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    221                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice));
    222         // Should do nothing new
    223         verify(mHeadsetService,
    224                 after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    225                 any(Intent.class), any(UserHandle.class), anyString());
    226         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    227                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class));
    228 
    229         // Indicate connection failed to test state machine
    230         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    231                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    232                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice));
    233 
    234         numBroadcastsSent++;
    235         verify(mHeadsetService,
    236                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    237                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    238         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    239                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING,
    240                 mIntentArgument.getValue());
    241         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    242                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class));
    243     }
    244 
    245     /**
    246      * Test state transition from Connecting to Disconnected state via CONNECT_TIMEOUT message
    247      */
    248     @Test
    249     public void testStateTransition_ConnectingToDisconnected_Timeout() {
    250         int numBroadcastsSent = setUpConnectingState();
    251         // Let the connection timeout
    252         numBroadcastsSent++;
    253         verify(mHeadsetService, timeout(CONNECT_TIMEOUT_TEST_WAIT_MILLIS).times(
    254                 numBroadcastsSent)).sendBroadcastAsUser(mIntentArgument.capture(),
    255                 eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    256         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    257                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING,
    258                 mIntentArgument.getValue());
    259         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    260                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class));
    261     }
    262 
    263     /**
    264      * Test state transition from Connecting to Connected state via StackEvent.SLC_CONNECTED message
    265      */
    266     @Test
    267     public void testStateTransition_ConnectingToConnected_StackSlcConnected() {
    268         int numBroadcastsSent = setUpConnectingState();
    269         // Indicate connecting to test state machine
    270         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    271                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    272                         HeadsetHalConstants.CONNECTION_STATE_CONNECTING, mTestDevice));
    273         // Should do nothing
    274         verify(mHeadsetService,
    275                 after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    276                 any(Intent.class), any(UserHandle.class), anyString());
    277         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    278                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class));
    279 
    280         // Indicate RFCOMM connection is successful to test state machine
    281         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    282                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    283                         HeadsetHalConstants.CONNECTION_STATE_CONNECTED, mTestDevice));
    284         // Should do nothing
    285         verify(mHeadsetService,
    286                 after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    287                 any(Intent.class), any(UserHandle.class), anyString());
    288         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    289                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class));
    290 
    291         // Indicate SLC connection is successful to test state machine
    292         numBroadcastsSent++;
    293         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    294                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    295                         HeadsetHalConstants.CONNECTION_STATE_SLC_CONNECTED, mTestDevice));
    296         verify(mHeadsetService,
    297                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    298                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    299         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    300                 BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING,
    301                 mIntentArgument.getValue());
    302         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    303                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class));
    304     }
    305 
    306     /**
    307      * Test state transition from Disconnecting to Disconnected state via StackEvent.DISCONNECTED
    308      * message
    309      */
    310     @Test
    311     public void testStateTransition_DisconnectingToDisconnected_StackDisconnected() {
    312         int numBroadcastsSent = setUpDisconnectingState();
    313         // Send StackEvent.DISCONNECTED message
    314         numBroadcastsSent++;
    315         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    316                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    317                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice));
    318         verify(mHeadsetService,
    319                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    320                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    321         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    322                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING,
    323                 mIntentArgument.getValue());
    324         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    325                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class));
    326     }
    327 
    328     /**
    329      * Test state transition from Disconnecting to Disconnected state via CONNECT_TIMEOUT
    330      * message
    331      */
    332     @Test
    333     public void testStateTransition_DisconnectingToDisconnected_Timeout() {
    334         int numBroadcastsSent = setUpDisconnectingState();
    335         // Let the connection timeout
    336         numBroadcastsSent++;
    337         verify(mHeadsetService, timeout(CONNECT_TIMEOUT_TEST_WAIT_MILLIS).times(
    338                 numBroadcastsSent)).sendBroadcastAsUser(mIntentArgument.capture(),
    339                 eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    340         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    341                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING,
    342                 mIntentArgument.getValue());
    343         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    344                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class));
    345     }
    346 
    347     /**
    348      * Test state transition from Disconnecting to Connected state via StackEvent.SLC_CONNECTED
    349      * message
    350      */
    351     @Test
    352     public void testStateTransition_DisconnectingToConnected_StackSlcCconnected() {
    353         int numBroadcastsSent = setUpDisconnectingState();
    354         // Send StackEvent.SLC_CONNECTED message
    355         numBroadcastsSent++;
    356         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    357                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    358                         HeadsetHalConstants.CONNECTION_STATE_SLC_CONNECTED, mTestDevice));
    359         verify(mHeadsetService,
    360                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    361                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    362         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    363                 BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTING,
    364                 mIntentArgument.getValue());
    365         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    366                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class));
    367     }
    368 
    369     /**
    370      * Test state transition from Connected to Disconnecting state via DISCONNECT message
    371      */
    372     @Test
    373     public void testStateTransition_ConnectedToDisconnecting_Disconnect() {
    374         int numBroadcastsSent = setUpConnectedState();
    375         // Send DISCONNECT message
    376         numBroadcastsSent++;
    377         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT, mTestDevice);
    378         verify(mHeadsetService,
    379                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    380                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    381         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    382                 BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED,
    383                 mIntentArgument.getValue());
    384         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    385                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class));
    386     }
    387 
    388     /**
    389      * Test state transition from Connected to Disconnecting state via StackEvent.DISCONNECTING
    390      * message
    391      */
    392     @Test
    393     public void testStateTransition_ConnectedToDisconnecting_StackDisconnecting() {
    394         int numBroadcastsSent = setUpConnectedState();
    395         // Send StackEvent.DISCONNECTING message
    396         numBroadcastsSent++;
    397         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    398                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    399                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice));
    400         verify(mHeadsetService,
    401                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    402                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    403         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    404                 BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED,
    405                 mIntentArgument.getValue());
    406         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    407                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class));
    408     }
    409 
    410     /**
    411      * Test state transition from Connected to Disconnected state via StackEvent.DISCONNECTED
    412      * message
    413      */
    414     @Test
    415     public void testStateTransition_ConnectedToDisconnected_StackDisconnected() {
    416         int numBroadcastsSent = setUpConnectedState();
    417         // Send StackEvent.DISCONNECTED message
    418         numBroadcastsSent++;
    419         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    420                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    421                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice));
    422         verify(mHeadsetService,
    423                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    424                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    425         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    426                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED,
    427                 mIntentArgument.getValue());
    428         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    429                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class));
    430     }
    431 
    432     /**
    433      * Test state transition from Connected to AudioConnecting state via CONNECT_AUDIO message
    434      */
    435     @Test
    436     public void testStateTransition_ConnectedToAudioConnecting_ConnectAudio() {
    437         int numBroadcastsSent = setUpConnectedState();
    438         // Send CONNECT_AUDIO message
    439         numBroadcastsSent++;
    440         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, mTestDevice);
    441         verify(mHeadsetService,
    442                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    443                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    444         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    445                 BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
    446                 mIntentArgument.getValue());
    447         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    448                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class));
    449     }
    450 
    451     /**
    452      * Test state transition from Connected to AudioConnecting state via
    453      * StackEvent.AUDIO_CONNECTING message
    454      */
    455     @Test
    456     public void testStateTransition_ConnectedToAudioConnecting_StackAudioConnecting() {
    457         int numBroadcastsSent = setUpConnectedState();
    458         // Send StackEvent.AUDIO_CONNECTING message
    459         numBroadcastsSent++;
    460         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    461                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED,
    462                         HeadsetHalConstants.AUDIO_STATE_CONNECTING, mTestDevice));
    463         verify(mHeadsetService,
    464                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    465                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    466         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    467                 BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
    468                 mIntentArgument.getValue());
    469         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    470                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class));
    471     }
    472 
    473     /**
    474      * Test state transition from Connected to AudioOn state via StackEvent.AUDIO_CONNECTED message
    475      */
    476     @Test
    477     public void testStateTransition_ConnectedToAudioOn_StackAudioConnected() {
    478         int numBroadcastsSent = setUpConnectedState();
    479         // Send StackEvent.AUDIO_CONNECTED message
    480         numBroadcastsSent++;
    481         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    482                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED,
    483                         HeadsetHalConstants.AUDIO_STATE_CONNECTED, mTestDevice));
    484         verify(mHeadsetService,
    485                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    486                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    487         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    488                 BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
    489                 mIntentArgument.getValue());
    490         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    491                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class));
    492     }
    493 
    494     /**
    495      * Test state transition from AudioConnecting to Connected state via CONNECT_TIMEOUT message
    496      */
    497     @Test
    498     public void testStateTransition_AudioConnectingToConnected_Timeout() {
    499         int numBroadcastsSent = setUpAudioConnectingState();
    500         // Wait for connection to timeout
    501         numBroadcastsSent++;
    502         verify(mHeadsetService, timeout(CONNECT_TIMEOUT_TEST_WAIT_MILLIS).times(
    503                 numBroadcastsSent)).sendBroadcastAsUser(mIntentArgument.capture(),
    504                 eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    505         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    506                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING,
    507                 mIntentArgument.getValue());
    508         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    509                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class));
    510     }
    511 
    512     /**
    513      * Test state transition from AudioConnecting to Connected state via
    514      * StackEvent.AUDIO_DISCONNECTED message
    515      */
    516     @Test
    517     public void testStateTransition_AudioConnectingToConnected_StackAudioDisconnected() {
    518         int numBroadcastsSent = setUpAudioConnectingState();
    519         // Send StackEvent.AUDIO_DISCONNECTED message
    520         numBroadcastsSent++;
    521         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    522                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED,
    523                         HeadsetHalConstants.AUDIO_STATE_DISCONNECTED, mTestDevice));
    524         verify(mHeadsetService,
    525                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    526                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    527         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    528                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING,
    529                 mIntentArgument.getValue());
    530         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    531                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class));
    532     }
    533 
    534     /**
    535      * Test state transition from AudioConnecting to Disconnected state via
    536      * StackEvent.DISCONNECTED message
    537      */
    538     @Test
    539     public void testStateTransition_AudioConnectingToDisconnected_StackDisconnected() {
    540         int numBroadcastsSent = setUpAudioConnectingState();
    541         // Send StackEvent.DISCONNECTED message
    542         numBroadcastsSent += 2;
    543         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    544                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    545                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice));
    546         verify(mHeadsetService,
    547                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    548                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    549         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    550                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING,
    551                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2));
    552         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    553                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED,
    554                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1));
    555         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    556                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class));
    557     }
    558 
    559     /**
    560      * Test state transition from AudioConnecting to Disconnecting state via
    561      * StackEvent.DISCONNECTING message
    562      */
    563     @Test
    564     public void testStateTransition_AudioConnectingToDisconnecting_StackDisconnecting() {
    565         int numBroadcastsSent = setUpAudioConnectingState();
    566         // Send StackEvent.DISCONNECTED message
    567         numBroadcastsSent += 2;
    568         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    569                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    570                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice));
    571         verify(mHeadsetService,
    572                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    573                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    574         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    575                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING,
    576                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2));
    577         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    578                 BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED,
    579                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1));
    580         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    581                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class));
    582     }
    583 
    584     /**
    585      * Test state transition from AudioConnecting to AudioOn state via
    586      * StackEvent.AUDIO_CONNECTED message
    587      */
    588     @Test
    589     public void testStateTransition_AudioConnectingToAudioOn_StackAudioConnected() {
    590         int numBroadcastsSent = setUpAudioConnectingState();
    591         // Send StackEvent.AUDIO_DISCONNECTED message
    592         numBroadcastsSent++;
    593         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    594                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED,
    595                         HeadsetHalConstants.AUDIO_STATE_CONNECTED, mTestDevice));
    596         verify(mHeadsetService,
    597                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    598                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    599         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    600                 BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING,
    601                 mIntentArgument.getValue());
    602         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    603                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class));
    604     }
    605 
    606     /**
    607      * Test state transition from AudioOn to AudioDisconnecting state via
    608      * StackEvent.AUDIO_DISCONNECTING message
    609      */
    610     @Test
    611     public void testStateTransition_AudioOnToAudioDisconnecting_StackAudioDisconnecting() {
    612         int numBroadcastsSent = setUpAudioOnState();
    613         // Send StackEvent.AUDIO_DISCONNECTING message
    614         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    615                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED,
    616                         HeadsetHalConstants.AUDIO_STATE_DISCONNECTING, mTestDevice));
    617         verify(mHeadsetService,
    618                 after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    619                 any(Intent.class), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    620         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    621                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class));
    622     }
    623 
    624     /**
    625      * Test state transition from AudioOn to AudioDisconnecting state via
    626      * DISCONNECT_AUDIO message
    627      */
    628     @Test
    629     public void testStateTransition_AudioOnToAudioDisconnecting_DisconnectAudio() {
    630         int numBroadcastsSent = setUpAudioOnState();
    631         // Send DISCONNECT_AUDIO message
    632         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, mTestDevice);
    633         // Should not sent any broadcast due to lack of AUDIO_DISCONNECTING intent value
    634         verify(mHeadsetService,
    635                 after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    636                 any(Intent.class), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    637         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    638                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class));
    639     }
    640 
    641     /**
    642      * Test state transition from AudioOn to AudioDisconnecting state via
    643      * Stack.AUDIO_DISCONNECTED message
    644      */
    645     @Test
    646     public void testStateTransition_AudioOnToConnected_StackAudioDisconnected() {
    647         int numBroadcastsSent = setUpAudioOnState();
    648         // Send DISCONNECT_AUDIO message
    649         numBroadcastsSent++;
    650         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    651                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED,
    652                         HeadsetHalConstants.AUDIO_STATE_DISCONNECTED, mTestDevice));
    653         verify(mHeadsetService,
    654                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    655                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    656         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    657                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED,
    658                 mIntentArgument.getValue());
    659         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    660                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class));
    661     }
    662 
    663     /**
    664      * Test state transition from AudioOn to Disconnected state via
    665      * Stack.DISCONNECTED message
    666      */
    667     @Test
    668     public void testStateTransition_AudioOnToDisconnected_StackDisconnected() {
    669         int numBroadcastsSent = setUpAudioOnState();
    670         // Send StackEvent.DISCONNECTED message
    671         numBroadcastsSent += 2;
    672         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    673                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    674                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice));
    675         verify(mHeadsetService,
    676                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    677                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    678         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    679                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED,
    680                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2));
    681         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    682                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED,
    683                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1));
    684         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    685                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class));
    686     }
    687 
    688     /**
    689      * Test state transition from AudioOn to Disconnecting state via
    690      * Stack.DISCONNECTING message
    691      */
    692     @Test
    693     public void testStateTransition_AudioOnToDisconnecting_StackDisconnecting() {
    694         int numBroadcastsSent = setUpAudioOnState();
    695         // Send StackEvent.DISCONNECTING message
    696         numBroadcastsSent += 2;
    697         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    698                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    699                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice));
    700         verify(mHeadsetService,
    701                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    702                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    703         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    704                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED,
    705                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2));
    706         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    707                 BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED,
    708                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1));
    709         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    710                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class));
    711     }
    712 
    713     /**
    714      * Test state transition from AudioDisconnecting to Connected state via
    715      * CONNECT_TIMEOUT message
    716      */
    717     @Test
    718     public void testStateTransition_AudioDisconnectingToConnected_Timeout() {
    719         int numBroadcastsSent = setUpAudioDisconnectingState();
    720         // Wait for connection to timeout
    721         numBroadcastsSent++;
    722         verify(mHeadsetService, timeout(CONNECT_TIMEOUT_TEST_WAIT_MILLIS).times(
    723                 numBroadcastsSent)).sendBroadcastAsUser(mIntentArgument.capture(),
    724                 eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    725         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    726                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED,
    727                 mIntentArgument.getValue());
    728         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    729                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class));
    730     }
    731 
    732     /**
    733      * Test state transition from AudioDisconnecting to Connected state via
    734      * Stack.AUDIO_DISCONNECTED message
    735      */
    736     @Test
    737     public void testStateTransition_AudioDisconnectingToConnected_StackAudioDisconnected() {
    738         int numBroadcastsSent = setUpAudioDisconnectingState();
    739         // Send Stack.AUDIO_DISCONNECTED message
    740         numBroadcastsSent++;
    741         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    742                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED,
    743                         HeadsetHalConstants.AUDIO_STATE_DISCONNECTED, mTestDevice));
    744         verify(mHeadsetService,
    745                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    746                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    747         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    748                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED,
    749                 mIntentArgument.getValue());
    750         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    751                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class));
    752     }
    753 
    754     /**
    755      * Test state transition from AudioDisconnecting to AudioOn state via
    756      * Stack.AUDIO_CONNECTED message
    757      */
    758     @Test
    759     public void testStateTransition_AudioDisconnectingToAudioOn_StackAudioConnected() {
    760         int numBroadcastsSent = setUpAudioDisconnectingState();
    761         // Send Stack.AUDIO_CONNECTED message
    762         numBroadcastsSent++;
    763         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    764                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED,
    765                         HeadsetHalConstants.AUDIO_STATE_CONNECTED, mTestDevice));
    766         verify(mHeadsetService,
    767                 after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    768                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    769         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    770                 BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED,
    771                 mIntentArgument.getValue());
    772         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    773                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class));
    774     }
    775 
    776     /**
    777      * Test state transition from AudioDisconnecting to Disconnecting state via
    778      * Stack.DISCONNECTING message
    779      */
    780     @Test
    781     public void testStateTransition_AudioDisconnectingToDisconnecting_StackDisconnecting() {
    782         int numBroadcastsSent = setUpAudioDisconnectingState();
    783         // Send StackEvent.DISCONNECTING message
    784         numBroadcastsSent += 2;
    785         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    786                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    787                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice));
    788         verify(mHeadsetService,
    789                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    790                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    791         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    792                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED,
    793                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2));
    794         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    795                 BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED,
    796                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1));
    797         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    798                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class));
    799     }
    800 
    801     /**
    802      * Test state transition from AudioDisconnecting to Disconnecting state via
    803      * Stack.DISCONNECTED message
    804      */
    805     @Test
    806     public void testStateTransition_AudioDisconnectingToDisconnected_StackDisconnected() {
    807         int numBroadcastsSent = setUpAudioDisconnectingState();
    808         // Send StackEvent.DISCONNECTED message
    809         numBroadcastsSent += 2;
    810         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    811                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    812                         HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice));
    813         verify(mHeadsetService,
    814                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    815                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    816         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    817                 BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED,
    818                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2));
    819         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    820                 BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED,
    821                 mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1));
    822         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    823                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class));
    824     }
    825 
    826     /**
    827      * A test to verify that we correctly subscribe to phone state updates for service and signal
    828      * strength information and further updates via AT+BIA command results in update
    829      */
    830     @Test
    831     public void testAtBiaEvent_initialSubscriptionWithUpdates() {
    832         setUpConnectedState();
    833         verify(mPhoneState).listenForPhoneState(mTestDevice, PhoneStateListener.LISTEN_SERVICE_STATE
    834                 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
    835         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    836                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIA,
    837                         new HeadsetAgIndicatorEnableState(true, true, false, false), mTestDevice));
    838         verify(mPhoneState, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).listenForPhoneState(mTestDevice,
    839                 PhoneStateListener.LISTEN_SERVICE_STATE);
    840         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    841                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIA,
    842                         new HeadsetAgIndicatorEnableState(false, true, true, false), mTestDevice));
    843         verify(mPhoneState, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).listenForPhoneState(mTestDevice,
    844                 PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
    845         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    846                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIA,
    847                         new HeadsetAgIndicatorEnableState(false, true, false, false), mTestDevice));
    848         verify(mPhoneState, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).listenForPhoneState(mTestDevice,
    849                 PhoneStateListener.LISTEN_NONE);
    850     }
    851 
    852     /**
    853      * A test to verify that we correctly handles key pressed event from a HSP headset
    854      */
    855     @Test
    856     public void testKeyPressedEventWhenIdleAndAudioOff_dialCall() {
    857         setUpConnectedState();
    858         Cursor cursor = mock(Cursor.class);
    859         when(cursor.getCount()).thenReturn(1);
    860         when(cursor.moveToNext()).thenReturn(true);
    861         int magicNumber = 42;
    862         when(cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER)).thenReturn(magicNumber);
    863         when(cursor.getString(magicNumber)).thenReturn(TEST_PHONE_NUMBER);
    864         MockContentProvider mockContentProvider = new MockContentProvider() {
    865             @Override
    866             public Cursor query(Uri uri, String[] projection, String selection,
    867                     String[] selectionArgs, String sortOrder) {
    868                 if (uri == null || !uri.equals(CallLog.Calls.CONTENT_URI)) {
    869                     return null;
    870                 }
    871                 if (projection == null || (projection.length == 0) || !projection[0].equals(
    872                         CallLog.Calls.NUMBER)) {
    873                     return null;
    874                 }
    875                 if (selection == null || !selection.equals(
    876                         CallLog.Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE)) {
    877                     return null;
    878                 }
    879                 if (selectionArgs != null) {
    880                     return null;
    881                 }
    882                 if (sortOrder == null || !sortOrder.equals(
    883                         CallLog.Calls.DEFAULT_SORT_ORDER + " LIMIT 1")) {
    884                     return null;
    885                 }
    886                 return cursor;
    887             }
    888         };
    889         mMockContentResolver.addProvider(CallLog.AUTHORITY, mockContentProvider);
    890         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    891                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice));
    892         verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).dialOutgoingCall(mTestDevice,
    893                 TEST_PHONE_NUMBER);
    894     }
    895 
    896     /**
    897      * A test to verify that we correctly handles key pressed event from a HSP headset
    898      */
    899     @Test
    900     public void testKeyPressedEventDuringRinging_answerCall() {
    901         setUpConnectedState();
    902         when(mSystemInterface.isRinging()).thenReturn(true);
    903         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    904                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice));
    905         verify(mSystemInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).answerCall(mTestDevice);
    906     }
    907 
    908     /**
    909      * A test to verify that we correctly handles key pressed event from a HSP headset
    910      */
    911     @Test
    912     public void testKeyPressedEventInCallButAudioOff_setActiveDevice() {
    913         setUpConnectedState();
    914         when(mSystemInterface.isInCall()).thenReturn(true);
    915         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    916                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice));
    917         verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setActiveDevice(mTestDevice);
    918     }
    919 
    920     /**
    921      * A test to verify that we correctly handles key pressed event from a HSP headset
    922      */
    923     @Test
    924     public void testKeyPressedEventInCallAndAudioOn_hangupCall() {
    925         setUpAudioOnState();
    926         when(mSystemInterface.isInCall()).thenReturn(true);
    927         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    928                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice));
    929         verify(mSystemInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).hangupCall(mTestDevice);
    930     }
    931 
    932     /**
    933      * A test to verify that we correctly handles key pressed event from a HSP headset
    934      */
    935     @Test
    936     public void testKeyPressedEventWhenIdleAndAudioOn_disconnectAudio() {
    937         setUpAudioOnState();
    938         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    939                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice));
    940         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).disconnectAudio(mTestDevice);
    941     }
    942 
    943     /**
    944      * Setup Connecting State
    945      * @return number of times mHeadsetService.sendBroadcastAsUser() has been invoked
    946      */
    947     private int setUpConnectingState() {
    948         // Put test state machine in connecting state
    949         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.CONNECT, mTestDevice);
    950         verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser(
    951                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    952         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    953                 BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED,
    954                 mIntentArgument.getValue());
    955         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    956                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class));
    957         return 1;
    958     }
    959 
    960     /**
    961      * Setup Connected State
    962      * @return number of times mHeadsetService.sendBroadcastAsUser() has been invoked
    963      */
    964     private int setUpConnectedState() {
    965         // Put test state machine into connected state
    966         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    967                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    968                         HeadsetHalConstants.CONNECTION_STATE_CONNECTED, mTestDevice));
    969         verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser(
    970                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    971         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    972                 BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED,
    973                 mIntentArgument.getValue());
    974         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    975                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class));
    976         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
    977                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED,
    978                         HeadsetHalConstants.CONNECTION_STATE_SLC_CONNECTED, mTestDevice));
    979         verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)).sendBroadcastAsUser(
    980                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    981         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
    982                 BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING,
    983                 mIntentArgument.getValue());
    984         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
    985                 IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class));
    986         return 2;
    987     }
    988 
    989     private int setUpAudioConnectingState() {
    990         int numBroadcastsSent = setUpConnectedState();
    991         // Send CONNECT_AUDIO
    992         numBroadcastsSent++;
    993         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, mTestDevice);
    994         verify(mHeadsetService,
    995                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
    996                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
    997         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
    998                 BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
    999                 mIntentArgument.getValue());
   1000         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
   1001                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class));
   1002         return numBroadcastsSent;
   1003     }
   1004 
   1005     private int setUpAudioOnState() {
   1006         int numBroadcastsSent = setUpAudioConnectingState();
   1007         // Send StackEvent.AUDIO_DISCONNECTED message
   1008         numBroadcastsSent++;
   1009         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
   1010                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED,
   1011                         HeadsetHalConstants.AUDIO_STATE_CONNECTED, mTestDevice));
   1012         verify(mHeadsetService,
   1013                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
   1014                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
   1015         HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice,
   1016                 BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING,
   1017                 mIntentArgument.getValue());
   1018         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
   1019                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class));
   1020         return numBroadcastsSent;
   1021     }
   1022 
   1023     private int setUpAudioDisconnectingState() {
   1024         int numBroadcastsSent = setUpAudioOnState();
   1025         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, mTestDevice);
   1026         // No new broadcast due to lack of AUDIO_DISCONNECTING intent variable
   1027         verify(mHeadsetService,
   1028                 after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
   1029                 any(Intent.class), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
   1030         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
   1031                 IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class));
   1032         return numBroadcastsSent;
   1033     }
   1034 
   1035     private int setUpDisconnectingState() {
   1036         int numBroadcastsSent = setUpConnectedState();
   1037         // Send DISCONNECT message
   1038         numBroadcastsSent++;
   1039         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT, mTestDevice);
   1040         verify(mHeadsetService,
   1041                 timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser(
   1042                 mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM));
   1043         HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice,
   1044                 BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED,
   1045                 mIntentArgument.getValue());
   1046         Assert.assertThat(mHeadsetStateMachine.getCurrentState(),
   1047                 IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class));
   1048         return numBroadcastsSent;
   1049     }
   1050 }
   1051