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

Commit 6346e790 authored by Michal Belusiak's avatar Michal Belusiak Committed by Automerger Merge Worker
Browse files

BASS: Notify of broadcaster on PeriodicAdv and on BIGInfo am: 01abfd92 am: 6e9e512a

parents cc1723f4 6e9e512a
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -1957,6 +1957,39 @@ public class BassClientService extends ProfileService {
                    }
                }
            }

            if (leaudioBigDependsOnAudioState()) {
                BluetoothDevice srcDevice = getDeviceForSyncHandle(syncHandle);
                if (srcDevice == null) {
                    log("No device found.");
                    return;
                }
                PeriodicAdvertisementResult result =
                        getPeriodicAdvertisementResult(
                                srcDevice, getBroadcastIdForSyncHandle(syncHandle));
                if (result == null) {
                    log("No PA record found");
                    return;
                }
                BaseData baseData = getBase(syncHandle);
                if (baseData == null) {
                    log("No BaseData found");
                    return;
                }
                PublicBroadcastData pbData = result.getPublicBroadcastData();
                if (pbData == null) {
                    log("No public broadcast data found, wait for BIG");
                    return;
                }
                if (!result.isNotified()) {
                    result.setNotified(true);
                    BluetoothLeBroadcastMetadata metaData =
                            getBroadcastMetadataFromBaseData(
                                    baseData, srcDevice, syncHandle, pbData.isEncrypted());
                    log("Notify broadcast source found");
                    mCallbacks.notifySourceFound(metaData);
                }
            }
        }

        @Override
+353 −9
Original line number Diff line number Diff line
@@ -4651,7 +4651,9 @@ public class BassClientServiceTest {
                .isEqualTo(TEST_BROADCAST_ID);
        assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null);

        if (!Flags.leaudioBigDependsOnAudioState()) {
            callback.onBigInfoAdvertisingReport(TEST_SYNC_HANDLE, true);
        }

        // Notified
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());
@@ -4665,6 +4667,8 @@ public class BassClientServiceTest {
        }
        Assert.assertEquals(TEST_RSSI, metaData.getValue().getRssi());

        // Any of them should not notified second time
        callback.onPeriodicAdvertisingReport(report);
        callback.onBigInfoAdvertisingReport(TEST_SYNC_HANDLE, true);

        // Not notified second time
