| /* |
| * 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 android.Manifest.permission.BLUETOOTH_CONNECT; |
| |
| import static org.mockito.Mockito.*; |
| |
| import android.bluetooth.BluetoothAdapter; |
| import android.bluetooth.BluetoothDevice; |
| import android.bluetooth.BluetoothHeadset; |
| import android.bluetooth.BluetoothProfile; |
| import android.bluetooth.BluetoothStatusCodes; |
| import android.content.ContentResolver; |
| 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.Bundle; |
| import android.os.CancellationSignal; |
| import android.os.HandlerThread; |
| import android.os.UserHandle; |
| import android.provider.CallLog; |
| import android.provider.CallLog.Calls; |
| import android.telephony.PhoneNumberUtils; |
| import android.telephony.PhoneStateListener; |
| import android.telephony.ServiceState; |
| import android.test.mock.MockContentProvider; |
| import android.test.mock.MockContentResolver; |
| |
| import androidx.test.InstrumentationRegistry; |
| import androidx.test.filters.MediumTest; |
| import androidx.test.runner.AndroidJUnit4; |
| |
| import com.android.bluetooth.TestUtils; |
| import com.android.bluetooth.btservice.ActiveDeviceManager; |
| import com.android.bluetooth.btservice.AdapterService; |
| import com.android.bluetooth.btservice.storage.DatabaseManager; |
| |
| import org.hamcrest.core.IsInstanceOf; |
| import org.junit.After; |
| import org.junit.Assert; |
| import org.junit.Before; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.ArgumentCaptor; |
| import org.mockito.Mock; |
| import org.mockito.Mockito; |
| import org.mockito.MockitoAnnotations; |
| |
| import java.util.ArrayList; |
| |
| /** |
| * 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 static final int MAX_RETRY_DISCONNECT_AUDIO = 3; |
| private Context mTargetContext; |
| private BluetoothAdapter mAdapter; |
| private HandlerThread mHandlerThread; |
| private HeadsetStateMachine mHeadsetStateMachine; |
| private BluetoothDevice mTestDevice; |
| private ArgumentCaptor<Intent> mIntentArgument = ArgumentCaptor.forClass(Intent.class); |
| |
| @Mock private AdapterService mAdapterService; |
| @Mock private ActiveDeviceManager mActiveDeviceManager; |
| @Mock private DatabaseManager mDatabaseManager; |
| @Mock private HeadsetService mHeadsetService; |
| @Mock private HeadsetSystemInterface mSystemInterface; |
| @Mock private AudioManager mAudioManager; |
| @Mock private HeadsetPhoneState mPhoneState; |
| @Mock private Intent mIntent; |
| private MockContentResolver mMockContentResolver; |
| private HeadsetNativeInterface mNativeInterface; |
| |
| @Before |
| public void setUp() throws Exception { |
| mTargetContext = InstrumentationRegistry.getTargetContext(); |
| // 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"); |
| // Get a database |
| doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); |
| doReturn(true).when(mDatabaseManager).setAudioPolicyMetadata(anyObject(), anyObject()); |
| // Get an active device manager |
| doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager(); |
| // 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.getConnectionPolicy(any(BluetoothDevice.class))).thenReturn( |
| BluetoothProfile.CONNECTION_POLICY_ALLOWED); |
| when(mHeadsetService.getForceScoAudio()).thenReturn(true); |
| when(mHeadsetService.okToAcceptConnection(any(BluetoothDevice.class), anyBoolean())) |
| .thenReturn(true); |
| when(mHeadsetService.isScoAcceptable(any(BluetoothDevice.class))).thenReturn( |
| BluetoothStatusCodes.SUCCESS); |
| // 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 { |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(), any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(), any(Bundle.class)); |
| 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(), any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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 AudioOn state via CONNECT_TIMEOUT message |
| * until retry count is reached, then test transition to Disconnecting state. |
| */ |
| @Test |
| public void testStateTransition_AudioDisconnectingToAudioOnAndDisconnecting_Timeout() { |
| int numBroadcastsSent = setUpAudioDisconnectingState(); |
| // Wait for connection to timeout |
| numBroadcastsSent++; |
| for (int i = 0; i <= MAX_RETRY_DISCONNECT_AUDIO; i++) { |
| if (i > 0) { // Skip first AUDIO_DISCONNECTING init as it was setup before the loop |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| Assert.assertThat(mHeadsetStateMachine.getCurrentState(), |
| IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class)); |
| if (i == MAX_RETRY_DISCONNECT_AUDIO) { |
| // Increment twice numBroadcastsSent as DISCONNECT message is added on max retry |
| numBroadcastsSent += 2; |
| } else { |
| numBroadcastsSent++; |
| } |
| } |
| verify(mHeadsetService, timeout(CONNECT_TIMEOUT_TEST_WAIT_MILLIS).times( |
| numBroadcastsSent)).sendBroadcastAsUser(mIntentArgument.capture(), |
| eq(UserHandle.ALL), eq(BLUETOOTH_CONNECT), any(Bundle.class)); |
| if (i < MAX_RETRY_DISCONNECT_AUDIO) { // Test if state is AudioOn before max retry |
| HeadsetTestUtils.verifyAudioStateBroadcast(mTestDevice, |
| BluetoothHeadset.STATE_AUDIO_CONNECTED, |
| BluetoothHeadset.STATE_AUDIO_CONNECTED, |
| mIntentArgument.getValue()); |
| Assert.assertThat(mHeadsetStateMachine.getCurrentState(), |
| IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); |
| } else { // Max retry count reached, test Disconnecting state |
| HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, |
| BluetoothHeadset.STATE_DISCONNECTING, |
| BluetoothHeadset.STATE_CONNECTED, |
| mIntentArgument.getValue()); |
| Assert.assertThat(mHeadsetStateMachine.getCurrentState(), |
| IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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, Bundle queryArgs, |
| CancellationSignal cancellationSignal) { |
| 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 (queryArgs == null |
| || !queryArgs.getString(ContentResolver.QUERY_ARG_SQL_SELECTION).equals( |
| Calls.TYPE + "=" + Calls.OUTGOING_TYPE) |
| || !queryArgs.getString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER).equals( |
| Calls.DEFAULT_SORT_ORDER) |
| || queryArgs.getInt(ContentResolver.QUERY_ARG_LIMIT) != 1) { |
| return null; |
| } |
| if (cancellationSignal != null) { |
| 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); |
| } |
| |
| /** |
| * A test to verfiy that we correctly handles AT+BIND event with driver safety case from HF |
| */ |
| @Test |
| public void testAtBindWithDriverSafetyEventWhenConnecting() { |
| setUpConnectingState(); |
| |
| String atString = "1"; |
| mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, |
| new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIND, atString, mTestDevice)); |
| ArgumentCaptor<Intent> intentArgument = ArgumentCaptor.forClass(Intent.class); |
| verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcast( |
| intentArgument.capture(), eq(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| verify(mHeadsetService, times(1)).sendBroadcast(any(), any(), |
| any()); |
| Assert.assertEquals(mTestDevice, intentArgument.getValue().getExtra( |
| BluetoothDevice.EXTRA_DEVICE, null)); |
| Assert.assertEquals(HeadsetHalConstants.HF_INDICATOR_ENHANCED_DRIVER_SAFETY, |
| intentArgument.getValue().getIntExtra( |
| BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1)); |
| Assert.assertEquals(-1, intentArgument.getValue().getIntExtra( |
| BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -2)); |
| } |
| |
| /** |
| * A test to verfiy that we correctly handles AT+BIND event with battery level case from HF |
| */ |
| @Test |
| public void testAtBindEventWithBatteryLevelEventWhenConnecting() { |
| setUpConnectingState(); |
| |
| String atString = "2"; |
| mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, |
| new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIND, atString, mTestDevice)); |
| ArgumentCaptor<Intent> intentArgument = ArgumentCaptor.forClass(Intent.class); |
| verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcast( |
| intentArgument.capture(), eq(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| verify(mHeadsetService, times(1)).sendBroadcast(any(), any(), |
| any()); |
| Assert.assertEquals(mTestDevice, intentArgument.getValue().getExtra( |
| BluetoothDevice.EXTRA_DEVICE, null)); |
| Assert.assertEquals(HeadsetHalConstants.HF_INDICATOR_BATTERY_LEVEL_STATUS, |
| intentArgument.getValue().getIntExtra( |
| BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1)); |
| Assert.assertEquals(-1, intentArgument.getValue().getIntExtra( |
| BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -2)); |
| } |
| |
| /** |
| * A test to verfiy that we correctly handles AT+BIND event with error case from HF |
| */ |
| @Test |
| public void testAtBindEventWithErrorEventWhenConnecting() { |
| setUpConnectingState(); |
| |
| String atString = "err,A,123,,1"; |
| mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, |
| new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIND, atString, mTestDevice)); |
| ArgumentCaptor<Intent> intentArgument = ArgumentCaptor.forClass(Intent.class); |
| verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcast( |
| intentArgument.capture(), eq(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| verify(mHeadsetService, times(1)).sendBroadcast(any(), any(), |
| any()); |
| Assert.assertEquals(mTestDevice, intentArgument.getValue().getExtra( |
| BluetoothDevice.EXTRA_DEVICE, null)); |
| Assert.assertEquals(HeadsetHalConstants.HF_INDICATOR_ENHANCED_DRIVER_SAFETY, |
| intentArgument.getValue().getIntExtra( |
| BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1)); |
| Assert.assertEquals(-1, intentArgument.getValue().getIntExtra( |
| BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -2)); |
| } |
| |
| /** |
| * A test to verify that we correctly set AG indicator mask when enter/exit silence mode |
| */ |
| @Test |
| public void testSetSilenceDevice() { |
| doNothing().when(mPhoneState).listenForPhoneState(any(BluetoothDevice.class), anyInt()); |
| mHeadsetStateMachine.setSilenceDevice(true); |
| mHeadsetStateMachine.setSilenceDevice(false); |
| verify(mPhoneState, times(2)).listenForPhoneState(mTestDevice, |
| PhoneStateListener.LISTEN_NONE); |
| } |
| |
| @Test |
| public void testBroadcastVendorSpecificEventIntent() { |
| mHeadsetStateMachine.broadcastVendorSpecificEventIntent( |
| "command", 1, 1, null, mTestDevice); |
| verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcastAsUser( |
| mIntentArgument.capture(), eq(UserHandle.ALL), eq(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| } |
| |
| @Test |
| public void testFindChar_withCharFound() { |
| char ch = 's'; |
| String input = "test"; |
| int fromIndex = 0; |
| |
| Assert.assertEquals(HeadsetStateMachine.findChar(ch, input, fromIndex), 2); |
| } |
| |
| @Test |
| public void testFindChar_withCharNotFound() { |
| char ch = 'x'; |
| String input = "test"; |
| int fromIndex = 0; |
| |
| Assert.assertEquals(HeadsetStateMachine.findChar(ch, input, fromIndex), input.length()); |
| } |
| |
| @Test |
| public void testFindChar_withQuotes() { |
| char ch = 's'; |
| String input = "te\"st"; |
| int fromIndex = 0; |
| |
| Assert.assertEquals(HeadsetStateMachine.findChar(ch, input, fromIndex), input.length()); |
| } |
| |
| @Test |
| public void testGenerateArgs() { |
| String input = "11,notint"; |
| ArrayList<Object> expected = new ArrayList<Object>(); |
| expected.add(11); |
| expected.add("notint"); |
| |
| Assert.assertEquals(HeadsetStateMachine.generateArgs(input), expected.toArray()); |
| } |
| |
| @Test |
| public void testGetAtCommandType() { |
| String atCommand = "start?"; |
| Assert.assertEquals(mHeadsetStateMachine.getAtCommandType(atCommand), |
| AtPhonebook.TYPE_READ); |
| |
| atCommand = "start=?"; |
| Assert.assertEquals(mHeadsetStateMachine.getAtCommandType(atCommand), |
| AtPhonebook.TYPE_TEST); |
| |
| atCommand = "start=comm"; |
| Assert.assertEquals(mHeadsetStateMachine.getAtCommandType(atCommand), AtPhonebook.TYPE_SET); |
| |
| atCommand = "start!"; |
| Assert.assertEquals(mHeadsetStateMachine.getAtCommandType(atCommand), |
| AtPhonebook.TYPE_UNKNOWN); |
| } |
| |
| @Test |
| public void testParseUnknownAt() { |
| String atString = "\"command\""; |
| |
| Assert.assertEquals(mHeadsetStateMachine.parseUnknownAt(atString), "\"command\""); |
| } |
| |
| @Test |
| public void testParseUnknownAt_withUnmatchingQuotes() { |
| String atString = "\"command"; |
| |
| Assert.assertEquals(mHeadsetStateMachine.parseUnknownAt(atString), "\"command\""); |
| } |
| |
| @Test |
| public void testParseUnknownAt_withCharOutsideQuotes() { |
| String atString = "a\"command\""; |
| |
| Assert.assertEquals(mHeadsetStateMachine.parseUnknownAt(atString), "A\"command\""); |
| } |
| |
| @Ignore("b/265556073") |
| @Test |
| public void testHandleAccessPermissionResult_withNoChangeInAtCommandResult() { |
| when(mIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)).thenReturn(null); |
| when(mIntent.getAction()).thenReturn(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); |
| when(mIntent.getIntExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT, |
| BluetoothDevice.CONNECTION_ACCESS_NO)) |
| .thenReturn(BluetoothDevice.CONNECTION_ACCESS_NO); |
| when(mIntent.getBooleanExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, false)).thenReturn(true); |
| mHeadsetStateMachine.mPhonebook.setCheckingAccessPermission(true); |
| |
| mHeadsetStateMachine.handleAccessPermissionResult(mIntent); |
| |
| verify(mNativeInterface).atResponseCode(null, 0, 0); |
| } |
| |
| @Test |
| public void testProcessAtBievCommand() { |
| mHeadsetStateMachine.processAtBiev(1, 1, mTestDevice); |
| |
| verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBroadcast( |
| mIntentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); |
| } |
| |
| @Test |
| public void testProcessAtChld_withProcessChldTrue() { |
| int chld = 1; |
| when(mSystemInterface.processChld(chld)).thenReturn(true); |
| |
| mHeadsetStateMachine.processAtChld(chld, mTestDevice); |
| |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0); |
| } |
| |
| @Test |
| public void testProcessAtChld_withProcessChldFalse() { |
| int chld = 1; |
| when(mSystemInterface.processChld(chld)).thenReturn(false); |
| |
| mHeadsetStateMachine.processAtChld(chld, mTestDevice); |
| |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| 0); |
| } |
| |
| @Test |
| public void testProcessAtClcc_withVirtualCallStarted() { |
| when(mHeadsetService.isVirtualCallStarted()).thenReturn(true); |
| when(mSystemInterface.getSubscriberNumber()).thenReturn(null); |
| |
| mHeadsetStateMachine.processAtClcc(mTestDevice); |
| |
| verify(mNativeInterface).clccResponse(mTestDevice, 0, 0, 0, 0, false, "", 0); |
| } |
| |
| @Test |
| public void testProcessAtClcc_withVirtualCallNotStarted() { |
| when(mHeadsetService.isVirtualCallStarted()).thenReturn(false); |
| when(mSystemInterface.listCurrentCalls()).thenReturn(false); |
| |
| mHeadsetStateMachine.processAtClcc(mTestDevice); |
| |
| verify(mNativeInterface).clccResponse(mTestDevice, 0, 0, 0, 0, false, "", 0); |
| } |
| |
| @Test |
| public void testProcessAtCops() { |
| ServiceState serviceState = mock(ServiceState.class); |
| when(serviceState.getOperatorAlphaLong()).thenReturn(""); |
| when(serviceState.getOperatorAlphaShort()).thenReturn(""); |
| HeadsetPhoneState phoneState = mock(HeadsetPhoneState.class); |
| when(phoneState.getServiceState()).thenReturn(serviceState); |
| when(mSystemInterface.getHeadsetPhoneState()).thenReturn(phoneState); |
| when(mSystemInterface.isInCall()).thenReturn(true); |
| when(mSystemInterface.getNetworkOperator()).thenReturn(null); |
| |
| mHeadsetStateMachine.processAtCops(mTestDevice); |
| |
| verify(mNativeInterface).copsResponse(mTestDevice, ""); |
| } |
| |
| @Test |
| public void testProcessAtCpbr() { |
| String atString = "command=ERR"; |
| int type = AtPhonebook.TYPE_SET; |
| |
| mHeadsetStateMachine.processAtCpbr(atString, type, mTestDevice); |
| |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| BluetoothCmeError.TEXT_HAS_INVALID_CHARS); |
| } |
| |
| @Test |
| public void testProcessAtCpbs() { |
| String atString = "command=ERR"; |
| int type = AtPhonebook.TYPE_SET; |
| |
| mHeadsetStateMachine.processAtCpbs(atString, type, mTestDevice); |
| |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| BluetoothCmeError.OPERATION_NOT_ALLOWED); |
| } |
| |
| @Test |
| public void testProcessAtCscs() { |
| String atString = "command=GSM"; |
| int type = AtPhonebook.TYPE_SET; |
| |
| mHeadsetStateMachine.processAtCscs(atString, type, mTestDevice); |
| |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, |
| -1); |
| } |
| |
| @Test |
| public void testProcessAtXapl() { |
| Object[] args = new Object[2]; |
| args[0] = "1-12-3"; |
| args[1] = 1; |
| |
| mHeadsetStateMachine.processAtXapl(args, mTestDevice); |
| |
| verify(mNativeInterface).atResponseString(mTestDevice, "+XAPL=iPhone," + String.valueOf(2)); |
| } |
| |
| @Test |
| public void testProcessSendVendorSpecificResultCode() { |
| HeadsetVendorSpecificResultCode resultCode = new HeadsetVendorSpecificResultCode( |
| mTestDevice, "command", "arg"); |
| |
| mHeadsetStateMachine.processSendVendorSpecificResultCode(resultCode); |
| |
| verify(mNativeInterface).atResponseString(mTestDevice, "command" + ": " + "arg"); |
| } |
| |
| @Test |
| public void testProcessSubscriberNumberRequest_withSubscriberNumberNull() { |
| when(mSystemInterface.getSubscriberNumber()).thenReturn(null); |
| |
| mHeadsetStateMachine.processSubscriberNumberRequest(mTestDevice); |
| |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0); |
| } |
| |
| @Test |
| public void testProcessSubscriberNumberRequest_withSubscriberNumberNotNull() { |
| String number = "1111"; |
| when(mSystemInterface.getSubscriberNumber()).thenReturn(number); |
| |
| mHeadsetStateMachine.processSubscriberNumberRequest(mTestDevice); |
| |
| verify(mNativeInterface).atResponseString(mTestDevice, |
| "+CNUM: ,\"" + number + "\"," + PhoneNumberUtils.toaFromString(number) + ",,4"); |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0); |
| } |
| |
| @Test |
| public void testProcessUnknownAt() { |
| String atString = "+CSCS=invalid"; |
| mHeadsetStateMachine.processUnknownAt(atString, mTestDevice); |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| BluetoothCmeError.OPERATION_NOT_SUPPORTED); |
| Mockito.clearInvocations(mNativeInterface); |
| |
| atString = "+CPBS="; |
| mHeadsetStateMachine.processUnknownAt(atString, mTestDevice); |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| BluetoothCmeError.OPERATION_NOT_SUPPORTED); |
| |
| atString = "+CPBR=ERR"; |
| mHeadsetStateMachine.processUnknownAt(atString, mTestDevice); |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| BluetoothCmeError.TEXT_HAS_INVALID_CHARS); |
| |
| atString = "inval="; |
| mHeadsetStateMachine.processUnknownAt(atString, mTestDevice); |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| 0); |
| } |
| |
| @Test |
| public void testProcessVendorSpecificAt_withNoEqualSignCommand() { |
| String atString = "invalid_command"; |
| |
| mHeadsetStateMachine.processVendorSpecificAt(atString, mTestDevice); |
| |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| 0); |
| } |
| |
| @Test |
| public void testProcessVendorSpecificAt_withUnsupportedCommand() { |
| String atString = "invalid_command="; |
| |
| mHeadsetStateMachine.processVendorSpecificAt(atString, mTestDevice); |
| |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| 0); |
| } |
| |
| @Test |
| public void testProcessVendorSpecificAt_withQuestionMarkArg() { |
| String atString = BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT + "=?arg"; |
| |
| mHeadsetStateMachine.processVendorSpecificAt(atString, mTestDevice); |
| |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, |
| 0); |
| } |
| |
| @Test |
| public void testProcessVendorSpecificAt_withValidCommandAndArg() { |
| String atString = BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_XAPL + "=1-12-3,1"; |
| |
| mHeadsetStateMachine.processVendorSpecificAt(atString, mTestDevice); |
| |
| verify(mNativeInterface).atResponseString(mTestDevice, "+XAPL=iPhone," + "2"); |
| verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0); |
| } |
| |
| @Test |
| public void testProcessVolumeEvent_withVolumeTypeMic() { |
| when(mHeadsetService.getActiveDevice()).thenReturn(mTestDevice); |
| |
| mHeadsetStateMachine.processVolumeEvent(HeadsetHalConstants.VOLUME_TYPE_MIC, 1); |
| |
| Assert.assertEquals(mHeadsetStateMachine.mMicVolume, 1); |
| } |
| |
| @Test |
| public void testProcessVolumeEvent_withVolumeTypeSpk() { |
| when(mHeadsetService.getActiveDevice()).thenReturn(mTestDevice); |
| AudioManager mockAudioManager = mock(AudioManager.class); |
| when(mockAudioManager.getStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO)).thenReturn(1); |
| when(mSystemInterface.getAudioManager()).thenReturn(mockAudioManager); |
| |
| mHeadsetStateMachine.processVolumeEvent(HeadsetHalConstants.VOLUME_TYPE_SPK, 2); |
| |
| Assert.assertEquals(mHeadsetStateMachine.mSpeakerVolume, 2); |
| verify(mockAudioManager).setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, 2, 0); |
| } |
| |
| @Test |
| public void testDump_doesNotCrash() { |
| StringBuilder sb = new StringBuilder(); |
| |
| mHeadsetStateMachine.dump(sb); |
| } |
| |
| /** |
| * A test to validate received Android AT commands and processing |
| */ |
| @Test |
| public void testCheckAndProcessAndroidAt() { |
| // Commands that will be handled |
| int counter_ok = 0; |
| int counter_error = 0; |
| Assert.assertTrue(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "+ANDROID=?" , mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(++counter_ok)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0); |
| Assert.assertTrue(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "+ANDROID=SINKAUDIOPOLICY,1,1,1" , mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(++counter_ok)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0); |
| Assert.assertTrue(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "+ANDROID=SINKAUDIOPOLICY,100,100,100" , mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(++counter_ok)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0); |
| Assert.assertTrue(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "+ANDROID=SINKAUDIOPOLICY,1,2,3,4,5" , mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(++counter_error)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0); |
| Assert.assertTrue(mHeadsetStateMachine.checkAndProcessAndroidAt("+ANDROID=1", mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(++counter_error)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0); |
| Assert.assertTrue( |
| mHeadsetStateMachine.checkAndProcessAndroidAt("+ANDROID=1,2", mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(++counter_error)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0); |
| Assert.assertTrue( |
| mHeadsetStateMachine.checkAndProcessAndroidAt("+ANDROID=1,2,3", mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(++counter_error)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0); |
| Assert.assertTrue( |
| mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "+ANDROID=1,2,3,4,5,6,7", mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(++counter_error)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0); |
| |
| // Commands with correct format but will not be handled |
| Assert.assertFalse(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "+ANDROID=" , mTestDevice)); |
| Assert.assertFalse(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "+ANDROID: PROBE,1,\"`AB\"" , mTestDevice)); |
| Assert.assertFalse(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "+ANDROID= PROBE,1,\"`AB\"" , mTestDevice)); |
| Assert.assertFalse(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "AT+ANDROID=PROBE,1,1,\"PQGHRSBCTU__\"" , mTestDevice)); |
| |
| // Incorrect format AT command |
| Assert.assertFalse(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "RANDOM FORMAT" , mTestDevice)); |
| |
| // Check no any AT result was sent for the failed ones |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(counter_ok)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(counter_error)) |
| .atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0); |
| } |
| |
| @Test |
| public void testCheckAndProcessAndroidAt_replyAndroidAtFeatureRequest() { |
| // Commands that will be handled |
| Assert.assertTrue(mHeadsetStateMachine.checkAndProcessAndroidAt( |
| "+ANDROID=?" , mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).atResponseString( |
| mTestDevice, "+ANDROID: (SINKAUDIOPOLICY)"); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).atResponseCode( |
| mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0); |
| } |
| |
| /** |
| * A end to end test to validate received Android AT commands and processing |
| */ |
| @Test |
| public void testCehckAndProcessAndroidAtFromStateMachine() { |
| // setAudioPolicyMetadata is invoked in HeadsetStateMachine.init() so start from 1 |
| int expectCallTimes = 1; |
| |
| // setup Audio Policy Feature |
| setUpConnectedState(); |
| |
| setUpAudioPolicy(); |
| // receive and set android policy |
| mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, |
| new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_UNKNOWN_AT, |
| "+ANDROID=SINKAUDIOPOLICY,1,1,1", mTestDevice)); |
| expectCallTimes++; |
| verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(expectCallTimes)) |
| .setAudioPolicyMetadata(anyObject(), anyObject()); |
| |
| // receive and not set android policy |
| mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, |
| new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_UNKNOWN_AT, |
| "AT+ANDROID=PROBE,1,1,\"PQGHRSBCTU__\"", mTestDevice)); |
| verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(expectCallTimes)) |
| .setAudioPolicyMetadata(anyObject(), anyObject()); |
| } |
| |
| /** |
| * A test to verify whether the sink audio policy command is valid |
| */ |
| @Test |
| public void testProcessAndroidAtSinkAudioPolicy() { |
| // expected format |
| Assert.assertTrue(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,0,0,0", mTestDevice)); |
| Assert.assertTrue(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,0,0,1", mTestDevice)); |
| Assert.assertTrue(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,0,1,0", mTestDevice)); |
| Assert.assertTrue(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,1,0,0", mTestDevice)); |
| Assert.assertTrue(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,1,1,1", mTestDevice)); |
| |
| // invalid format |
| Assert.assertFalse(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,0", mTestDevice)); |
| Assert.assertFalse(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,0,0", mTestDevice)); |
| Assert.assertFalse(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,0,0,0,0", mTestDevice)); |
| Assert.assertFalse(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,NOT,INT,TYPE", mTestDevice)); |
| Assert.assertFalse(setSinkAudioPolicyArgs("RANDOM,VALUE-#$%,*(&^", mTestDevice)); |
| |
| // wrong device |
| BluetoothDevice device = mAdapter.getRemoteDevice("01:01:01:01:01:01"); |
| Assert.assertFalse(setSinkAudioPolicyArgs("SINKAUDIOPOLICY,0,0,0", device)); |
| } |
| |
| /** |
| * set sink audio policy |
| * @param arg body of the AT command |
| * @return the result from processAndroidAtSinkAudioPolicy |
| */ |
| private boolean setSinkAudioPolicyArgs(String arg, BluetoothDevice device) { |
| Object[] args = HeadsetStateMachine.generateArgs(arg); |
| return mHeadsetStateMachine.processAndroidAtSinkAudioPolicy(args, device); |
| } |
| |
| /** |
| * 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| 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(BLUETOOTH_CONNECT), |
| any(Bundle.class)); |
| HeadsetTestUtils.verifyConnectionStateBroadcast(mTestDevice, |
| BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, |
| mIntentArgument.getValue()); |
| Assert.assertThat(mHeadsetStateMachine.getCurrentState(), |
| IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); |
| return numBroadcastsSent; |
| } |
| |
| private void setUpAudioPolicy() { |
| mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, |
| new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_UNKNOWN_AT, |
| "+ANDROID=?", mTestDevice)); |
| verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).atResponseString( |
| anyObject(), anyString()); |
| } |
| } |