Loading android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +6 −40 Original line number Diff line number Diff line Loading @@ -152,7 +152,8 @@ public class BassClientStateMachine extends StateMachine { private final Connecting mConnecting = new Connecting(); private final Disconnecting mDisconnecting = new Disconnecting(); private final ConnectedProcessing mConnectedProcessing = new ConnectedProcessing(); private final List<BluetoothGattCharacteristic> mBroadcastCharacteristics = @VisibleForTesting final List<BluetoothGattCharacteristic> mBroadcastCharacteristics = new ArrayList<BluetoothGattCharacteristic>(); @VisibleForTesting BluetoothDevice mDevice; Loading Loading @@ -181,7 +182,8 @@ public class BassClientStateMachine extends StateMachine { // Psync and PAST interfaces private PeriodicAdvertisingManager mPeriodicAdvManager; private boolean mAutoTriggered = false; private boolean mNoStopScanOffload = false; @VisibleForTesting boolean mNoStopScanOffload = false; private boolean mDefNoPAS = false; private boolean mForceSB = false; private int mBroadcastSourceIdLength = 3; Loading Loading @@ -559,7 +561,8 @@ public class BassClientStateMachine extends StateMachine { mService.getCallbacks().notifyReceiveStateChanged(mDevice, sourceId, state); } private static boolean isEmpty(final byte[] data) { @VisibleForTesting static boolean isEmpty(final byte[] data) { return IntStream.range(0, data.length).parallel().allMatch(i -> data[i] == 0); } Loading Loading @@ -1231,18 +1234,6 @@ public class BassClientStateMachine extends StateMachine { } } private byte[] bluetoothAddressToBytes(String s) { log("BluetoothAddressToBytes: input string:" + s); String[] splits = s.split(":"); byte[] addressBytes = new byte[6]; for (int i = 0; i < 6; i++) { int hexValue = Integer.parseInt(splits[i], 16); log("hexValue:" + hexValue); addressBytes[i] = (byte) hexValue; } return addressBytes; } private static int getBisSyncFromChannelPreference( List<BluetoothLeBroadcastChannel> channels) { int bisSync = 0; Loading Loading @@ -1392,15 +1383,6 @@ public class BassClientStateMachine extends StateMachine { return res; } private byte[] convertAsciitoValues(byte[] val) { byte[] ret = new byte[val.length]; for (int i = 0; i < val.length; i++) { ret[i] = (byte) (val[i] - (byte) '0'); } log("convertAsciitoValues: returns:" + Arrays.toString(val)); return ret; } private byte[] convertRecvStateToSetBroadcastCodeByteArray( BluetoothLeBroadcastReceiveState recvState) { byte[] res = new byte[BassConstants.PIN_CODE_CMD_LEN]; Loading Loading @@ -1990,22 +1972,6 @@ public class BassClientStateMachine extends StateMachine { return Integer.toString(what); } private static String profileStateToString(int state) { switch (state) { case BluetoothProfile.STATE_DISCONNECTED: return "DISCONNECTED"; case BluetoothProfile.STATE_CONNECTING: return "CONNECTING"; case BluetoothProfile.STATE_CONNECTED: return "CONNECTED"; case BluetoothProfile.STATE_DISCONNECTING: return "DISCONNECTING"; default: break; } return Integer.toString(state); } /** * Dump info */ Loading android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +124 −12 Original line number Diff line number Diff line Loading @@ -18,11 +18,18 @@ package com.android.bluetooth.bass_client; import static android.bluetooth.BluetoothGatt.GATT_SUCCESS; import static com.android.bluetooth.bass_client.BassClientStateMachine.CONNECT; import static com.android.bluetooth.bass_client.BassClientStateMachine.CONNECT_TIMEOUT; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.after; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -31,7 +38,10 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.bluetooth.le.PeriodicAdvertisingManager; import android.bluetooth.le.ScanRecord; import android.content.Intent; import android.os.Bundle; import android.os.HandlerThread; Loading @@ -43,8 +53,6 @@ import androidx.test.filters.MediumTest; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import static com.google.common.truth.Truth.assertThat; import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; Loading @@ -59,6 +67,8 @@ import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; import java.util.UUID; @MediumTest Loading Loading @@ -134,7 +144,7 @@ public class BassClientStateMachineTest { allowConnectGatt(true); // Inject an event for when incoming connection is requested mBassClientStateMachine.sendMessage(BassClientStateMachine.CONNECT); mBassClientStateMachine.sendMessage(CONNECT); // Verify that no connection state broadcast is executed verify(mBassClientService, after(WAIT_MS).never()).sendBroadcast(any(Intent.class), Loading @@ -151,7 +161,7 @@ public class BassClientStateMachineTest { allowConnectGatt(false); // Inject an event for when incoming connection is requested mBassClientStateMachine.sendMessage(BassClientStateMachine.CONNECT); mBassClientStateMachine.sendMessage(CONNECT); // Verify that no connection state broadcast is executed verify(mBassClientService, after(WAIT_MS).never()).sendBroadcast(any(Intent.class), Loading @@ -169,7 +179,7 @@ public class BassClientStateMachineTest { allowConnectGatt(true); // Inject an event for when incoming connection is requested mBassClientStateMachine.sendMessage(BassClientStateMachine.CONNECT); mBassClientStateMachine.sendMessage(CONNECT); // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); Loading Loading @@ -201,7 +211,7 @@ public class BassClientStateMachineTest { allowConnectGatt(true); // Inject an event for when incoming connection is requested mBassClientStateMachine.sendMessage(BassClientStateMachine.CONNECT); mBassClientStateMachine.sendMessage(CONNECT); // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); Loading Loading @@ -234,7 +244,7 @@ public class BassClientStateMachineTest { // disconnected -> connecting ---timeout---> disconnected sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT_TIMEOUT), Loading @@ -242,7 +252,7 @@ public class BassClientStateMachineTest { // disconnected -> connecting ---DISCONNECT---> disconnected sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.DISCONNECT), Loading @@ -251,7 +261,7 @@ public class BassClientStateMachineTest { // disconnected -> connecting ---CONNECTION_STATE_CHANGED(connected)---> connected --> // disconnected sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage( Loading @@ -266,7 +276,7 @@ public class BassClientStateMachineTest { // disconnected -> connecting ---CONNECTION_STATE_CHANGED(non-connected) --> disconnected sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage( Loading @@ -276,7 +286,7 @@ public class BassClientStateMachineTest { // change default state to connected for the next tests sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage( Loading Loading @@ -338,6 +348,109 @@ public class BassClientStateMachineTest { BassClientStateMachine.Connected.class); } @Test public void acquireAllBassChars() { BassClientStateMachine.BluetoothGattTestableWrapper btGatt = Mockito.mock( BassClientStateMachine.BluetoothGattTestableWrapper.class); mBassClientStateMachine.mBluetoothGatt = btGatt; // Do nothing when mBluetoothGatt.getService returns null mBassClientStateMachine.acquireAllBassChars(); BluetoothGattService gattService = Mockito.mock(BluetoothGattService.class); when(btGatt.getService(BassConstants.BASS_UUID)).thenReturn(gattService); List<BluetoothGattCharacteristic> characteristics = new ArrayList<>(); BluetoothGattCharacteristic scanControlPoint = new BluetoothGattCharacteristic( BassConstants.BASS_BCAST_AUDIO_SCAN_CTRL_POINT, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ); characteristics.add(scanControlPoint); BluetoothGattCharacteristic bassCharacteristic = new BluetoothGattCharacteristic( UUID.randomUUID(), BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ); characteristics.add(bassCharacteristic); when(gattService.getCharacteristics()).thenReturn(characteristics); mBassClientStateMachine.acquireAllBassChars(); assertThat(mBassClientStateMachine.mBroadcastScanControlPoint).isEqualTo(scanControlPoint); assertThat(mBassClientStateMachine.mBroadcastCharacteristics).contains(bassCharacteristic); } @Test public void simpleMethods() { // dump() shouldn't crash StringBuilder sb = new StringBuilder(); mBassClientStateMachine.dump(sb); // log() shouldn't crash String msg = "test-log-message"; mBassClientStateMachine.log(msg); // messageWhatToString() shouldn't crash for (int i = CONNECT; i <= CONNECT_TIMEOUT + 1; ++i) { mBassClientStateMachine.messageWhatToString(i); } final int invalidSourceId = -100; assertThat(mBassClientStateMachine.getCurrentBroadcastMetadata(invalidSourceId)).isNull(); assertThat(mBassClientStateMachine.getDevice()).isEqualTo(mTestDevice); assertThat(mBassClientStateMachine.hasPendingSourceOperation()).isFalse(); assertThat(mBassClientStateMachine.isEmpty(new byte[] { 0 })).isTrue(); assertThat(mBassClientStateMachine.isEmpty(new byte[] { 1 })).isFalse(); assertThat(mBassClientStateMachine.isPendingRemove(invalidSourceId)).isFalse(); } @Test public void parseScanRecord_withoutBaseData_makesNoStopScanOffloadFalse() { byte[] scanRecord = new byte[]{ 0x02, 0x01, 0x1a, // advertising flags 0x05, 0x02, 0x0b, 0x11, 0x0a, 0x11, // 16 bit service uuids 0x04, 0x09, 0x50, 0x65, 0x64, // name 0x02, 0x0A, (byte) 0xec, // tx power level 0x05, 0x16, 0x0b, 0x11, 0x50, 0x64, // service data 0x05, (byte) 0xff, (byte) 0xe0, 0x00, 0x02, 0x15, // manufacturer specific data 0x03, 0x50, 0x01, 0x02, // an unknown data type won't cause trouble }; ScanRecord data = ScanRecord.parseFromBytes(scanRecord); mBassClientStateMachine.mNoStopScanOffload = true; mBassClientStateMachine.parseScanRecord(0, data); assertThat(mBassClientStateMachine.mNoStopScanOffload).isFalse(); } @Test public void parseScanRecord_withBaseData_callsUpdateBase() { byte[] scanRecordWithBaseData = new byte[] { 0x02, 0x01, 0x1a, // advertising flags 0x05, 0x02, 0x51, 0x18, 0x0a, 0x11, // 16 bit service uuids 0x04, 0x09, 0x50, 0x65, 0x64, // name 0x02, 0x0A, (byte) 0xec, // tx power level 0x15, 0x16, 0x51, 0x18, // service data (base data with 18 bytes) // LEVEL 1 (byte) 0x01, (byte) 0x02, (byte) 0x03, // presentationDelay (byte) 0x01, // numSubGroups // LEVEL 2 (byte) 0x01, // numSubGroups (byte) 0xFE, // UNKNOWN_CODEC (byte) 0x02, // codecConfigLength (byte) 0x01, (byte) 'A', // codecConfigInfo (byte) 0x03, // metaDataLength (byte) 0x06, (byte) 0x07, (byte) 0x08, // metaData // LEVEL 3 (byte) 0x04, // index (byte) 0x03, // codecConfigLength (byte) 0x02, (byte) 'B', (byte) 'C', // codecConfigInfo 0x05, (byte) 0xff, (byte) 0xe0, 0x00, 0x02, 0x15, // manufacturer specific data 0x03, 0x50, 0x01, 0x02, // an unknown data type won't cause trouble }; ScanRecord data = ScanRecord.parseFromBytes(scanRecordWithBaseData); assertThat(data.getServiceUuids()).contains(BassConstants.BASIC_AUDIO_UUID); assertThat(data.getServiceData(BassConstants.BASIC_AUDIO_UUID)).isNotNull(); mBassClientStateMachine.parseScanRecord(0, data); verify(mBassClientService).updateBase(anyInt(), any()); } private <T> void sendMessageAndVerifyTransition(Message msg, Class<T> type) { Mockito.clearInvocations(mBassClientService); mBassClientStateMachine.sendMessage(msg); Loading @@ -348,7 +461,6 @@ public class BassClientStateMachineTest { Assert.assertThat(mBassClientStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type)); } // It simulates GATT connection for testing. public static class StubBassClientStateMachine extends BassClientStateMachine { boolean mShouldAllowGatt = true; Loading Loading
android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +6 −40 Original line number Diff line number Diff line Loading @@ -152,7 +152,8 @@ public class BassClientStateMachine extends StateMachine { private final Connecting mConnecting = new Connecting(); private final Disconnecting mDisconnecting = new Disconnecting(); private final ConnectedProcessing mConnectedProcessing = new ConnectedProcessing(); private final List<BluetoothGattCharacteristic> mBroadcastCharacteristics = @VisibleForTesting final List<BluetoothGattCharacteristic> mBroadcastCharacteristics = new ArrayList<BluetoothGattCharacteristic>(); @VisibleForTesting BluetoothDevice mDevice; Loading Loading @@ -181,7 +182,8 @@ public class BassClientStateMachine extends StateMachine { // Psync and PAST interfaces private PeriodicAdvertisingManager mPeriodicAdvManager; private boolean mAutoTriggered = false; private boolean mNoStopScanOffload = false; @VisibleForTesting boolean mNoStopScanOffload = false; private boolean mDefNoPAS = false; private boolean mForceSB = false; private int mBroadcastSourceIdLength = 3; Loading Loading @@ -559,7 +561,8 @@ public class BassClientStateMachine extends StateMachine { mService.getCallbacks().notifyReceiveStateChanged(mDevice, sourceId, state); } private static boolean isEmpty(final byte[] data) { @VisibleForTesting static boolean isEmpty(final byte[] data) { return IntStream.range(0, data.length).parallel().allMatch(i -> data[i] == 0); } Loading Loading @@ -1231,18 +1234,6 @@ public class BassClientStateMachine extends StateMachine { } } private byte[] bluetoothAddressToBytes(String s) { log("BluetoothAddressToBytes: input string:" + s); String[] splits = s.split(":"); byte[] addressBytes = new byte[6]; for (int i = 0; i < 6; i++) { int hexValue = Integer.parseInt(splits[i], 16); log("hexValue:" + hexValue); addressBytes[i] = (byte) hexValue; } return addressBytes; } private static int getBisSyncFromChannelPreference( List<BluetoothLeBroadcastChannel> channels) { int bisSync = 0; Loading Loading @@ -1392,15 +1383,6 @@ public class BassClientStateMachine extends StateMachine { return res; } private byte[] convertAsciitoValues(byte[] val) { byte[] ret = new byte[val.length]; for (int i = 0; i < val.length; i++) { ret[i] = (byte) (val[i] - (byte) '0'); } log("convertAsciitoValues: returns:" + Arrays.toString(val)); return ret; } private byte[] convertRecvStateToSetBroadcastCodeByteArray( BluetoothLeBroadcastReceiveState recvState) { byte[] res = new byte[BassConstants.PIN_CODE_CMD_LEN]; Loading Loading @@ -1990,22 +1972,6 @@ public class BassClientStateMachine extends StateMachine { return Integer.toString(what); } private static String profileStateToString(int state) { switch (state) { case BluetoothProfile.STATE_DISCONNECTED: return "DISCONNECTED"; case BluetoothProfile.STATE_CONNECTING: return "CONNECTING"; case BluetoothProfile.STATE_CONNECTED: return "CONNECTED"; case BluetoothProfile.STATE_DISCONNECTING: return "DISCONNECTING"; default: break; } return Integer.toString(state); } /** * Dump info */ Loading
android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +124 −12 Original line number Diff line number Diff line Loading @@ -18,11 +18,18 @@ package com.android.bluetooth.bass_client; import static android.bluetooth.BluetoothGatt.GATT_SUCCESS; import static com.android.bluetooth.bass_client.BassClientStateMachine.CONNECT; import static com.android.bluetooth.bass_client.BassClientStateMachine.CONNECT_TIMEOUT; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.after; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -31,7 +38,10 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.bluetooth.le.PeriodicAdvertisingManager; import android.bluetooth.le.ScanRecord; import android.content.Intent; import android.os.Bundle; import android.os.HandlerThread; Loading @@ -43,8 +53,6 @@ import androidx.test.filters.MediumTest; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import static com.google.common.truth.Truth.assertThat; import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; Loading @@ -59,6 +67,8 @@ import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; import java.util.UUID; @MediumTest Loading Loading @@ -134,7 +144,7 @@ public class BassClientStateMachineTest { allowConnectGatt(true); // Inject an event for when incoming connection is requested mBassClientStateMachine.sendMessage(BassClientStateMachine.CONNECT); mBassClientStateMachine.sendMessage(CONNECT); // Verify that no connection state broadcast is executed verify(mBassClientService, after(WAIT_MS).never()).sendBroadcast(any(Intent.class), Loading @@ -151,7 +161,7 @@ public class BassClientStateMachineTest { allowConnectGatt(false); // Inject an event for when incoming connection is requested mBassClientStateMachine.sendMessage(BassClientStateMachine.CONNECT); mBassClientStateMachine.sendMessage(CONNECT); // Verify that no connection state broadcast is executed verify(mBassClientService, after(WAIT_MS).never()).sendBroadcast(any(Intent.class), Loading @@ -169,7 +179,7 @@ public class BassClientStateMachineTest { allowConnectGatt(true); // Inject an event for when incoming connection is requested mBassClientStateMachine.sendMessage(BassClientStateMachine.CONNECT); mBassClientStateMachine.sendMessage(CONNECT); // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); Loading Loading @@ -201,7 +211,7 @@ public class BassClientStateMachineTest { allowConnectGatt(true); // Inject an event for when incoming connection is requested mBassClientStateMachine.sendMessage(BassClientStateMachine.CONNECT); mBassClientStateMachine.sendMessage(CONNECT); // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); Loading Loading @@ -234,7 +244,7 @@ public class BassClientStateMachineTest { // disconnected -> connecting ---timeout---> disconnected sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT_TIMEOUT), Loading @@ -242,7 +252,7 @@ public class BassClientStateMachineTest { // disconnected -> connecting ---DISCONNECT---> disconnected sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.DISCONNECT), Loading @@ -251,7 +261,7 @@ public class BassClientStateMachineTest { // disconnected -> connecting ---CONNECTION_STATE_CHANGED(connected)---> connected --> // disconnected sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage( Loading @@ -266,7 +276,7 @@ public class BassClientStateMachineTest { // disconnected -> connecting ---CONNECTION_STATE_CHANGED(non-connected) --> disconnected sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage( Loading @@ -276,7 +286,7 @@ public class BassClientStateMachineTest { // change default state to connected for the next tests sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT), mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage( Loading Loading @@ -338,6 +348,109 @@ public class BassClientStateMachineTest { BassClientStateMachine.Connected.class); } @Test public void acquireAllBassChars() { BassClientStateMachine.BluetoothGattTestableWrapper btGatt = Mockito.mock( BassClientStateMachine.BluetoothGattTestableWrapper.class); mBassClientStateMachine.mBluetoothGatt = btGatt; // Do nothing when mBluetoothGatt.getService returns null mBassClientStateMachine.acquireAllBassChars(); BluetoothGattService gattService = Mockito.mock(BluetoothGattService.class); when(btGatt.getService(BassConstants.BASS_UUID)).thenReturn(gattService); List<BluetoothGattCharacteristic> characteristics = new ArrayList<>(); BluetoothGattCharacteristic scanControlPoint = new BluetoothGattCharacteristic( BassConstants.BASS_BCAST_AUDIO_SCAN_CTRL_POINT, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ); characteristics.add(scanControlPoint); BluetoothGattCharacteristic bassCharacteristic = new BluetoothGattCharacteristic( UUID.randomUUID(), BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ); characteristics.add(bassCharacteristic); when(gattService.getCharacteristics()).thenReturn(characteristics); mBassClientStateMachine.acquireAllBassChars(); assertThat(mBassClientStateMachine.mBroadcastScanControlPoint).isEqualTo(scanControlPoint); assertThat(mBassClientStateMachine.mBroadcastCharacteristics).contains(bassCharacteristic); } @Test public void simpleMethods() { // dump() shouldn't crash StringBuilder sb = new StringBuilder(); mBassClientStateMachine.dump(sb); // log() shouldn't crash String msg = "test-log-message"; mBassClientStateMachine.log(msg); // messageWhatToString() shouldn't crash for (int i = CONNECT; i <= CONNECT_TIMEOUT + 1; ++i) { mBassClientStateMachine.messageWhatToString(i); } final int invalidSourceId = -100; assertThat(mBassClientStateMachine.getCurrentBroadcastMetadata(invalidSourceId)).isNull(); assertThat(mBassClientStateMachine.getDevice()).isEqualTo(mTestDevice); assertThat(mBassClientStateMachine.hasPendingSourceOperation()).isFalse(); assertThat(mBassClientStateMachine.isEmpty(new byte[] { 0 })).isTrue(); assertThat(mBassClientStateMachine.isEmpty(new byte[] { 1 })).isFalse(); assertThat(mBassClientStateMachine.isPendingRemove(invalidSourceId)).isFalse(); } @Test public void parseScanRecord_withoutBaseData_makesNoStopScanOffloadFalse() { byte[] scanRecord = new byte[]{ 0x02, 0x01, 0x1a, // advertising flags 0x05, 0x02, 0x0b, 0x11, 0x0a, 0x11, // 16 bit service uuids 0x04, 0x09, 0x50, 0x65, 0x64, // name 0x02, 0x0A, (byte) 0xec, // tx power level 0x05, 0x16, 0x0b, 0x11, 0x50, 0x64, // service data 0x05, (byte) 0xff, (byte) 0xe0, 0x00, 0x02, 0x15, // manufacturer specific data 0x03, 0x50, 0x01, 0x02, // an unknown data type won't cause trouble }; ScanRecord data = ScanRecord.parseFromBytes(scanRecord); mBassClientStateMachine.mNoStopScanOffload = true; mBassClientStateMachine.parseScanRecord(0, data); assertThat(mBassClientStateMachine.mNoStopScanOffload).isFalse(); } @Test public void parseScanRecord_withBaseData_callsUpdateBase() { byte[] scanRecordWithBaseData = new byte[] { 0x02, 0x01, 0x1a, // advertising flags 0x05, 0x02, 0x51, 0x18, 0x0a, 0x11, // 16 bit service uuids 0x04, 0x09, 0x50, 0x65, 0x64, // name 0x02, 0x0A, (byte) 0xec, // tx power level 0x15, 0x16, 0x51, 0x18, // service data (base data with 18 bytes) // LEVEL 1 (byte) 0x01, (byte) 0x02, (byte) 0x03, // presentationDelay (byte) 0x01, // numSubGroups // LEVEL 2 (byte) 0x01, // numSubGroups (byte) 0xFE, // UNKNOWN_CODEC (byte) 0x02, // codecConfigLength (byte) 0x01, (byte) 'A', // codecConfigInfo (byte) 0x03, // metaDataLength (byte) 0x06, (byte) 0x07, (byte) 0x08, // metaData // LEVEL 3 (byte) 0x04, // index (byte) 0x03, // codecConfigLength (byte) 0x02, (byte) 'B', (byte) 'C', // codecConfigInfo 0x05, (byte) 0xff, (byte) 0xe0, 0x00, 0x02, 0x15, // manufacturer specific data 0x03, 0x50, 0x01, 0x02, // an unknown data type won't cause trouble }; ScanRecord data = ScanRecord.parseFromBytes(scanRecordWithBaseData); assertThat(data.getServiceUuids()).contains(BassConstants.BASIC_AUDIO_UUID); assertThat(data.getServiceData(BassConstants.BASIC_AUDIO_UUID)).isNotNull(); mBassClientStateMachine.parseScanRecord(0, data); verify(mBassClientService).updateBase(anyInt(), any()); } private <T> void sendMessageAndVerifyTransition(Message msg, Class<T> type) { Mockito.clearInvocations(mBassClientService); mBassClientStateMachine.sendMessage(msg); Loading @@ -348,7 +461,6 @@ public class BassClientStateMachineTest { Assert.assertThat(mBassClientStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type)); } // It simulates GATT connection for testing. public static class StubBassClientStateMachine extends BassClientStateMachine { boolean mShouldAllowGatt = true; Loading