Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e98c97f2 authored by Michal Belusiak's avatar Michal Belusiak
Browse files

BASS: Remove old broadcaster when new synced on the same syncHandle

In case when onSyncEstablished (new broadcaster) came before
onSyncLost (old broadcaster) on the same syncHandle, properly
handle retrieve broadcast ID and remove the old one with notification.

When onSyncLost came, the new broadcaster will be removed but on next
onScanResult will be added again. On the controller nothing change as
on native it is still synced. Such operation is seamless for the user.

Bug: 342552854
Bug: 333691526
Test: atest BassClientServiceTest
Change-Id: I222f35b813132840871088e4ef15fa0cd2f9d15b
parent 361aeb61
Loading
Loading
Loading
Loading
+41 −14
Original line number Diff line number Diff line
@@ -285,10 +285,6 @@ public class BassClientService extends ProfileService {
        log("updatePeriodicAdvertisementResultMap: broadcastName: " + broadcastName);
        log("mSyncHandleToDeviceMap" + mSyncHandleToDeviceMap);
        log("mPeriodicAdvertisementResultMap" + mPeriodicAdvertisementResultMap);
        // Cache the SyncHandle and source device
        if (mSyncHandleToDeviceMap != null && syncHandle != BassConstants.INVALID_SYNC_HANDLE) {
            mSyncHandleToDeviceMap.put(syncHandle, device);
        }
        if (mPeriodicAdvertisementResultMap != null) {
            HashMap<Integer, PeriodicAdvertisementResult> paResMap =
                    mPeriodicAdvertisementResultMap.get(device);
@@ -314,6 +310,33 @@ public class BassClientService extends ProfileService {
                log("PAResmap: update >>>");
                if (bId == BassConstants.INVALID_BROADCAST_ID) {
                    // Update when onSyncEstablished, try to retrieve valid broadcast id
                    if (leaudioBroadcastExtractPeriodicScannerFromStateMachine()) {
                        bId = getBroadcastIdForSyncHandle(BassConstants.INVALID_SYNC_HANDLE);

                        if (bId == BassConstants.INVALID_BROADCAST_ID
                                || !paResMap.containsKey(bId)) {
                            Log.e(TAG, "PAResmap: error! no valid broadcast id found>>>");
                            return;
                        }

                        int oldBroadcastId = getBroadcastIdForSyncHandle(syncHandle);
                        if (oldBroadcastId != BassConstants.INVALID_BROADCAST_ID
                                && oldBroadcastId != bId) {
                            log(
                                    "updatePeriodicAdvertisementResultMap: SyncEstablished on the"
                                            + " same syncHandle="
                                            + syncHandle
                                            + ", before syncLost");
                            if (leaudioBroadcastMonitorSourceSyncStatus()) {
                                log(
                                        "Notify broadcast source lost, broadcast id: "
                                                + oldBroadcastId);
                                mCallbacks.notifySourceLost(oldBroadcastId);
                            }
                            clearAllDataForSyncHandle(syncHandle);
                            mCachedBroadcasts.remove(oldBroadcastId);
                        }
                    } else {
                        for (Map.Entry<Integer, PeriodicAdvertisementResult> entry :
                                paResMap.entrySet()) {
                            PeriodicAdvertisementResult value = entry.getValue();
@@ -327,11 +350,15 @@ public class BassClientService extends ProfileService {
                            return;
                        }
                    }
                }
                PeriodicAdvertisementResult paRes = paResMap.get(bId);
                if (advSid != BassConstants.INVALID_ADV_SID) {
                    paRes.updateAdvSid(advSid);
                }
                if (syncHandle != BassConstants.INVALID_SYNC_HANDLE) {
                    if (mSyncHandleToDeviceMap != null) {
                        mSyncHandleToDeviceMap.put(syncHandle, device);
                    }
                    paRes.updateSyncHandle(syncHandle);
                    if (paRes.getBroadcastId() != BassConstants.INVALID_BROADCAST_ID) {
                        // broadcast successfully synced
+133 −19
Original line number Diff line number Diff line
@@ -2989,6 +2989,8 @@ public class BassClientServiceTest {
                        TEST_MAC_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM);

        // mock the update in selectSource
        mBassClientService.updateSyncHandleForBroadcastId(
                BassConstants.INVALID_SYNC_HANDLE, testBroadcastId);
        mBassClientService.updatePeriodicAdvertisementResultMap(
                testDevice,
                testDevice.getAddressType(),
@@ -3029,8 +3031,119 @@ public class BassClientServiceTest {
        assertThat(paResult.isNotified()).isEqualTo(false);
    }

    @Test
    public void testPeriodicAdvertisementResultMap_syncEstablishedOnTheSameSyncHandle() {
        mSetFlagsRule.enableFlags(
                Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE);

        final String testBroadcastName1 = "Test1";
        final String testBroadcastName2 = "Test2";
        final int testSyncHandle = 1;
        final int testBroadcastId1 = 42;
        final int testBroadcastId2 = 43;
        final int testAdvertiserSid1 = 1234;
        final int testAdvertiserSid2 = 2345;
        final int testAdvInterval1 = 100;
        final int testAdvInterval2 = 200;

        BluetoothDevice testDevice =
                mBluetoothAdapter.getRemoteLeDevice(
                        TEST_MAC_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM);

        // mock the update in selectSource
        mBassClientService.updateSyncHandleForBroadcastId(
                BassConstants.INVALID_SYNC_HANDLE, testBroadcastId1);
        mBassClientService.updatePeriodicAdvertisementResultMap(
                testDevice,
                testDevice.getAddressType(),
                BassConstants.INVALID_SYNC_HANDLE,
                BassConstants.INVALID_ADV_SID,
                testAdvInterval1,
                testBroadcastId1,
                null,
                testBroadcastName1);

        // mock the update in onSyncEstablished
        mBassClientService.updatePeriodicAdvertisementResultMap(
                testDevice,
                BassConstants.INVALID_ADV_ADDRESS_TYPE,
                testSyncHandle,
                testAdvertiserSid1,
                BassConstants.INVALID_ADV_INTERVAL,
                BassConstants.INVALID_BROADCAST_ID,
                null,
                null);

        assertThat(mBassClientService.getPeriodicAdvertisementResult(testDevice, testBroadcastId2))
                .isEqualTo(null);
        PeriodicAdvertisementResult paResult =
                mBassClientService.getPeriodicAdvertisementResult(testDevice, testBroadcastId1);
        assertThat(paResult.getAddressType()).isEqualTo(BluetoothDevice.ADDRESS_TYPE_RANDOM);
        assertThat(paResult.getSyncHandle()).isEqualTo(testSyncHandle);
        assertThat(paResult.getAdvSid()).isEqualTo(testAdvertiserSid1);
        assertThat(paResult.getAdvInterval()).isEqualTo(testAdvInterval1);
        assertThat(paResult.getBroadcastName()).isEqualTo(testBroadcastName1);

        // mock the update in selectSource
        mBassClientService.updateSyncHandleForBroadcastId(
                BassConstants.INVALID_SYNC_HANDLE, testBroadcastId2);
        mBassClientService.updatePeriodicAdvertisementResultMap(
                testDevice,
                testDevice.getAddressType(),
                BassConstants.INVALID_SYNC_HANDLE,
                BassConstants.INVALID_ADV_SID,
                testAdvInterval2,
                testBroadcastId2,
                null,
                testBroadcastName2);

        // mock the update in onSyncEstablished
        mBassClientService.updatePeriodicAdvertisementResultMap(
                testDevice,
                BassConstants.INVALID_ADV_ADDRESS_TYPE,
                testSyncHandle,
                testAdvertiserSid2,
                BassConstants.INVALID_ADV_INTERVAL,
                BassConstants.INVALID_BROADCAST_ID,
                null,
                null);

        assertThat(mBassClientService.getPeriodicAdvertisementResult(testDevice, testBroadcastId1))
                .isEqualTo(null);
        paResult = mBassClientService.getPeriodicAdvertisementResult(testDevice, testBroadcastId2);
        assertThat(paResult.getAddressType()).isEqualTo(BluetoothDevice.ADDRESS_TYPE_RANDOM);
        assertThat(paResult.getSyncHandle()).isEqualTo(testSyncHandle);
        assertThat(paResult.getAdvSid()).isEqualTo(testAdvertiserSid2);
        assertThat(paResult.getAdvInterval()).isEqualTo(testAdvInterval2);
        assertThat(paResult.getBroadcastName()).isEqualTo(testBroadcastName2);
    }

    @Test
    public void testSyncHandleToBroadcastIdMap_getSyncHandleAndGetBroadcastId() {
        if (Flags.leaudioBroadcastExtractPeriodicScannerFromStateMachine()) {
            final int testSyncHandle = 1;
            final int testSyncHandleInvalid = 2;
            final int testBroadcastId = 42;
            final int testBroadcastIdInvalid = 43;

            BluetoothDevice testDevice =
                    mBluetoothAdapter.getRemoteLeDevice(
                            TEST_MAC_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM);

            prepareConnectedDeviceGroup();
            startSearchingForSources();
            onScanResult(testDevice, testBroadcastId);
            onSyncEstablished(testDevice, testSyncHandle);

            assertThat(mBassClientService.getSyncHandleForBroadcastId(testBroadcastIdInvalid))
                    .isEqualTo(BassConstants.INVALID_SYNC_HANDLE);
            assertThat(mBassClientService.getBroadcastIdForSyncHandle(testSyncHandleInvalid))
                    .isEqualTo(BassConstants.INVALID_BROADCAST_ID);
            assertThat(mBassClientService.getSyncHandleForBroadcastId(testBroadcastId))
                    .isEqualTo(testSyncHandle);
            assertThat(mBassClientService.getBroadcastIdForSyncHandle(testSyncHandle))
                    .isEqualTo(testBroadcastId);
        } else {
            final String testBroadcastName = "Test";
            final int testSyncHandle = 1;
            final int testSyncHandleInvalid = 2;
@@ -3074,6 +3187,7 @@ public class BassClientServiceTest {
            assertThat(mBassClientService.getBroadcastIdForSyncHandle(testSyncHandle))
                    .isEqualTo(testBroadcastId);
        }
    }

    @Test
    public void testSuspendResumeSourceSynchronization() {