Loading android/app/src/com/android/bluetooth/bass_client/BassClientService.java +21 −16 Original line number Original line Diff line number Diff line Loading @@ -3363,12 +3363,16 @@ public class BassClientService extends ProfileService { return isReceivingExternalBroadcast; return isReceivingExternalBroadcast; } } /** Get the active broadcast sink devices receiving broadcast stream */ /** Get sink devices synced to the broadcasts */ public List<BluetoothDevice> getActiveBroadcastSinks() { public List<BluetoothDevice> getSyncedBroadcastSinks() { List<BluetoothDevice> activeSinks = new ArrayList<>(); List<BluetoothDevice> activeSinks = new ArrayList<>(); for (BluetoothDevice device : getConnectedDevices()) { for (BluetoothDevice device : getConnectedDevices()) { // Check if any device's source in active sync state if (leaudioBigDependsOnAudioState()) { if (!getAllSources(device).isEmpty()) { activeSinks.add(device); } } else { if (getAllSources(device).stream() if (getAllSources(device).stream() .anyMatch( .anyMatch( receiveState -> receiveState -> Loading @@ -3384,6 +3388,7 @@ public class BassClientService extends ProfileService { activeSinks.add(device); activeSinks.add(device); } } } } } return activeSinks; return activeSinks; } } Loading android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -4333,7 +4333,7 @@ public class LeAudioService extends ProfileService { BassClientService bassClientService = getBassClientService(); BassClientService bassClientService = getBassClientService(); if (bassClientService != null) { if (bassClientService != null) { activeBroadcastSinks = bassClientService.getActiveBroadcastSinks(); activeBroadcastSinks = bassClientService.getSyncedBroadcastSinks(); } } if (activeBroadcastSinks.isEmpty()) { if (activeBroadcastSinks.isEmpty()) { Loading android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +64 −8 Original line number Original line Diff line number Diff line Loading @@ -4047,7 +4047,7 @@ public class BassClientServiceTest { // Verify isAnyReceiverReceivingBroadcast returns false if no BIS synced // Verify isAnyReceiverReceivingBroadcast returns false if no BIS synced assertThat(mBassClientService.isAnyReceiverReceivingBroadcast(devices)).isFalse(); assertThat(mBassClientService.isAnyReceiverReceivingBroadcast(devices)).isFalse(); // Update receiver state with lost BIS sync // Update receiver state with BIS sync for (BassClientStateMachine sm : mStateMachines.values()) { for (BassClientStateMachine sm : mStateMachines.values()) { if (sm.getDevice().equals(mCurrentDevice)) { if (sm.getDevice().equals(mCurrentDevice)) { injectRemoteSourceStateChanged( injectRemoteSourceStateChanged( Loading Loading @@ -4084,12 +4084,28 @@ public class BassClientServiceTest { } } @Test @Test public void testGetActiveBroadcastSinks() { public void testGetSyncedBroadcastSinks() { prepareConnectedDeviceGroup(); prepareConnectedDeviceGroup(); startSearchingForSources(); startSearchingForSources(); onScanResult(mSourceDevice, TEST_BROADCAST_ID); onScanResult(mSourceDevice, TEST_BROADCAST_ID); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); BluetoothLeBroadcastMetadata.Builder builder = new BluetoothLeBroadcastMetadata.Builder() .setEncrypted(false) .setSourceDevice( mBluetoothAdapter.getRemoteLeDevice( "00:00:00:00:00:00", BluetoothDevice.ADDRESS_TYPE_RANDOM), BluetoothDevice.ADDRESS_TYPE_RANDOM) .setSourceAdvertisingSid(TEST_ADVERTISER_SID) .setBroadcastId(0) .setBroadcastCode(null) .setPaSyncInterval(TEST_PA_SYNC_INTERVAL) .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS); // builder expect at least one subgroup builder.addSubgroup(createBroadcastSubgroup()); BluetoothLeBroadcastMetadata metaNoBroadcast = builder.build(); verifyAddSourceForGroup(meta); verifyAddSourceForGroup(meta); for (BassClientStateMachine sm : mStateMachines.values()) { for (BassClientStateMachine sm : mStateMachines.values()) { if (sm.getDevice().equals(mCurrentDevice)) { if (sm.getDevice().equals(mCurrentDevice)) { Loading @@ -4105,7 +4121,7 @@ public class BassClientServiceTest { null); null); injectRemoteSourceStateChanged( injectRemoteSourceStateChanged( sm, sm, meta, metaNoBroadcast, TEST_SOURCE_ID, TEST_SOURCE_ID, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, meta.isEncrypted() meta.isEncrypted() Loading @@ -4125,6 +4141,38 @@ public class BassClientServiceTest { : BluetoothLeBroadcastReceiveState : BluetoothLeBroadcastReceiveState .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null); null); injectRemoteSourceStateChanged( sm, metaNoBroadcast, TEST_SOURCE_ID + 1, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, meta.isEncrypted() ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING : BluetoothLeBroadcastReceiveState .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null, (long) 0x00000000); } } // Verify getSyncedBroadcastSinks returns empty device list if no broadcst ID assertThat(mBassClientService.getSyncedBroadcastSinks().isEmpty()).isTrue(); // Update receiver state with broadcast ID for (BassClientStateMachine sm : mStateMachines.values()) { if (sm.getDevice().equals(mCurrentDevice)) { injectRemoteSourceStateChanged( sm, meta, TEST_SOURCE_ID, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, meta.isEncrypted() ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING : BluetoothLeBroadcastReceiveState .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null, (long) 0x00000000); } else if (sm.getDevice().equals(mCurrentDevice1)) { injectRemoteSourceStateChanged( injectRemoteSourceStateChanged( sm, sm, meta, meta, Loading @@ -4139,10 +4187,18 @@ public class BassClientServiceTest { } } } } // Verify isAnyReceiverReceivingBroadcast returns empty device list if no BIS synced List<BluetoothDevice> activeSinks = mBassClientService.getSyncedBroadcastSinks(); assertThat(mBassClientService.getActiveBroadcastSinks().isEmpty()).isTrue(); if (Flags.leaudioBigDependsOnAudioState()) { // Verify getSyncedBroadcastSinks returns correct device list if no BIS synced assertThat(activeSinks.size()).isEqualTo(2); assertThat(activeSinks.contains(mCurrentDevice)).isTrue(); assertThat(activeSinks.contains(mCurrentDevice1)).isTrue(); } else { // Verify getSyncedBroadcastSinks returns empty device list if no BIS synced assertThat(mBassClientService.getSyncedBroadcastSinks().isEmpty()).isTrue(); } // Update receiver state with lost BIS sync // Update receiver state with BIS sync for (BassClientStateMachine sm : mStateMachines.values()) { for (BassClientStateMachine sm : mStateMachines.values()) { if (sm.getDevice().equals(mCurrentDevice)) { if (sm.getDevice().equals(mCurrentDevice)) { injectRemoteSourceStateChanged( injectRemoteSourceStateChanged( Loading Loading @@ -4170,9 +4226,9 @@ public class BassClientServiceTest { (long) 0x00000002); (long) 0x00000002); } } } } List<BluetoothDevice> activeSinks = mBassClientService.getActiveBroadcastSinks(); // Verify isAnyReceiverReceivingBroadcast returns correct device list if BIS synced // Verify getSyncedBroadcastSinks returns correct device list if BIS synced activeSinks = mBassClientService.getSyncedBroadcastSinks(); assertThat(activeSinks.size()).isEqualTo(2); assertThat(activeSinks.size()).isEqualTo(2); assertThat(activeSinks.contains(mCurrentDevice)).isTrue(); assertThat(activeSinks.contains(mCurrentDevice)).isTrue(); assertThat(activeSinks.contains(mCurrentDevice1)).isTrue(); assertThat(activeSinks.contains(mCurrentDevice1)).isTrue(); Loading android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +4 −4 Original line number Original line Diff line number Diff line Loading @@ -2677,16 +2677,16 @@ public class LeAudioServiceTest { eq(null), any(), any(BluetoothProfileConnectionInfo.class)); eq(null), any(), any(BluetoothProfileConnectionInfo.class)); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); // Verify setGroupVolume will not be called if no active sinks // Verify setGroupVolume will not be called if no synced sinks doReturn(new ArrayList<>()).when(mBassClientService).getActiveBroadcastSinks(); doReturn(new ArrayList<>()).when(mBassClientService).getSyncedBroadcastSinks(); mService.setVolume(newVolume); mService.setVolume(newVolume); verify(mVolumeControlService, never()).setGroupVolume(groupId, newVolume); verify(mVolumeControlService, never()).setGroupVolume(groupId, newVolume); mService.mUnicastGroupIdDeactivatedForBroadcastTransition = groupId; mService.mUnicastGroupIdDeactivatedForBroadcastTransition = groupId; // Verify setGroupVolume will be called if active sinks // Verify setGroupVolume will be called if synced sinks doReturn(List.of(mLeftDevice, mRightDevice, mSingleDevice)) doReturn(List.of(mLeftDevice, mRightDevice, mSingleDevice)) .when(mBassClientService) .when(mBassClientService) .getActiveBroadcastSinks(); .getSyncedBroadcastSinks(); mService.setVolume(newVolume); mService.setVolume(newVolume); // Verify set volume only on primary group // Verify set volume only on primary group Loading Loading
android/app/src/com/android/bluetooth/bass_client/BassClientService.java +21 −16 Original line number Original line Diff line number Diff line Loading @@ -3363,12 +3363,16 @@ public class BassClientService extends ProfileService { return isReceivingExternalBroadcast; return isReceivingExternalBroadcast; } } /** Get the active broadcast sink devices receiving broadcast stream */ /** Get sink devices synced to the broadcasts */ public List<BluetoothDevice> getActiveBroadcastSinks() { public List<BluetoothDevice> getSyncedBroadcastSinks() { List<BluetoothDevice> activeSinks = new ArrayList<>(); List<BluetoothDevice> activeSinks = new ArrayList<>(); for (BluetoothDevice device : getConnectedDevices()) { for (BluetoothDevice device : getConnectedDevices()) { // Check if any device's source in active sync state if (leaudioBigDependsOnAudioState()) { if (!getAllSources(device).isEmpty()) { activeSinks.add(device); } } else { if (getAllSources(device).stream() if (getAllSources(device).stream() .anyMatch( .anyMatch( receiveState -> receiveState -> Loading @@ -3384,6 +3388,7 @@ public class BassClientService extends ProfileService { activeSinks.add(device); activeSinks.add(device); } } } } } return activeSinks; return activeSinks; } } Loading
android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -4333,7 +4333,7 @@ public class LeAudioService extends ProfileService { BassClientService bassClientService = getBassClientService(); BassClientService bassClientService = getBassClientService(); if (bassClientService != null) { if (bassClientService != null) { activeBroadcastSinks = bassClientService.getActiveBroadcastSinks(); activeBroadcastSinks = bassClientService.getSyncedBroadcastSinks(); } } if (activeBroadcastSinks.isEmpty()) { if (activeBroadcastSinks.isEmpty()) { Loading
android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +64 −8 Original line number Original line Diff line number Diff line Loading @@ -4047,7 +4047,7 @@ public class BassClientServiceTest { // Verify isAnyReceiverReceivingBroadcast returns false if no BIS synced // Verify isAnyReceiverReceivingBroadcast returns false if no BIS synced assertThat(mBassClientService.isAnyReceiverReceivingBroadcast(devices)).isFalse(); assertThat(mBassClientService.isAnyReceiverReceivingBroadcast(devices)).isFalse(); // Update receiver state with lost BIS sync // Update receiver state with BIS sync for (BassClientStateMachine sm : mStateMachines.values()) { for (BassClientStateMachine sm : mStateMachines.values()) { if (sm.getDevice().equals(mCurrentDevice)) { if (sm.getDevice().equals(mCurrentDevice)) { injectRemoteSourceStateChanged( injectRemoteSourceStateChanged( Loading Loading @@ -4084,12 +4084,28 @@ public class BassClientServiceTest { } } @Test @Test public void testGetActiveBroadcastSinks() { public void testGetSyncedBroadcastSinks() { prepareConnectedDeviceGroup(); prepareConnectedDeviceGroup(); startSearchingForSources(); startSearchingForSources(); onScanResult(mSourceDevice, TEST_BROADCAST_ID); onScanResult(mSourceDevice, TEST_BROADCAST_ID); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); BluetoothLeBroadcastMetadata.Builder builder = new BluetoothLeBroadcastMetadata.Builder() .setEncrypted(false) .setSourceDevice( mBluetoothAdapter.getRemoteLeDevice( "00:00:00:00:00:00", BluetoothDevice.ADDRESS_TYPE_RANDOM), BluetoothDevice.ADDRESS_TYPE_RANDOM) .setSourceAdvertisingSid(TEST_ADVERTISER_SID) .setBroadcastId(0) .setBroadcastCode(null) .setPaSyncInterval(TEST_PA_SYNC_INTERVAL) .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS); // builder expect at least one subgroup builder.addSubgroup(createBroadcastSubgroup()); BluetoothLeBroadcastMetadata metaNoBroadcast = builder.build(); verifyAddSourceForGroup(meta); verifyAddSourceForGroup(meta); for (BassClientStateMachine sm : mStateMachines.values()) { for (BassClientStateMachine sm : mStateMachines.values()) { if (sm.getDevice().equals(mCurrentDevice)) { if (sm.getDevice().equals(mCurrentDevice)) { Loading @@ -4105,7 +4121,7 @@ public class BassClientServiceTest { null); null); injectRemoteSourceStateChanged( injectRemoteSourceStateChanged( sm, sm, meta, metaNoBroadcast, TEST_SOURCE_ID, TEST_SOURCE_ID, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, meta.isEncrypted() meta.isEncrypted() Loading @@ -4125,6 +4141,38 @@ public class BassClientServiceTest { : BluetoothLeBroadcastReceiveState : BluetoothLeBroadcastReceiveState .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null); null); injectRemoteSourceStateChanged( sm, metaNoBroadcast, TEST_SOURCE_ID + 1, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, meta.isEncrypted() ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING : BluetoothLeBroadcastReceiveState .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null, (long) 0x00000000); } } // Verify getSyncedBroadcastSinks returns empty device list if no broadcst ID assertThat(mBassClientService.getSyncedBroadcastSinks().isEmpty()).isTrue(); // Update receiver state with broadcast ID for (BassClientStateMachine sm : mStateMachines.values()) { if (sm.getDevice().equals(mCurrentDevice)) { injectRemoteSourceStateChanged( sm, meta, TEST_SOURCE_ID, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, meta.isEncrypted() ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING : BluetoothLeBroadcastReceiveState .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, null, (long) 0x00000000); } else if (sm.getDevice().equals(mCurrentDevice1)) { injectRemoteSourceStateChanged( injectRemoteSourceStateChanged( sm, sm, meta, meta, Loading @@ -4139,10 +4187,18 @@ public class BassClientServiceTest { } } } } // Verify isAnyReceiverReceivingBroadcast returns empty device list if no BIS synced List<BluetoothDevice> activeSinks = mBassClientService.getSyncedBroadcastSinks(); assertThat(mBassClientService.getActiveBroadcastSinks().isEmpty()).isTrue(); if (Flags.leaudioBigDependsOnAudioState()) { // Verify getSyncedBroadcastSinks returns correct device list if no BIS synced assertThat(activeSinks.size()).isEqualTo(2); assertThat(activeSinks.contains(mCurrentDevice)).isTrue(); assertThat(activeSinks.contains(mCurrentDevice1)).isTrue(); } else { // Verify getSyncedBroadcastSinks returns empty device list if no BIS synced assertThat(mBassClientService.getSyncedBroadcastSinks().isEmpty()).isTrue(); } // Update receiver state with lost BIS sync // Update receiver state with BIS sync for (BassClientStateMachine sm : mStateMachines.values()) { for (BassClientStateMachine sm : mStateMachines.values()) { if (sm.getDevice().equals(mCurrentDevice)) { if (sm.getDevice().equals(mCurrentDevice)) { injectRemoteSourceStateChanged( injectRemoteSourceStateChanged( Loading Loading @@ -4170,9 +4226,9 @@ public class BassClientServiceTest { (long) 0x00000002); (long) 0x00000002); } } } } List<BluetoothDevice> activeSinks = mBassClientService.getActiveBroadcastSinks(); // Verify isAnyReceiverReceivingBroadcast returns correct device list if BIS synced // Verify getSyncedBroadcastSinks returns correct device list if BIS synced activeSinks = mBassClientService.getSyncedBroadcastSinks(); assertThat(activeSinks.size()).isEqualTo(2); assertThat(activeSinks.size()).isEqualTo(2); assertThat(activeSinks.contains(mCurrentDevice)).isTrue(); assertThat(activeSinks.contains(mCurrentDevice)).isTrue(); assertThat(activeSinks.contains(mCurrentDevice1)).isTrue(); assertThat(activeSinks.contains(mCurrentDevice1)).isTrue(); Loading
android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +4 −4 Original line number Original line Diff line number Diff line Loading @@ -2677,16 +2677,16 @@ public class LeAudioServiceTest { eq(null), any(), any(BluetoothProfileConnectionInfo.class)); eq(null), any(), any(BluetoothProfileConnectionInfo.class)); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); // Verify setGroupVolume will not be called if no active sinks // Verify setGroupVolume will not be called if no synced sinks doReturn(new ArrayList<>()).when(mBassClientService).getActiveBroadcastSinks(); doReturn(new ArrayList<>()).when(mBassClientService).getSyncedBroadcastSinks(); mService.setVolume(newVolume); mService.setVolume(newVolume); verify(mVolumeControlService, never()).setGroupVolume(groupId, newVolume); verify(mVolumeControlService, never()).setGroupVolume(groupId, newVolume); mService.mUnicastGroupIdDeactivatedForBroadcastTransition = groupId; mService.mUnicastGroupIdDeactivatedForBroadcastTransition = groupId; // Verify setGroupVolume will be called if active sinks // Verify setGroupVolume will be called if synced sinks doReturn(List.of(mLeftDevice, mRightDevice, mSingleDevice)) doReturn(List.of(mLeftDevice, mRightDevice, mSingleDevice)) .when(mBassClientService) .when(mBassClientService) .getActiveBroadcastSinks(); .getSyncedBroadcastSinks(); mService.setVolume(newVolume); mService.setVolume(newVolume); // Verify set volume only on primary group // Verify set volume only on primary group Loading