@@ -4676,6 +4680,179 @@ public class BassClientServiceTest {
        }
    }

    @Test
    public void notifySourceFound_without_public_announcement() {
        mSetFlagsRule.enableFlags(
                Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE);
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS);
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE);

        prepareConnectedDeviceGroup();
        startSearchingForSources();

        byte[] broadcastScanRecord =
                new byte[] {
                    0x02,
                    0x01,
                    0x1a, // advertising flags
                    0x05,
                    0x02,
                    0x52,
                    0x18,
                    0x0a,
                    0x11, // 16 bit service uuids
                    0x04,
                    0x09,
                    0x50,
                    0x65,
                    0x64, // name
                    0x02,
                    0x0A,
                    (byte) 0xec, // tx power level
                    0x05,
                    0x30,
                    0x54,
                    0x65,
                    0x73,
                    0x74, // broadcast name: Test
                    0x06,
                    0x16,
                    0x52,
                    0x18,
                    (byte) TEST_BROADCAST_ID,
                    (byte) (TEST_BROADCAST_ID >> 8),
                    (byte) (TEST_BROADCAST_ID >> 16), // service data, broadcast id
                    0x05,
                    (byte) 0xff,
                    (byte) 0xe0,
                    0x00,
                    0x02,
                    0x15, // manufacturer specific data
                    0x03,
                    0x50,
                    0x01,
                    0x02, // an unknown data type won't cause trouble
                };
        ScanResult scanResult =
                new ScanResult(
                        mSourceDevice,
                        0,
                        0,
                        0,
                        0,
                        0,
                        TEST_RSSI,
                        0,
                        ScanRecord.parseFromBytes(broadcastScanRecord),
                        0);

        mCallbackCaptor.getValue().onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
        onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE);
        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);
        assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null);

        byte[] scanRecord =
                new byte[] {
                    (byte) 0x02,
                    (byte) 0x01,
                    (byte) 0x1a, // advertising flags
                    (byte) 0x05,
                    (byte) 0x02,
                    (byte) 0x51,
                    (byte) 0x18,
                    (byte) 0x0a,
                    (byte) 0x11, // 16 bit service uuids
                    (byte) 0x04,
                    (byte) 0x09,
                    (byte) 0x50,
                    (byte) 0x65,
                    (byte) 0x64, // name
                    (byte) 0x02,
                    (byte) 0x0A,
                    (byte) 0xec, // tx power level
                    (byte) 0x19,
                    (byte) 0x16,
                    (byte) 0x51,
                    (byte) 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) 0x00,
                    (byte) 0x00,
                    (byte) 0x00,
                    (byte) 0x00,
                    (byte) 0x00, // 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
                    (byte) 0x05,
                    (byte) 0xff,
                    (byte) 0xe0,
                    (byte) 0x00,
                    (byte) 0x02,
                    (byte) 0x15, // manufacturer specific data
                    (byte) 0x03,
                    (byte) 0x50,
                    (byte) 0x01,
                    (byte) 0x02, // an unknown data type won't cause trouble
                };
        PeriodicAdvertisingReport report =
                new PeriodicAdvertisingReport(
                        TEST_SYNC_HANDLE, 0, 0, 0, ScanRecord.parseFromBytes(scanRecord));
        BassClientService.PACallback callback = mBassClientService.new PACallback();

        // No public announcement so it will not notify
        callback.onPeriodicAdvertisingReport(report);

        // Not canceled, updated base
        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);
        assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null);

        // Not notified
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());
        InOrder inOrder = inOrder(mCallback);
        try {
            inOrder.verify(mCallback, never()).onSourceFound(any());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        // onBigInfoAdvertisingReport causes notification
        callback.onBigInfoAdvertisingReport(TEST_SYNC_HANDLE, true);

        // Notified
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());
        try {
            inOrder.verify(mCallback).onSourceFound(any());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @Test
    public void notifySourceFound_periodic_after_big() {
        mSetFlagsRule.enableFlags(
@@ -4781,8 +4958,167 @@ public class BassClientServiceTest {
                .isEqualTo(TEST_BROADCAST_ID);
        assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null);

        // Next big report, should notified
        if (!Flags.leaudioBigDependsOnAudioState()) {
            // onBigInfoAdvertisingReport causes notification
            callback.onBigInfoAdvertisingReport(TEST_SYNC_HANDLE, true);
        }

        // Notified
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());
        try {
            inOrder.verify(mCallback).onSourceFound(any());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @Test
    public void notifySourceFound_periodic_after_wrong_periodic() {
        mSetFlagsRule.enableFlags(
                Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE);
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS);
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE);

        prepareConnectedDeviceGroup();
        startSearchingForSources();
        onScanResult(mSourceDevice, TEST_BROADCAST_ID);
        onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE);
        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);
        assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null);

        byte[] scanRecordNoBaseData =
                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
                };

        byte[] scanRecordOk =
                new byte[] {
                    (byte) 0x02,
                    (byte) 0x01,
                    (byte) 0x1a, // advertising flags
                    (byte) 0x05,
                    (byte) 0x02,
                    (byte) 0x51,
                    (byte) 0x18,
                    (byte) 0x0a,
                    (byte) 0x11, // 16 bit service uuids
                    (byte) 0x04,
                    (byte) 0x09,
                    (byte) 0x50,
                    (byte) 0x65,
                    (byte) 0x64, // name
                    (byte) 0x02,
                    (byte) 0x0A,
                    (byte) 0xec, // tx power level
                    (byte) 0x19,
                    (byte) 0x16,
                    (byte) 0x51,
                    (byte) 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) 0x00,
                    (byte) 0x00,
                    (byte) 0x00,
                    (byte) 0x00,
                    (byte) 0x00, // 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
                    (byte) 0x05,
                    (byte) 0xff,
                    (byte) 0xe0,
                    (byte) 0x00,
                    (byte) 0x02,
                    (byte) 0x15, // manufacturer specific data
                    (byte) 0x03,
                    (byte) 0x50,
                    (byte) 0x01,
                    (byte) 0x02, // an unknown data type won't cause trouble
                };

        BassClientService.PACallback callback = mBassClientService.new PACallback();

        PeriodicAdvertisingReport report =
                new PeriodicAdvertisingReport(
                        TEST_SYNC_HANDLE, 0, 0, 0, ScanRecord.parseFromBytes(scanRecordNoBaseData));

        // Wrong base data not cause notification
        callback.onPeriodicAdvertisingReport(report);

        // Not notified
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());
        InOrder inOrder = inOrder(mCallback);
        try {
            inOrder.verify(mCallback, never()).onSourceFound(any());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        report =
                new PeriodicAdvertisingReport(
                        TEST_SYNC_HANDLE, 0, 0, 0, ScanRecord.parseFromBytes(scanRecordOk));
        callback.onPeriodicAdvertisingReport(report);

        // Not canceled, updated base
        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);
        assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null);

        // Notified
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());
@@ -4870,9 +5206,12 @@ public class BassClientServiceTest {
                new PeriodicAdvertisingReport(
                        TEST_SYNC_HANDLE, 0, 0, 0, ScanRecord.parseFromBytes(scanRecord));
        BassClientService.PACallback callback = mBassClientService.new PACallback();
        // onBigInfoAdvertisingReport causes notification
        callback.onPeriodicAdvertisingReport(report);
        if (!Flags.leaudioBigDependsOnAudioState()) {
            // onBigInfoAdvertisingReport causes notification
            callback.onBigInfoAdvertisingReport(TEST_SYNC_HANDLE, true);
        }

        // Notified
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());
        InOrder inOrder = inOrder(mCallback);
@@ -4893,9 +5232,12 @@ public class BassClientServiceTest {
        // Source synced
        onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE);

        // onBigInfoAdvertisingReport causes notification
        callback.onPeriodicAdvertisingReport(report);
        if (!Flags.leaudioBigDependsOnAudioState()) {
            // onBigInfoAdvertisingReport causes notification
            callback.onBigInfoAdvertisingReport(TEST_SYNC_HANDLE, true);
        }

        // Notified
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());
        try {
@@ -4907,9 +5249,11 @@ public class BassClientServiceTest {
        // Start searching again clears timeout, mCachedBroadcasts and notifiedFlags but keep syncs
        startSearchingForSources();

        // onBigInfoAdvertisingReport should notified again
        callback.onPeriodicAdvertisingReport(report);
        if (!Flags.leaudioBigDependsOnAudioState()) {
            // onBigInfoAdvertisingReport should notified again
            callback.onBigInfoAdvertisingReport(TEST_SYNC_HANDLE, true);
        }
        // Notified
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());
        try {