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