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

Commit fad5b715 authored by Grzegorz Kołodziejczyk's avatar Grzegorz Kołodziejczyk
Browse files

bass: Monitor LE Audio unicast source when managed

Assistant should notify about its activity when sink device has its
localy managed external source in receive state. Activity callback is
used to keep monitoring of unicast source streaming activity. Monitoring
source activity let unicast have knowledge about being in handover mode.

Bug: 360051130
Bug: 378661060
Test: atest LeAudioServiceTest
Test: atest BassClientServiceTest
Flag: com.android.bluetooth.flags.leaudio_monitor_unicast_source_when_managed_by_broadcast_delegator
Change-Id: I555e8a8027c14df57e8278afdcf896ad8ee386b6
parent dbbf7f0c
Loading
Loading
Loading
Loading
+36 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static com.android.bluetooth.flags.Flags.leaudioBroadcastApiGetLocalMetad
import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastExtractPeriodicScannerFromStateMachine;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastResyncHelper;
import static com.android.bluetooth.flags.Flags.leaudioMonitorUnicastSourceWhenManagedByBroadcastDelegator;
import static com.android.bluetooth.flags.Flags.leaudioSortScansToSyncByFails;

import android.annotation.RequiresPermission;
@@ -1173,8 +1174,12 @@ public class BassClientService extends ProfileService {
            return;
        }

        boolean isAssistantActive =
                areReceiversReceivingOnlyExternalBroadcast(getConnectedDevices());
        boolean isAssistantActive;
        if (leaudioMonitorUnicastSourceWhenManagedByBroadcastDelegator()) {
            isAssistantActive = hasPrimaryDeviceManagedExternalBroadcast();
        } else {
            isAssistantActive = areReceiversReceivingOnlyExternalBroadcast(getConnectedDevices());
        }

        if (isAssistantActive) {
            /* Assistant become active */
@@ -4042,6 +4047,35 @@ public class BassClientService extends ProfileService {
        return false;
    }

    public boolean hasPrimaryDeviceManagedExternalBroadcast() {
        LeAudioService leAudioService = mServiceFactory.getLeAudioService();

        if (leAudioService == null) {
            Log.e(TAG, "no LeAudioService");
            return false;
        }

        for (BluetoothDevice device : getConnectedDevices()) {
            if (!leAudioService.isPrimaryDevice(device)) {
                continue;
            }

            Map<Integer, BluetoothLeBroadcastMetadata> entry = mBroadcastMetadataMap.get(device);

            /* null means that this source was not added or modified by assistant */
            if (entry == null) {
                continue;
            }

            /* Assistant manages some external broadcast */
            if (entry.values().stream().anyMatch(e -> !isLocalBroadcast(e))) {
                return true;
            }
        }

        return false;
    }

    /** Check if any sink receivers are receiving broadcast stream */
    public boolean areReceiversReceivingOnlyExternalBroadcast(List<BluetoothDevice> devices) {
        boolean isReceivingExternalBroadcast = false;
+8 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static com.android.bluetooth.flags.Flags.leaudioAllowedContextMask;
import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastApiManagePrimaryGroup;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment;
import static com.android.bluetooth.flags.Flags.leaudioMonitorUnicastSourceWhenManagedByBroadcastDelegator;
import static com.android.bluetooth.flags.Flags.leaudioUseAudioModeListener;
import static com.android.modules.utils.build.SdkLevel.isAtLeastU;

@@ -1570,8 +1571,14 @@ public class LeAudioService extends ProfileService {
            return false;
        }

        if (leaudioMonitorUnicastSourceWhenManagedByBroadcastDelegator()) {
            return (descriptor.mGroupId == mUnicastGroupIdDeactivatedForBroadcastTransition)
                    || device.equals(mActiveAudioInDevice)
                    || device.equals(mActiveAudioOutDevice);
        } else {
            return descriptor.mGroupId == mUnicastGroupIdDeactivatedForBroadcastTransition;
        }
    }

    /** Return true if group is primary - is active or was active before switch to broadcast */
    public boolean isPrimaryGroup(int groupId) {
+8 −1
Original line number Diff line number Diff line
@@ -559,6 +559,9 @@ public class BassClientServiceTest {
                injectRemoteSourceStateRemoval(sm, TEST_SOURCE_ID + 1);
            }
        }

        doReturn(true).when(mLeAudioService).isPrimaryDevice(mCurrentDevice);
        doReturn(true).when(mLeAudioService).isPrimaryDevice(mCurrentDevice1);
    }

    private void startSearchingForSources() {
@@ -1576,6 +1579,9 @@ public class BassClientServiceTest {
                .getCallbacks()
                .notifySourceAdded(
                        sm.getDevice(), recvState, BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);
        mBassClientService
                .getCallbacks()
                .notifyReceiveStateChanged(sm.getDevice(), recvState.getSourceId(), recvState);
        TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper());

        return recvState;
@@ -1945,7 +1951,6 @@ public class BassClientServiceTest {
                            : BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED,
                    null,
                    (long) 0x00000001);
            verify(mLeAudioService).activeBroadcastAssistantNotification(eq(true));
        }

        // Remove broadcast source
@@ -1971,6 +1976,8 @@ public class BassClientServiceTest {
        for (BassClientStateMachine sm : mStateMachines.values()) {
            injectRemoteSourceStateRemoval(sm, TEST_SOURCE_ID);
        }

        verify(mLeAudioService).activeBroadcastAssistantNotification(eq(false));
    }

    private void verifyRemoveMessageAndInjectSourceRemoval() {