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