1 package com.android.bluetooth.hfpclient; 2 3 import android.bluetooth.BluetoothAdapter; 4 import android.bluetooth.BluetoothDevice; 5 import android.bluetooth.BluetoothProfile; 6 import android.content.Context; 7 import android.content.Intent; 8 import android.media.AudioManager; 9 import android.os.Bundle; 10 import android.test.AndroidTestCase; 11 import android.util.Log; 12 13 import java.nio.ByteBuffer; 14 import java.util.List; 15 import java.util.Arrays; 16 import java.util.ArrayList; 17 18 import com.android.bluetooth.btservice.AdapterService; 19 20 import static org.mockito.Mockito.*; 21 import org.mockito.ArgumentCaptor; 22 23 public class HeadsetClientStateMachineTest extends AndroidTestCase { 24 private BluetoothAdapter mAdapter = null; 25 26 @Override setUp()27 protected void setUp() throws Exception { 28 AdapterService inst = AdapterService.getAdapterService(); 29 assertTrue(inst != null); 30 mAdapter = BluetoothAdapter.getDefaultAdapter(); 31 } 32 33 // Test that default state is disconnected testDefaultDisconnectedState()34 public void testDefaultDisconnectedState() { 35 HeadsetClientService mockService = mock(HeadsetClientService.class); 36 AudioManager mockAudioManager = mock(AudioManager.class); 37 38 when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager); 39 40 HeadsetClientStateMachine mockSM = new HeadsetClientStateMachine( 41 mockService, getContext().getMainLooper()); 42 assertEquals( 43 mockSM.getConnectionState((BluetoothDevice) null), BluetoothProfile.STATE_DISCONNECTED); 44 } 45 46 // Test that an incoming connection with low priority is rejected testIncomingPriorityReject()47 public void testIncomingPriorityReject() { 48 HeadsetClientService mockService = mock(HeadsetClientService.class); 49 AudioManager mockAudioManager = mock(AudioManager.class); 50 BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05"); 51 52 when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager); 53 54 HeadsetClientStateMachine mockSM = new HeadsetClientStateMachine( 55 mockService, getContext().getMainLooper()); 56 mockSM.start(); 57 58 // Return false for priority. 59 when(mockService.getPriority(any(BluetoothDevice.class))).thenReturn( 60 BluetoothProfile.PRIORITY_OFF); 61 62 // Inject an event for when incoming connection is requested 63 StackEvent connStCh = 64 new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 65 connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; 66 connStCh.valueInt2 = 0; 67 connStCh.valueInt3 = 0; 68 connStCh.device = device; 69 mockSM.sendMessage(StackEvent.STACK_EVENT, connStCh); 70 71 // Verify that no connection state broadcast is executed 72 verify(mockService, never()).sendBroadcast(any(Intent.class), anyString()); 73 // Check we are in disconnected state still. 74 assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Disconnected); 75 } 76 77 // Test that an incoming connection with high priority is accepted testIncomingPriorityAccept()78 public void testIncomingPriorityAccept() { 79 HeadsetClientService mockService = mock(HeadsetClientService.class); 80 AudioManager mockAudioManager = mock(AudioManager.class); 81 BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05"); 82 83 when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager); 84 // Set a valid volume 85 when(mockAudioManager.getStreamVolume(anyInt())).thenReturn(2); 86 when(mockAudioManager.getStreamMaxVolume(anyInt())).thenReturn(10); 87 when(mockAudioManager.getStreamMinVolume(anyInt())).thenReturn(1); 88 89 90 HeadsetClientStateMachine mockSM = new HeadsetClientStateMachine( 91 mockService, getContext().getMainLooper()); 92 mockSM.start(); 93 94 // Return false for priority. 95 when(mockService.getPriority(any(BluetoothDevice.class))).thenReturn( 96 BluetoothProfile.PRIORITY_ON); 97 98 // Inject an event for when incoming connection is requested 99 StackEvent connStCh = 100 new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 101 connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; 102 connStCh.valueInt2 = 0; 103 connStCh.valueInt3 = 0; 104 connStCh.device = device; 105 mockSM.sendMessage(StackEvent.STACK_EVENT, connStCh); 106 107 // Verify that one connection state broadcast is executed 108 ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); 109 verify(mockService, 110 timeout(1000)).sendBroadcast(intentArgument1.capture(), anyString()); 111 assertEquals(BluetoothProfile.STATE_CONNECTING, 112 intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); 113 114 // Check we are in connecting state now. 115 assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Connecting); 116 117 // Send a message to trigger SLC connection 118 StackEvent slcEvent = 119 new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 120 slcEvent.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_SLC_CONNECTED; 121 slcEvent.valueInt2 = HeadsetClientHalConstants.PEER_FEAT_ECS; 122 slcEvent.valueInt3 = 0; 123 slcEvent.device = device; 124 mockSM.sendMessage(StackEvent.STACK_EVENT, slcEvent); 125 126 // Verify that one connection state broadcast is executed 127 ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class); 128 verify(mockService, 129 timeout(1000).times(2)).sendBroadcast(intentArgument2.capture(), anyString()); 130 assertEquals(BluetoothProfile.STATE_CONNECTED, 131 intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); 132 // Check we are in connecting state now. 133 assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Connected); 134 } 135 136 // Test that an incoming connection that times out testIncomingTimeout()137 public void testIncomingTimeout() { 138 HeadsetClientService mockService = mock(HeadsetClientService.class); 139 AudioManager mockAudioManager = mock(AudioManager.class); 140 BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05"); 141 142 when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager); 143 // Set a valid volume 144 when(mockAudioManager.getStreamVolume(anyInt())).thenReturn(2); 145 when(mockAudioManager.getStreamMaxVolume(anyInt())).thenReturn(10); 146 when(mockAudioManager.getStreamMinVolume(anyInt())).thenReturn(1); 147 148 149 HeadsetClientStateMachine mockSM = new HeadsetClientStateMachine( 150 mockService, getContext().getMainLooper()); 151 mockSM.start(); 152 153 // Return false for priority. 154 when(mockService.getPriority(any(BluetoothDevice.class))).thenReturn( 155 BluetoothProfile.PRIORITY_ON); 156 157 // Inject an event for when incoming connection is requested 158 StackEvent connStCh = 159 new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 160 connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED; 161 connStCh.valueInt2 = 0; 162 connStCh.valueInt3 = 0; 163 connStCh.device = device; 164 mockSM.sendMessage(StackEvent.STACK_EVENT, connStCh); 165 166 // Verify that one connection state broadcast is executed 167 ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); 168 verify(mockService, timeout(1000)).sendBroadcast(intentArgument1.capture(), anyString()); 169 assertEquals(BluetoothProfile.STATE_CONNECTING, 170 intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); 171 172 // Check we are in connecting state now. 173 assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Connecting); 174 175 // Verify that one connection state broadcast is executed 176 ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class); 177 verify(mockService, 178 timeout(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS * 2).times(2)).sendBroadcast( 179 intentArgument2.capture(), anyString()); 180 assertEquals(BluetoothProfile.STATE_DISCONNECTED, 181 intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); 182 183 // Check we are in connecting state now. 184 assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Disconnected); 185 } 186 } 187