/* * Copyright 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.hfp; import static org.mockito.Mockito.*; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.database.Cursor; import android.media.AudioManager; import android.net.Uri; import android.os.HandlerThread; import android.os.UserHandle; import android.provider.CallLog; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import android.support.test.runner.AndroidJUnit4; import android.telephony.PhoneStateListener; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; /** * Tests for {@link HeadsetStateMachine} */ @MediumTest @RunWith(AndroidJUnit4.class) public class HeadsetStateMachineTest { private static final int CONNECT_TIMEOUT_TEST_MILLIS = 1000; private static final int CONNECT_TIMEOUT_TEST_WAIT_MILLIS = CONNECT_TIMEOUT_TEST_MILLIS * 3 / 2; private static final int ASYNC_CALL_TIMEOUT_MILLIS = 250; private static final String TEST_PHONE_NUMBER = "1234567890"; private Context mTargetContext; private BluetoothAdapter mAdapter; private HandlerThread mHandlerThread; private HeadsetStateMachine mHeadsetStateMachine; private BluetoothDevice mTestDevice; private ArgumentCaptor mIntentArgument = ArgumentCaptor.forClass(Intent.class); @Mock private AdapterService mAdapterService; @Mock private HeadsetService mHeadsetService; @Mock private HeadsetSystemInterface mSystemInterface; @Mock private AudioManager mAudioManager; @Mock private HeadsetPhoneState mPhoneState; private MockContentResolver mMockContentResolver; private HeadsetNativeInterface mNativeInterface; @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); Assume.assumeTrue("Ignore test when HeadsetService is not enabled", mTargetContext.getResources().getBoolean(R.bool.profile_supported_hs_hfp)); // Setup mocks and test assets MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); // Stub system interface when(mSystemInterface.getHeadsetPhoneState()).thenReturn(mPhoneState); when(mSystemInterface.getAudioManager()).thenReturn(mAudioManager); // This line must be called to make sure relevant objects are initialized properly mAdapter = BluetoothAdapter.getDefaultAdapter(); // Get a device for testing mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); // Spy on native interface mNativeInterface = spy(HeadsetNativeInterface.getInstance()); doNothing().when(mNativeInterface).init(anyInt(), anyBoolean()); doReturn(true).when(mNativeInterface).connectHfp(mTestDevice); doReturn(true).when(mNativeInterface).disconnectHfp(mTestDevice); doReturn(true).when(mNativeInterface).connectAudio(mTestDevice); doReturn(true).when(mNativeInterface).disconnectAudio(mTestDevice); // Stub headset service mMockContentResolver = new MockContentResolver(); when(mHeadsetService.getContentResolver()).thenReturn(mMockContentResolver); doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService) .getBondState(any(BluetoothDevice.class)); when(mHeadsetService.bindService(any(Intent.class), any(ServiceConnection.class), anyInt())) .thenReturn(true); when(mHeadsetService.getResources()).thenReturn( InstrumentationRegistry.getTargetContext().getResources()); when(mHeadsetService.getPackageManager()).thenReturn( InstrumentationRegistry.getContext().getPackageManager()); when(mHeadsetService.getPriority(any(BluetoothDevice.class))).thenReturn( BluetoothProfile.PRIORITY_ON); when(mHeadsetService.getForceScoAudio()).thenReturn(true); when(mHeadsetService.okToAcceptConnection(any(BluetoothDevice.class))).thenReturn(true); when(mHeadsetService.isScoAcceptable(any(BluetoothDevice.class))).thenReturn(true); // Setup thread and looper mHandlerThread = new HandlerThread("HeadsetStateMachineTestHandlerThread"); mHandlerThread.start(); // Modify CONNECT timeout to a smaller value for test only HeadsetStateMachine.sConnectTimeoutMs = CONNECT_TIMEOUT_TEST_MILLIS; mHeadsetStateMachine = HeadsetObjectsFactory.getInstance() .makeStateMachine(mTestDevice, mHandlerThread.getLooper(), mHeadsetService, mAdapterService, mNativeInterface, mSystemInterface); } @After public void tearDown() throws Exception { if (!mTargetContext.getResources().getBoolean(R.bool.profile_supported_hs_hfp)) { return; } HeadsetObjectsFactory.getInstance().destroyStateMachine(mHeadsetStateMachine); mHandlerThread.quit(); TestUtils.clearAdapterService(mAdapterService); } /** * Test that default state is Disconnected */ @Test public void testDefaultDisconnectedState() { Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, mHeadsetStateMachine.getConnectionState()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); } /** * Test that state is Connected after calling setUpConnectedState() */ @Test public void testSetupConnectedState() { setUpConnectedState(); Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mHeadsetStateMachine.getConnectionState()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); } /** * Test state transition from Disconnected to Connecting state via CONNECT message */ @Test public void testStateTransition_DisconnectedToConnecting_Connect() { mHeadsetStateMachine.sendMessage(HeadsetStateMachine.CONNECT, mTestDevice); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); } /** * Test state transition from Disconnected to Connecting state via StackEvent.CONNECTED message */ @Test public void testStateTransition_DisconnectedToConnecting_StackConnected() { mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_CONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); } /** * Test state transition from Disconnected to Connecting state via StackEvent.CONNECTING message */ @Test public void testStateTransition_DisconnectedToConnecting_StackConnecting() { mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_CONNECTING, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); } /** * Test state transition from Connecting to Disconnected state via StackEvent.DISCONNECTED * message */ @Test public void testStateTransition_ConnectingToDisconnected_StackDisconnected() { int numBroadcastsSent = setUpConnectingState(); // Indicate disconnecting to test state machine, which should do nothing mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice)); // Should do nothing new verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( any(Intent.class), any(UserHandle.class), anyString()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); // Indicate connection failed to test state machine mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice)); numBroadcastsSent++; verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); } /** * Test state transition from Connecting to Disconnected state via CONNECT_TIMEOUT message */ @Test public void testStateTransition_ConnectingToDisconnected_Timeout() { int numBroadcastsSent = setUpConnectingState(); // Let the connection timeout numBroadcastsSent++; verify(mHeadsetService, timeout(CONNECT_TIMEOUT_TEST_WAIT_MILLIS).times( numBroadcastsSent)).sendBroadcastAsUser(mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); } /** * Test state transition from Connecting to Connected state via StackEvent.SLC_CONNECTED message */ @Test public void testStateTransition_ConnectingToConnected_StackSlcConnected() { int numBroadcastsSent = setUpConnectingState(); // Indicate connecting to test state machine mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_CONNECTING, mTestDevice)); // Should do nothing verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( any(Intent.class), any(UserHandle.class), anyString()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); // Indicate RFCOMM connection is successful to test state machine mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_CONNECTED, mTestDevice)); // Should do nothing verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( any(Intent.class), any(UserHandle.class), anyString()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); // Indicate SLC connection is successful to test state machine numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_SLC_CONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); } /** * Test state transition from Disconnecting to Disconnected state via StackEvent.DISCONNECTED * message */ @Test public void testStateTransition_DisconnectingToDisconnected_StackDisconnected() { int numBroadcastsSent = setUpDisconnectingState(); // Send StackEvent.DISCONNECTED message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); } /** * Test state transition from Disconnecting to Disconnected state via CONNECT_TIMEOUT * message */ @Test public void testStateTransition_DisconnectingToDisconnected_Timeout() { int numBroadcastsSent = setUpDisconnectingState(); // Let the connection timeout numBroadcastsSent++; verify(mHeadsetService, timeout(CONNECT_TIMEOUT_TEST_WAIT_MILLIS).times( numBroadcastsSent)).sendBroadcastAsUser(mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); } /** * Test state transition from Disconnecting to Connected state via StackEvent.SLC_CONNECTED * message */ @Test public void testStateTransition_DisconnectingToConnected_StackSlcCconnected() { int numBroadcastsSent = setUpDisconnectingState(); // Send StackEvent.SLC_CONNECTED message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_SLC_CONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); } /** * Test state transition from Connected to Disconnecting state via DISCONNECT message */ @Test public void testStateTransition_ConnectedToDisconnecting_Disconnect() { int numBroadcastsSent = setUpConnectedState(); // Send DISCONNECT message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT, mTestDevice); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); } /** * Test state transition from Connected to Disconnecting state via StackEvent.DISCONNECTING * message */ @Test public void testStateTransition_ConnectedToDisconnecting_StackDisconnecting() { int numBroadcastsSent = setUpConnectedState(); // Send StackEvent.DISCONNECTING message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); } /** * Test state transition from Connected to Disconnected state via StackEvent.DISCONNECTED * message */ @Test public void testStateTransition_ConnectedToDisconnected_StackDisconnected() { int numBroadcastsSent = setUpConnectedState(); // Send StackEvent.DISCONNECTED message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); } /** * Test state transition from Connected to AudioConnecting state via CONNECT_AUDIO message */ @Test public void testStateTransition_ConnectedToAudioConnecting_ConnectAudio() { int numBroadcastsSent = setUpConnectedState(); // Send CONNECT_AUDIO message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, mTestDevice); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class)); } /** * Test state transition from Connected to AudioConnecting state via * StackEvent.AUDIO_CONNECTING message */ @Test public void testStateTransition_ConnectedToAudioConnecting_StackAudioConnecting() { int numBroadcastsSent = setUpConnectedState(); // Send StackEvent.AUDIO_CONNECTING message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED, HeadsetHalConstants.AUDIO_STATE_CONNECTING, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class)); } /** * Test state transition from Connected to AudioOn state via StackEvent.AUDIO_CONNECTED message */ @Test public void testStateTransition_ConnectedToAudioOn_StackAudioConnected() { int numBroadcastsSent = setUpConnectedState(); // Send StackEvent.AUDIO_CONNECTED message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED, HeadsetHalConstants.AUDIO_STATE_CONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); } /** * Test state transition from AudioConnecting to Connected state via CONNECT_TIMEOUT message */ @Test public void testStateTransition_AudioConnectingToConnected_Timeout() { int numBroadcastsSent = setUpAudioConnectingState(); // Wait for connection to timeout numBroadcastsSent++; verify(mHeadsetService, timeout(CONNECT_TIMEOUT_TEST_WAIT_MILLIS).times( numBroadcastsSent)).sendBroadcastAsUser(mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); } /** * Test state transition from AudioConnecting to Connected state via * StackEvent.AUDIO_DISCONNECTED message */ @Test public void testStateTransition_AudioConnectingToConnected_StackAudioDisconnected() { int numBroadcastsSent = setUpAudioConnectingState(); // Send StackEvent.AUDIO_DISCONNECTED message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED, HeadsetHalConstants.AUDIO_STATE_DISCONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); } /** * Test state transition from AudioConnecting to Disconnected state via * StackEvent.DISCONNECTED message */ @Test public void testStateTransition_AudioConnectingToDisconnected_StackDisconnected() { int numBroadcastsSent = setUpAudioConnectingState(); // Send StackEvent.DISCONNECTED message numBroadcastsSent += 2; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); } /** * Test state transition from AudioConnecting to Disconnecting state via * StackEvent.DISCONNECTING message */ @Test public void testStateTransition_AudioConnectingToDisconnecting_StackDisconnecting() { int numBroadcastsSent = setUpAudioConnectingState(); // Send StackEvent.DISCONNECTED message numBroadcastsSent += 2; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); } /** * Test state transition from AudioConnecting to AudioOn state via * StackEvent.AUDIO_CONNECTED message */ @Test public void testStateTransition_AudioConnectingToAudioOn_StackAudioConnected() { int numBroadcastsSent = setUpAudioConnectingState(); // Send StackEvent.AUDIO_DISCONNECTED message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED, HeadsetHalConstants.AUDIO_STATE_CONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); } /** * Test state transition from AudioOn to AudioDisconnecting state via * StackEvent.AUDIO_DISCONNECTING message */ @Test public void testStateTransition_AudioOnToAudioDisconnecting_StackAudioDisconnecting() { int numBroadcastsSent = setUpAudioOnState(); // Send StackEvent.AUDIO_DISCONNECTING message mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED, HeadsetHalConstants.AUDIO_STATE_DISCONNECTING, mTestDevice)); verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( any(Intent.class), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class)); } /** * Test state transition from AudioOn to AudioDisconnecting state via * DISCONNECT_AUDIO message */ @Test public void testStateTransition_AudioOnToAudioDisconnecting_DisconnectAudio() { int numBroadcastsSent = setUpAudioOnState(); // Send DISCONNECT_AUDIO message mHeadsetStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, mTestDevice); // Should not sent any broadcast due to lack of AUDIO_DISCONNECTING intent value verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( any(Intent.class), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class)); } /** * Test state transition from AudioOn to AudioDisconnecting state via * Stack.AUDIO_DISCONNECTED message */ @Test public void testStateTransition_AudioOnToConnected_StackAudioDisconnected() { int numBroadcastsSent = setUpAudioOnState(); // Send DISCONNECT_AUDIO message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED, HeadsetHalConstants.AUDIO_STATE_DISCONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); } /** * Test state transition from AudioOn to Disconnected state via * Stack.DISCONNECTED message */ @Test public void testStateTransition_AudioOnToDisconnected_StackDisconnected() { int numBroadcastsSent = setUpAudioOnState(); // Send StackEvent.DISCONNECTED message numBroadcastsSent += 2; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); } /** * Test state transition from AudioOn to Disconnecting state via * Stack.DISCONNECTING message */ @Test public void testStateTransition_AudioOnToDisconnecting_StackDisconnecting() { int numBroadcastsSent = setUpAudioOnState(); // Send StackEvent.DISCONNECTING message numBroadcastsSent += 2; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); } /** * Test state transition from AudioDisconnecting to Connected state via * CONNECT_TIMEOUT message */ @Test public void testStateTransition_AudioDisconnectingToConnected_Timeout() { int numBroadcastsSent = setUpAudioDisconnectingState(); // Wait for connection to timeout numBroadcastsSent++; verify(mHeadsetService, timeout(CONNECT_TIMEOUT_TEST_WAIT_MILLIS).times( numBroadcastsSent)).sendBroadcastAsUser(mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); } /** * Test state transition from AudioDisconnecting to Connected state via * Stack.AUDIO_DISCONNECTED message */ @Test public void testStateTransition_AudioDisconnectingToConnected_StackAudioDisconnected() { int numBroadcastsSent = setUpAudioDisconnectingState(); // Send Stack.AUDIO_DISCONNECTED message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED, HeadsetHalConstants.AUDIO_STATE_DISCONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); } /** * Test state transition from AudioDisconnecting to AudioOn state via * Stack.AUDIO_CONNECTED message */ @Test public void testStateTransition_AudioDisconnectingToAudioOn_StackAudioConnected() { int numBroadcastsSent = setUpAudioDisconnectingState(); // Send Stack.AUDIO_CONNECTED message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED, HeadsetHalConstants.AUDIO_STATE_CONNECTED, mTestDevice)); verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); } /** * Test state transition from AudioDisconnecting to Disconnecting state via * Stack.DISCONNECTING message */ @Test public void testStateTransition_AudioDisconnectingToDisconnecting_StackDisconnecting() { int numBroadcastsSent = setUpAudioDisconnectingState(); // Send StackEvent.DISCONNECTING message numBroadcastsSent += 2; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); } /** * Test state transition from AudioDisconnecting to Disconnecting state via * Stack.DISCONNECTED message */ @Test public void testStateTransition_AudioDisconnectingToDisconnected_StackDisconnected() { int numBroadcastsSent = setUpAudioDisconnectingState(); // Send StackEvent.DISCONNECTED message numBroadcastsSent += 2; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_DISCONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); } /** * A test to verify that we correctly subscribe to phone state updates for service and signal * strength information and further updates via AT+BIA command results in update */ @Test public void testAtBiaEvent_initialSubscriptionWithUpdates() { setUpConnectedState(); verify(mPhoneState).listenForPhoneState(mTestDevice, PhoneStateListener.LISTEN_SERVICE_STATE | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIA, new HeadsetAgIndicatorEnableState(true, true, false, false), mTestDevice)); verify(mPhoneState, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).listenForPhoneState(mTestDevice, PhoneStateListener.LISTEN_SERVICE_STATE); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIA, new HeadsetAgIndicatorEnableState(false, true, true, false), mTestDevice)); verify(mPhoneState, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).listenForPhoneState(mTestDevice, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIA, new HeadsetAgIndicatorEnableState(false, true, false, false), mTestDevice)); verify(mPhoneState, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).listenForPhoneState(mTestDevice, PhoneStateListener.LISTEN_NONE); } /** * A test to verify that we correctly handles key pressed event from a HSP headset */ @Test public void testKeyPressedEventWhenIdleAndAudioOff_dialCall() { setUpConnectedState(); Cursor cursor = mock(Cursor.class); when(cursor.getCount()).thenReturn(1); when(cursor.moveToNext()).thenReturn(true); int magicNumber = 42; when(cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER)).thenReturn(magicNumber); when(cursor.getString(magicNumber)).thenReturn(TEST_PHONE_NUMBER); MockContentProvider mockContentProvider = new MockContentProvider() { @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { if (uri == null || !uri.equals(CallLog.Calls.CONTENT_URI)) { return null; } if (projection == null || (projection.length == 0) || !projection[0].equals( CallLog.Calls.NUMBER)) { return null; } if (selection == null || !selection.equals( CallLog.Calls.TYPE + "=" + CallLog.Calls.OUTGOING_TYPE)) { return null; } if (selectionArgs != null) { return null; } if (sortOrder == null || !sortOrder.equals( CallLog.Calls.DEFAULT_SORT_ORDER + " LIMIT 1")) { return null; } return cursor; } }; mMockContentResolver.addProvider(CallLog.AUTHORITY, mockContentProvider); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).dialOutgoingCall(mTestDevice, TEST_PHONE_NUMBER); } /** * A test to verify that we correctly handles key pressed event from a HSP headset */ @Test public void testKeyPressedEventDuringRinging_answerCall() { setUpConnectedState(); when(mSystemInterface.isRinging()).thenReturn(true); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice)); verify(mSystemInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).answerCall(mTestDevice); } /** * A test to verify that we correctly handles key pressed event from a HSP headset */ @Test public void testKeyPressedEventInCallButAudioOff_setActiveDevice() { setUpConnectedState(); when(mSystemInterface.isInCall()).thenReturn(true); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setActiveDevice(mTestDevice); } /** * A test to verify that we correctly handles key pressed event from a HSP headset */ @Test public void testKeyPressedEventInCallAndAudioOn_hangupCall() { setUpAudioOnState(); when(mSystemInterface.isInCall()).thenReturn(true); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice)); verify(mSystemInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).hangupCall(mTestDevice); } /** * A test to verify that we correctly handles key pressed event from a HSP headset */ @Test public void testKeyPressedEventWhenIdleAndAudioOn_disconnectAudio() { setUpAudioOnState(); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_KEY_PRESSED, mTestDevice)); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).disconnectAudio(mTestDevice); } /** * Setup Connecting State * @return number of times mHeadsetService.sendBroadcastAsUser() has been invoked */ private int setUpConnectingState() { // Put test state machine in connecting state mHeadsetStateMachine.sendMessage(HeadsetStateMachine.CONNECT, mTestDevice); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); return 1; } /** * Setup Connected State * @return number of times mHeadsetService.sendBroadcastAsUser() has been invoked */ private int setUpConnectedState() { // Put test state machine into connected state mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_CONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED, HeadsetHalConstants.CONNECTION_STATE_SLC_CONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); return 2; } private int setUpAudioConnectingState() { int numBroadcastsSent = setUpConnectedState(); // Send CONNECT_AUDIO numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, mTestDevice); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class)); return numBroadcastsSent; } private int setUpAudioOnState() { int numBroadcastsSent = setUpAudioConnectingState(); // Send StackEvent.AUDIO_DISCONNECTED message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED, HeadsetHalConstants.AUDIO_STATE_CONNECTED, mTestDevice)); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); return numBroadcastsSent; } private int setUpAudioDisconnectingState() { int numBroadcastsSent = setUpAudioOnState(); mHeadsetStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, mTestDevice); // No new broadcast due to lack of AUDIO_DISCONNECTING intent variable verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( any(Intent.class), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class)); return numBroadcastsSent; } private int setUpDisconnectingState() { int numBroadcastsSent = setUpConnectedState(); // Send DISCONNECT message numBroadcastsSent++; mHeadsetStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT, mTestDevice); verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)).sendBroadcastAsUser( mIntentArgument.capture(), eq(UserHandle.ALL), eq(HeadsetService.BLUETOOTH_PERM)); HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getValue()); Assert.assertThat(mHeadsetStateMachine.getCurrentState(), IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); return numBroadcastsSent; } }