package com.android.bluetooth.hfpclient; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.os.Bundle; import android.test.AndroidTestCase; import android.util.Log; import java.nio.ByteBuffer; import java.util.List; import java.util.Arrays; import java.util.ArrayList; import com.android.bluetooth.btservice.AdapterService; import static org.mockito.Mockito.*; import org.mockito.ArgumentCaptor; public class HeadsetClientStateMachineTest extends AndroidTestCase { private BluetoothAdapter mAdapter = null; @Override protected void setUp() throws Exception { AdapterService inst = mock(AdapterService.class); assertTrue(inst != null); mAdapter = BluetoothAdapter.getDefaultAdapter(); } // Test that default state is disconnected public void testDefaultDisconnectedState() { HeadsetClientService mockService = mock(HeadsetClientService.class); AudioManager mockAudioManager = mock(AudioManager.class); when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager); HeadsetClientStateMachine mockSM = new HeadsetClientStateMachine( mockService, getContext().getMainLooper()); assertEquals( mockSM.getConnectionState((BluetoothDevice) null), BluetoothProfile.STATE_DISCONNECTED); } // Test that an incoming connection with low priority is rejected public void testIncomingPriorityReject() { HeadsetClientService mockService = mock(HeadsetClientService.class); AudioManager mockAudioManager = mock(AudioManager.class); BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05"); when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager); HeadsetClientStateMachine mockSM = new HeadsetClientStateMachine( mockService, getContext().getMainLooper()); mockSM.start(); // Return false for priority. when(mockService.getPriority(any(BluetoothDevice.class))).thenReturn( BluetoothProfile.PRIORITY_OFF); // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.valueInt2 = 0; connStCh.valueInt3 = 0; connStCh.device = device; mockSM.sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that no connection state broadcast is executed verify(mockService, never()).sendBroadcast(any(Intent.class), anyString()); // Check we are in disconnected state still. assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Disconnected); } // Test that an incoming connection with high priority is accepted public void testIncomingPriorityAccept() { HeadsetClientService mockService = mock(HeadsetClientService.class); AudioManager mockAudioManager = mock(AudioManager.class); BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05"); when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager); // Set a valid volume when(mockAudioManager.getStreamVolume(anyInt())).thenReturn(2); when(mockAudioManager.getStreamMaxVolume(anyInt())).thenReturn(10); when(mockAudioManager.getStreamMinVolume(anyInt())).thenReturn(1); HeadsetClientStateMachine mockSM = new HeadsetClientStateMachine( mockService, getContext().getMainLooper()); mockSM.start(); // Return false for priority. when(mockService.getPriority(any(BluetoothDevice.class))).thenReturn( BluetoothProfile.PRIORITY_ON); // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.valueInt2 = 0; connStCh.valueInt3 = 0; connStCh.device = device; mockSM.sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); verify(mockService, timeout(1000)).sendBroadcast(intentArgument1.capture(), anyString()); assertEquals(BluetoothProfile.STATE_CONNECTING, intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); // Check we are in connecting state now. assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Connecting); // Send a message to trigger SLC connection StackEvent slcEvent = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); slcEvent.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_SLC_CONNECTED; slcEvent.valueInt2 = HeadsetClientHalConstants.PEER_FEAT_ECS; slcEvent.valueInt3 = 0; slcEvent.device = device; mockSM.sendMessage(StackEvent.STACK_EVENT, slcEvent); // Verify that one connection state broadcast is executed ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); verify(mockService, timeout(1000).times(2)).sendBroadcast(intentArgument2.capture(), anyString()); assertEquals(BluetoothProfile.STATE_CONNECTED, intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); // Check we are in connecting state now. assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Connected); } // Test that an incoming connection that times out public void testIncomingTimeout() { HeadsetClientService mockService = mock(HeadsetClientService.class); AudioManager mockAudioManager = mock(AudioManager.class); BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05"); when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager); // Set a valid volume when(mockAudioManager.getStreamVolume(anyInt())).thenReturn(2); when(mockAudioManager.getStreamMaxVolume(anyInt())).thenReturn(10); when(mockAudioManager.getStreamMinVolume(anyInt())).thenReturn(1); HeadsetClientStateMachine mockSM = new HeadsetClientStateMachine( mockService, getContext().getMainLooper()); mockSM.start(); // Return false for priority. when(mockService.getPriority(any(BluetoothDevice.class))).thenReturn( BluetoothProfile.PRIORITY_ON); // Inject an event for when incoming connection is requested StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; connStCh.valueInt2 = 0; connStCh.valueInt3 = 0; connStCh.device = device; mockSM.sendMessage(StackEvent.STACK_EVENT, connStCh); // Verify that one connection state broadcast is executed ArgumentCaptor intentArgument1 = ArgumentCaptor.forClass(Intent.class); verify(mockService, timeout(1000)).sendBroadcast(intentArgument1.capture(), anyString()); assertEquals(BluetoothProfile.STATE_CONNECTING, intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); // Check we are in connecting state now. assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Connecting); // Verify that one connection state broadcast is executed ArgumentCaptor intentArgument2 = ArgumentCaptor.forClass(Intent.class); verify(mockService, timeout(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS * 2).times(2)).sendBroadcast( intentArgument2.capture(), anyString()); assertEquals(BluetoothProfile.STATE_DISCONNECTED, intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); // Check we are in connecting state now. assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Disconnected); } }