Loading android/app/src/com/android/bluetooth/bass_client/BassClientService.java +43 −12 Original line number Original line Diff line number Diff line Loading @@ -902,6 +902,40 @@ public class BassClientService extends ProfileService { return false; return false; } } private boolean isAnyConnectedDeviceSwitchingSource() { for (BluetoothDevice device : getConnectedDevices()) { synchronized (mStateMachines) { BassClientStateMachine sm = getOrCreateStateMachine(device); // Need to check both mPendingSourceToSwitch and mPendingMetadata // to guard the whole source switching flow if (sm != null && (sm.hasPendingSwitchingSourceOperation() || sm.hasPendingSourceOperation())) { return true; } } } return false; } private void checkAndSetGroupAllowedContextMask(BluetoothDevice sink) { LeAudioService leAudioService = mServiceFactory.getLeAudioService(); if (leAudioService == null) { return; } if (leaudioAllowedContextMask()) { /* Don't bother active group (external broadcaster scenario) with SOUND EFFECTS */ if (!mIsAllowedContextOfActiveGroupModified && isDevicePartOfActiveUnicastGroup(sink)) { leAudioService.setActiveGroupAllowedContextMask( BluetoothLeAudio.CONTEXTS_ALL & ~BluetoothLeAudio.CONTEXT_TYPE_SOUND_EFFECTS, BluetoothLeAudio.CONTEXTS_ALL); mIsAllowedContextOfActiveGroupModified = true; } } } private void checkAndResetGroupAllowedContextMask() { private void checkAndResetGroupAllowedContextMask() { LeAudioService leAudioService = mServiceFactory.getLeAudioService(); LeAudioService leAudioService = mServiceFactory.getLeAudioService(); if (leAudioService == null) { if (leAudioService == null) { Loading @@ -911,7 +945,8 @@ public class BassClientService extends ProfileService { if (leaudioAllowedContextMask()) { if (leaudioAllowedContextMask()) { /* Restore allowed context mask for Unicast */ /* Restore allowed context mask for Unicast */ if (mIsAllowedContextOfActiveGroupModified if (mIsAllowedContextOfActiveGroupModified && !hasAnyConnectedDeviceExternalBroadcastSource()) { && !hasAnyConnectedDeviceExternalBroadcastSource() && !isAnyConnectedDeviceSwitchingSource()) { leAudioService.setActiveGroupAllowedContextMask( leAudioService.setActiveGroupAllowedContextMask( BluetoothLeAudio.CONTEXTS_ALL, BluetoothLeAudio.CONTEXTS_ALL); BluetoothLeAudio.CONTEXTS_ALL, BluetoothLeAudio.CONTEXTS_ALL); mIsAllowedContextOfActiveGroupModified = false; mIsAllowedContextOfActiveGroupModified = false; Loading @@ -935,17 +970,7 @@ public class BassClientService extends ProfileService { leAudioService.activeBroadcastAssistantNotification(true); leAudioService.activeBroadcastAssistantNotification(true); } } if (leaudioAllowedContextMask()) { checkAndSetGroupAllowedContextMask(sink); /* Don't bother active group (external broadcaster scenario) with SOUND EFFECTS */ if (!mIsAllowedContextOfActiveGroupModified && isDevicePartOfActiveUnicastGroup(sink)) { leAudioService.setActiveGroupAllowedContextMask( BluetoothLeAudio.CONTEXTS_ALL & ~BluetoothLeAudio.CONTEXT_TYPE_SOUND_EFFECTS, BluetoothLeAudio.CONTEXTS_ALL); mIsAllowedContextOfActiveGroupModified = true; } } } else { } else { /* Assistant become inactive */ /* Assistant become inactive */ if (mIsAssistantActive && mPausedBroadcastSinks.isEmpty()) { if (mIsAssistantActive && mPausedBroadcastSinks.isEmpty()) { Loading Loading @@ -2608,6 +2633,10 @@ public class BassClientService extends ProfileService { device, BassClientStateMachine.ADD_BCAST_SOURCE, sourceMetadata); device, BassClientStateMachine.ADD_BCAST_SOURCE, sourceMetadata); } } if (!isLocalBroadcast(sourceMetadata)) { checkAndSetGroupAllowedContextMask(device); } sEventLogger.logd( sEventLogger.logd( TAG, TAG, "Add Broadcast Source: " "Add Broadcast Source: " Loading Loading @@ -3552,6 +3581,8 @@ public class BassClientService extends ProfileService { void notifySourceAddFailed( void notifySourceAddFailed( BluetoothDevice sink, BluetoothLeBroadcastMetadata source, int reason) { BluetoothDevice sink, BluetoothLeBroadcastMetadata source, int reason) { sService.checkAndResetGroupAllowedContextMask(); sEventLogger.loge( sEventLogger.loge( TAG, TAG, "notifySourceAddFailed: sink: " "notifySourceAddFailed: sink: " Loading android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +10 −1 Original line number Original line Diff line number Diff line Loading @@ -269,6 +269,10 @@ public class BassClientStateMachine extends StateMachine { } } } } Boolean hasPendingSwitchingSourceOperation() { return mPendingSourceToSwitch != null; } BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) { BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) { return mCurrentMetadata.getOrDefault(sourceId, null); return mCurrentMetadata.getOrDefault(sourceId, null); } } Loading Loading @@ -995,7 +999,6 @@ public class BassClientStateMachine extends StateMachine { Message message = obtainMessage(ADD_BCAST_SOURCE); Message message = obtainMessage(ADD_BCAST_SOURCE); message.obj = mPendingSourceToSwitch; message.obj = mPendingSourceToSwitch; sendMessage(message); sendMessage(message); mPendingSourceToSwitch = null; } else { } else { mService.getCallbacks() mService.getCallbacks() .notifySourceRemoved( .notifySourceRemoved( Loading Loading @@ -2003,6 +2006,12 @@ public class BassClientStateMachine extends StateMachine { .notifySourceAddFailed( .notifySourceAddFailed( mDevice, metaData, BluetoothStatusCodes.ERROR_UNKNOWN); mDevice, metaData, BluetoothStatusCodes.ERROR_UNKNOWN); } } if (mPendingSourceToSwitch != null && mPendingSourceToSwitch.getBroadcastId() == metaData.getBroadcastId()) { // Clear pending source to switch when starting to add this new source mPendingSourceToSwitch = null; } break; break; case UPDATE_BCAST_SOURCE: case UPDATE_BCAST_SOURCE: metaData = (BluetoothLeBroadcastMetadata) message.obj; metaData = (BluetoothLeBroadcastMetadata) message.obj; Loading android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +83 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothLeAudioCodecConfigMetadata; import android.bluetooth.BluetoothLeAudioCodecConfigMetadata; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastAssistant; Loading Loading @@ -2624,6 +2625,88 @@ public class BassClientServiceTest { } } } } @Test public void testAddSourceForExternalBroadcast_triggerSetContextMask() { mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_ALLOWED_CONTEXT_MASK); mSetFlagsRule.enableFlags( Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE); mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_ASSISTANT_PERIPHERAL_ENTRUSTMENT); final int testGroupId = 1; prepareConnectedDeviceGroup(); startSearchingForSources(); onScanResult(mSourceDevice, TEST_BROADCAST_ID); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); /* Fake external broadcast - no Broadcast Metadata from LE Audio service */ doReturn(new ArrayList<BluetoothLeBroadcastMetadata>()) .when(mLeAudioService) .getAllBroadcastMetadata(); doReturn(testGroupId).when(mLeAudioService).getActiveGroupId(); doReturn(new ArrayList<BluetoothDevice>(Arrays.asList(mCurrentDevice))) .when(mLeAudioService) .getActiveDevices(); assertThat(mBassClientService.getActiveSyncedSources().size()).isEqualTo(1); assertThat(mBassClientService.getActiveSyncedSources().contains(TEST_SYNC_HANDLE)).isTrue(); assertThat(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); BluetoothLeBroadcastMetadata.Builder builder = new BluetoothLeBroadcastMetadata.Builder() .setEncrypted(false) .setSourceDevice(mSourceDevice, BluetoothDevice.ADDRESS_TYPE_RANDOM) .setSourceAdvertisingSid(TEST_ADVERTISER_SID) .setBroadcastId(TEST_BROADCAST_ID) .setBroadcastCode(null) .setPaSyncInterval(TEST_PA_SYNC_INTERVAL) .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS); // builder expect at least one subgroup builder.addSubgroup(createBroadcastSubgroup()); BluetoothLeBroadcastMetadata meta = builder.build(); // Add source to unsynced broadcast, causes synchronization first mBassClientService.addSource(mCurrentDevice, meta, true); // Verify setting allowed context mask is triggered verify(mLeAudioService) .setActiveGroupAllowedContextMask( eq( BluetoothLeAudio.CONTEXTS_ALL & ~BluetoothLeAudio.CONTEXT_TYPE_SOUND_EFFECTS), eq(BluetoothLeAudio.CONTEXTS_ALL)); handleHandoverSupport(); // Verify all group members getting ADD_BCAST_SOURCE message assertThat(mStateMachines.size()).isEqualTo(2); for (BassClientStateMachine sm : mStateMachines.values()) { ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(sm, atLeast(1)).sendMessage(messageCaptor.capture()); Message msg = messageCaptor.getAllValues().stream() .filter( m -> (m.what == BassClientStateMachine.ADD_BCAST_SOURCE) && (m.obj == meta)) .findFirst() .orElse(null); assertThat(msg).isNotNull(); } mBassClientService .getCallbacks() .notifySourceAddFailed(mCurrentDevice, meta, BluetoothStatusCodes.ERROR_UNKNOWN); TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); // Verify resetting allowed context mask is triggered when switching source failed verify(mLeAudioService) .setActiveGroupAllowedContextMask( eq(BluetoothLeAudio.CONTEXTS_ALL), eq(BluetoothLeAudio.CONTEXTS_ALL)); } @Test @Test public void testSelectSource_orderOfSyncRegistering() { public void testSelectSource_orderOfSyncRegistering() { mSetFlagsRule.enableFlags( mSetFlagsRule.enableFlags( Loading android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +5 −1 Original line number Original line Diff line number Diff line Loading @@ -907,7 +907,6 @@ public class BassClientStateMachineTest { verify(callbacks) verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); assertThat(mBassClientStateMachine.mPendingSourceToSwitch).isEqualTo(null); } } @Test @Test Loading Loading @@ -1364,6 +1363,9 @@ public class BassClientStateMachineTest { @Test @Test public void sendAddBcastSourceMessage_inConnectedState() { public void sendAddBcastSourceMessage_inConnectedState() { mSetFlagsRule.enableFlags( Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE); initToConnectedState(); initToConnectedState(); BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); Loading @@ -1386,11 +1388,13 @@ public class BassClientStateMachineTest { Mockito.mock(BluetoothGattCharacteristic.class); Mockito.mock(BluetoothGattCharacteristic.class); mBassClientStateMachine.mBroadcastScanControlPoint = scanControlPoint; mBassClientStateMachine.mBroadcastScanControlPoint = scanControlPoint; mBassClientStateMachine.mPendingSourceToSwitch = metadata; sendMessageAndVerifyTransition( sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(ADD_BCAST_SOURCE, metadata), mBassClientStateMachine.obtainMessage(ADD_BCAST_SOURCE, metadata), BassClientStateMachine.ConnectedProcessing.class); BassClientStateMachine.ConnectedProcessing.class); verify(scanControlPoint).setValue(any(byte[].class)); verify(scanControlPoint).setValue(any(byte[].class)); verify(btGatt).writeCharacteristic(any()); verify(btGatt).writeCharacteristic(any()); assertThat(mBassClientStateMachine.mPendingSourceToSwitch).isEqualTo(null); } } @Test @Test Loading Loading
android/app/src/com/android/bluetooth/bass_client/BassClientService.java +43 −12 Original line number Original line Diff line number Diff line Loading @@ -902,6 +902,40 @@ public class BassClientService extends ProfileService { return false; return false; } } private boolean isAnyConnectedDeviceSwitchingSource() { for (BluetoothDevice device : getConnectedDevices()) { synchronized (mStateMachines) { BassClientStateMachine sm = getOrCreateStateMachine(device); // Need to check both mPendingSourceToSwitch and mPendingMetadata // to guard the whole source switching flow if (sm != null && (sm.hasPendingSwitchingSourceOperation() || sm.hasPendingSourceOperation())) { return true; } } } return false; } private void checkAndSetGroupAllowedContextMask(BluetoothDevice sink) { LeAudioService leAudioService = mServiceFactory.getLeAudioService(); if (leAudioService == null) { return; } if (leaudioAllowedContextMask()) { /* Don't bother active group (external broadcaster scenario) with SOUND EFFECTS */ if (!mIsAllowedContextOfActiveGroupModified && isDevicePartOfActiveUnicastGroup(sink)) { leAudioService.setActiveGroupAllowedContextMask( BluetoothLeAudio.CONTEXTS_ALL & ~BluetoothLeAudio.CONTEXT_TYPE_SOUND_EFFECTS, BluetoothLeAudio.CONTEXTS_ALL); mIsAllowedContextOfActiveGroupModified = true; } } } private void checkAndResetGroupAllowedContextMask() { private void checkAndResetGroupAllowedContextMask() { LeAudioService leAudioService = mServiceFactory.getLeAudioService(); LeAudioService leAudioService = mServiceFactory.getLeAudioService(); if (leAudioService == null) { if (leAudioService == null) { Loading @@ -911,7 +945,8 @@ public class BassClientService extends ProfileService { if (leaudioAllowedContextMask()) { if (leaudioAllowedContextMask()) { /* Restore allowed context mask for Unicast */ /* Restore allowed context mask for Unicast */ if (mIsAllowedContextOfActiveGroupModified if (mIsAllowedContextOfActiveGroupModified && !hasAnyConnectedDeviceExternalBroadcastSource()) { && !hasAnyConnectedDeviceExternalBroadcastSource() && !isAnyConnectedDeviceSwitchingSource()) { leAudioService.setActiveGroupAllowedContextMask( leAudioService.setActiveGroupAllowedContextMask( BluetoothLeAudio.CONTEXTS_ALL, BluetoothLeAudio.CONTEXTS_ALL); BluetoothLeAudio.CONTEXTS_ALL, BluetoothLeAudio.CONTEXTS_ALL); mIsAllowedContextOfActiveGroupModified = false; mIsAllowedContextOfActiveGroupModified = false; Loading @@ -935,17 +970,7 @@ public class BassClientService extends ProfileService { leAudioService.activeBroadcastAssistantNotification(true); leAudioService.activeBroadcastAssistantNotification(true); } } if (leaudioAllowedContextMask()) { checkAndSetGroupAllowedContextMask(sink); /* Don't bother active group (external broadcaster scenario) with SOUND EFFECTS */ if (!mIsAllowedContextOfActiveGroupModified && isDevicePartOfActiveUnicastGroup(sink)) { leAudioService.setActiveGroupAllowedContextMask( BluetoothLeAudio.CONTEXTS_ALL & ~BluetoothLeAudio.CONTEXT_TYPE_SOUND_EFFECTS, BluetoothLeAudio.CONTEXTS_ALL); mIsAllowedContextOfActiveGroupModified = true; } } } else { } else { /* Assistant become inactive */ /* Assistant become inactive */ if (mIsAssistantActive && mPausedBroadcastSinks.isEmpty()) { if (mIsAssistantActive && mPausedBroadcastSinks.isEmpty()) { Loading Loading @@ -2608,6 +2633,10 @@ public class BassClientService extends ProfileService { device, BassClientStateMachine.ADD_BCAST_SOURCE, sourceMetadata); device, BassClientStateMachine.ADD_BCAST_SOURCE, sourceMetadata); } } if (!isLocalBroadcast(sourceMetadata)) { checkAndSetGroupAllowedContextMask(device); } sEventLogger.logd( sEventLogger.logd( TAG, TAG, "Add Broadcast Source: " "Add Broadcast Source: " Loading Loading @@ -3552,6 +3581,8 @@ public class BassClientService extends ProfileService { void notifySourceAddFailed( void notifySourceAddFailed( BluetoothDevice sink, BluetoothLeBroadcastMetadata source, int reason) { BluetoothDevice sink, BluetoothLeBroadcastMetadata source, int reason) { sService.checkAndResetGroupAllowedContextMask(); sEventLogger.loge( sEventLogger.loge( TAG, TAG, "notifySourceAddFailed: sink: " "notifySourceAddFailed: sink: " Loading
android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +10 −1 Original line number Original line Diff line number Diff line Loading @@ -269,6 +269,10 @@ public class BassClientStateMachine extends StateMachine { } } } } Boolean hasPendingSwitchingSourceOperation() { return mPendingSourceToSwitch != null; } BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) { BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) { return mCurrentMetadata.getOrDefault(sourceId, null); return mCurrentMetadata.getOrDefault(sourceId, null); } } Loading Loading @@ -995,7 +999,6 @@ public class BassClientStateMachine extends StateMachine { Message message = obtainMessage(ADD_BCAST_SOURCE); Message message = obtainMessage(ADD_BCAST_SOURCE); message.obj = mPendingSourceToSwitch; message.obj = mPendingSourceToSwitch; sendMessage(message); sendMessage(message); mPendingSourceToSwitch = null; } else { } else { mService.getCallbacks() mService.getCallbacks() .notifySourceRemoved( .notifySourceRemoved( Loading Loading @@ -2003,6 +2006,12 @@ public class BassClientStateMachine extends StateMachine { .notifySourceAddFailed( .notifySourceAddFailed( mDevice, metaData, BluetoothStatusCodes.ERROR_UNKNOWN); mDevice, metaData, BluetoothStatusCodes.ERROR_UNKNOWN); } } if (mPendingSourceToSwitch != null && mPendingSourceToSwitch.getBroadcastId() == metaData.getBroadcastId()) { // Clear pending source to switch when starting to add this new source mPendingSourceToSwitch = null; } break; break; case UPDATE_BCAST_SOURCE: case UPDATE_BCAST_SOURCE: metaData = (BluetoothLeBroadcastMetadata) message.obj; metaData = (BluetoothLeBroadcastMetadata) message.obj; Loading
android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +83 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothLeAudioCodecConfigMetadata; import android.bluetooth.BluetoothLeAudioCodecConfigMetadata; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastAssistant; Loading Loading @@ -2624,6 +2625,88 @@ public class BassClientServiceTest { } } } } @Test public void testAddSourceForExternalBroadcast_triggerSetContextMask() { mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_ALLOWED_CONTEXT_MASK); mSetFlagsRule.enableFlags( Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE); mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_ASSISTANT_PERIPHERAL_ENTRUSTMENT); final int testGroupId = 1; prepareConnectedDeviceGroup(); startSearchingForSources(); onScanResult(mSourceDevice, TEST_BROADCAST_ID); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); /* Fake external broadcast - no Broadcast Metadata from LE Audio service */ doReturn(new ArrayList<BluetoothLeBroadcastMetadata>()) .when(mLeAudioService) .getAllBroadcastMetadata(); doReturn(testGroupId).when(mLeAudioService).getActiveGroupId(); doReturn(new ArrayList<BluetoothDevice>(Arrays.asList(mCurrentDevice))) .when(mLeAudioService) .getActiveDevices(); assertThat(mBassClientService.getActiveSyncedSources().size()).isEqualTo(1); assertThat(mBassClientService.getActiveSyncedSources().contains(TEST_SYNC_HANDLE)).isTrue(); assertThat(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); BluetoothLeBroadcastMetadata.Builder builder = new BluetoothLeBroadcastMetadata.Builder() .setEncrypted(false) .setSourceDevice(mSourceDevice, BluetoothDevice.ADDRESS_TYPE_RANDOM) .setSourceAdvertisingSid(TEST_ADVERTISER_SID) .setBroadcastId(TEST_BROADCAST_ID) .setBroadcastCode(null) .setPaSyncInterval(TEST_PA_SYNC_INTERVAL) .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS); // builder expect at least one subgroup builder.addSubgroup(createBroadcastSubgroup()); BluetoothLeBroadcastMetadata meta = builder.build(); // Add source to unsynced broadcast, causes synchronization first mBassClientService.addSource(mCurrentDevice, meta, true); // Verify setting allowed context mask is triggered verify(mLeAudioService) .setActiveGroupAllowedContextMask( eq( BluetoothLeAudio.CONTEXTS_ALL & ~BluetoothLeAudio.CONTEXT_TYPE_SOUND_EFFECTS), eq(BluetoothLeAudio.CONTEXTS_ALL)); handleHandoverSupport(); // Verify all group members getting ADD_BCAST_SOURCE message assertThat(mStateMachines.size()).isEqualTo(2); for (BassClientStateMachine sm : mStateMachines.values()) { ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(sm, atLeast(1)).sendMessage(messageCaptor.capture()); Message msg = messageCaptor.getAllValues().stream() .filter( m -> (m.what == BassClientStateMachine.ADD_BCAST_SOURCE) && (m.obj == meta)) .findFirst() .orElse(null); assertThat(msg).isNotNull(); } mBassClientService .getCallbacks() .notifySourceAddFailed(mCurrentDevice, meta, BluetoothStatusCodes.ERROR_UNKNOWN); TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); // Verify resetting allowed context mask is triggered when switching source failed verify(mLeAudioService) .setActiveGroupAllowedContextMask( eq(BluetoothLeAudio.CONTEXTS_ALL), eq(BluetoothLeAudio.CONTEXTS_ALL)); } @Test @Test public void testSelectSource_orderOfSyncRegistering() { public void testSelectSource_orderOfSyncRegistering() { mSetFlagsRule.enableFlags( mSetFlagsRule.enableFlags( Loading
android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +5 −1 Original line number Original line Diff line number Diff line Loading @@ -907,7 +907,6 @@ public class BassClientStateMachineTest { verify(callbacks) verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); assertThat(mBassClientStateMachine.mPendingSourceToSwitch).isEqualTo(null); } } @Test @Test Loading Loading @@ -1364,6 +1363,9 @@ public class BassClientStateMachineTest { @Test @Test public void sendAddBcastSourceMessage_inConnectedState() { public void sendAddBcastSourceMessage_inConnectedState() { mSetFlagsRule.enableFlags( Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE); initToConnectedState(); initToConnectedState(); BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); Loading @@ -1386,11 +1388,13 @@ public class BassClientStateMachineTest { Mockito.mock(BluetoothGattCharacteristic.class); Mockito.mock(BluetoothGattCharacteristic.class); mBassClientStateMachine.mBroadcastScanControlPoint = scanControlPoint; mBassClientStateMachine.mBroadcastScanControlPoint = scanControlPoint; mBassClientStateMachine.mPendingSourceToSwitch = metadata; sendMessageAndVerifyTransition( sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(ADD_BCAST_SOURCE, metadata), mBassClientStateMachine.obtainMessage(ADD_BCAST_SOURCE, metadata), BassClientStateMachine.ConnectedProcessing.class); BassClientStateMachine.ConnectedProcessing.class); verify(scanControlPoint).setValue(any(byte[].class)); verify(scanControlPoint).setValue(any(byte[].class)); verify(btGatt).writeCharacteristic(any()); verify(btGatt).writeCharacteristic(any()); assertThat(mBassClientStateMachine.mPendingSourceToSwitch).isEqualTo(null); } } @Test @Test Loading