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

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

bass: Add support for multiple sources per sink device

This CL enhances assistant support for sink devices with multiple
receive state entities.

Bug: 360051130
Test: atest BassClientServiceTest
Flag: EXEMPT; no logical change for devices with single entity
Change-Id: I6d2bb7762d6de3a45c13c647b2aa4e5beaf9c2c1
parent 82c51c65
Loading
Loading
Loading
Loading
+168 −80
Original line number Diff line number Diff line
@@ -169,8 +169,8 @@ public class BassClientService extends ProfileService {
    private final Map<BluetoothDevice, List<Integer>> mGroupManagedSources =
            new ConcurrentHashMap<>();
    private final Map<BluetoothDevice, List<Integer>> mActiveSourceMap = new ConcurrentHashMap<>();
    private final Map<BluetoothDevice, BluetoothLeBroadcastMetadata> mBroadcastMetadataMap =
            new ConcurrentHashMap<>();
    private final Map<BluetoothDevice, Map<Integer, BluetoothLeBroadcastMetadata>>
            mBroadcastMetadataMap = new ConcurrentHashMap<>();
    private final HashSet<BluetoothDevice> mPausedBroadcastSinks = new HashSet<>();
    private final Map<BluetoothDevice, Pair<Integer, Integer>> mSinksWaitingForPast =
            new HashMap<>();
@@ -2879,6 +2879,77 @@ public class BassClientService extends ProfileService {
        }
    }

    private void storeSinkMetadata(
            BluetoothDevice device, int broadcastId, BluetoothLeBroadcastMetadata metadata) {
        if (device == null
                || broadcastId == BassConstants.INVALID_BROADCAST_ID
                || metadata == null) {
            Log.e(
                    TAG,
                    "Failed to store Sink Metadata, invalid parameters (device: "
                            + device
                            + ", broadcastId: "
                            + broadcastId
                            + ", metadata: "
                            + metadata
                            + ")");
            return;
        }

        mBroadcastMetadataMap.compute(
                device,
                (key, existingMap) -> {
                    if (existingMap == null) {
                        existingMap = new ConcurrentHashMap<>();
                    }
                    existingMap.put(broadcastId, metadata);
                    return existingMap;
                });
    }

    private void removeSinkMetadata(BluetoothDevice device, int broadcastId) {
        if (device == null || broadcastId == BassConstants.INVALID_BROADCAST_ID) {
            Log.e(
                    TAG,
                    "Failed to remove Sink Metadata, invalid parameters (device: "
                            + device
                            + ", broadcastId: "
                            + broadcastId
                            + ")");
            return;
        }

        mBroadcastMetadataMap.compute(
                device,
                (key, existingMap) -> {
                    if (existingMap != null) {
                        existingMap.remove(broadcastId);
                        if (existingMap.isEmpty()) {
                            return null;
                        }
                    } else {
                        Log.w(
                                TAG,
                                "There is no metadata related to sink (device: "
                                        + device
                                        + ", broadcastId: "
                                        + broadcastId);
                    }
                    return existingMap;
                });
    }

    private void removeSinkMetadata(BluetoothDevice device) {
        if (device == null) {
            Log.e(
                    TAG,
                    "Failed to remove Sink Metadata, invalid parameters (device: " + device + ")");
            return;
        }

        mBroadcastMetadataMap.remove(device);
    }

    /**
     * Add a Broadcast Source to the Broadcast Sink
     *
@@ -3048,7 +3119,7 @@ public class BassClientService extends ProfileService {
                    }

                    /* Store metadata for sink device */
                    mBroadcastMetadataMap.put(device, sourceMetadata);
                    storeSinkMetadata(device, sourceMetadata.getBroadcastId(), sourceMetadata);

                    Message message =
                            stateMachine.obtainMessage(BassClientStateMachine.SWITCH_BCAST_SOURCE);
@@ -3076,7 +3147,7 @@ public class BassClientService extends ProfileService {
            }

            /* Store metadata for sink device */
            mBroadcastMetadataMap.put(device, sourceMetadata);
            storeSinkMetadata(device, sourceMetadata.getBroadcastId(), sourceMetadata);

            if (isGroupOp) {
                enqueueSourceGroupOp(
@@ -3140,7 +3211,7 @@ public class BassClientService extends ProfileService {
        }

        /* Update metadata for sink device */
        mBroadcastMetadataMap.put(sink, updatedMetadata);
        storeSinkMetadata(sink, updatedMetadata.getBroadcastId(), updatedMetadata);

        byte[] code = updatedMetadata.getBroadcastCode();
        for (Map.Entry<BluetoothDevice, Integer> deviceSourceIdPair : devices.entrySet()) {
@@ -3209,16 +3280,13 @@ public class BassClientService extends ProfileService {
        Map<BluetoothDevice, Integer> devices = getGroupManagedDeviceSources(sink, sourceId).second;
        for (Map.Entry<BluetoothDevice, Integer> deviceSourceIdPair : devices.entrySet()) {
            BluetoothDevice device = deviceSourceIdPair.getKey();
            /* Removes metadata for sink device if not paused */
            if (!mPausedBroadcastSinks.contains(device)) {
                mBroadcastMetadataMap.remove(device);
            }

            Integer deviceSourceId = deviceSourceIdPair.getValue();
            BassClientStateMachine stateMachine = getOrCreateStateMachine(device);
            int statusCode =
                    validateParametersForSourceOperation(stateMachine, device, deviceSourceId);
            if (statusCode != BluetoothStatusCodes.SUCCESS) {
                removeSinkMetadata(device);
                mCallbacks.notifySourceRemoveFailed(device, sourceId, statusCode);
                continue;
            }
@@ -3226,6 +3294,15 @@ public class BassClientService extends ProfileService {
            BluetoothLeBroadcastMetadata metaData =
                    stateMachine.getCurrentBroadcastMetadata(sourceId);

            /* Removes metadata for sink device if not paused */
            if (!mPausedBroadcastSinks.contains(device)) {
                if (metaData != null) {
                    removeSinkMetadata(device, metaData.getBroadcastId());
                } else {
                    removeSinkMetadata(device);
                }
            }

            if (metaData != null) {
                stopBigMonitoring(metaData.getBroadcastId(), true);
            }
@@ -3574,7 +3651,7 @@ public class BassClientService extends ProfileService {
                    continue;
                }

                mBroadcastMetadataMap.remove(sink);
                removeSinkMetadata(sink);

                /* Check if there is any other primary device receiving this broadcast */
                if (devices.stream()
@@ -3629,10 +3706,18 @@ public class BassClientService extends ProfileService {

    /** Handle device newly connected and its peer device still has active source */
    private void checkAndResumeBroadcast(BluetoothDevice sink) {
        BluetoothLeBroadcastMetadata metadata = mBroadcastMetadataMap.get(sink);
        Map<Integer, BluetoothLeBroadcastMetadata> entry = mBroadcastMetadataMap.get(sink);

        if (entry == null) {
            Log.d(TAG, "checkAndResumeBroadcast: no entry for device: " + sink + ", available");
            return;
        }

        for (Map.Entry<Integer, BluetoothLeBroadcastMetadata> idMetadataIdPair : entry.entrySet()) {
            BluetoothLeBroadcastMetadata metadata = idMetadataIdPair.getValue();
            if (metadata == null) {
                Log.d(TAG, "checkAndResumeBroadcast: no metadata available");
            return;
                continue;
            }
            for (BluetoothDevice groupDevice : getTargetDeviceList(sink, true)) {
                if (groupDevice.equals(sink)) {
@@ -3654,6 +3739,7 @@ public class BassClientService extends ProfileService {
                }
            }
        }
    }

    private void logPausedBroadcastsAndSinks() {
        log(
@@ -3784,7 +3870,10 @@ public class BassClientService extends ProfileService {
        while (iterator.hasNext()) {
            BluetoothDevice sink = iterator.next();
            sEventLogger.logd(TAG, "Remove broadcast sink from paused cache: " + sink);
            BluetoothLeBroadcastMetadata metadata = mBroadcastMetadataMap.get(sink);
            Map<Integer, BluetoothLeBroadcastMetadata> entry =
                    mBroadcastMetadataMap.getOrDefault(sink, Collections.emptyMap());

            for (BluetoothLeBroadcastMetadata metadata : entry.values()) {

                if (leaudioBroadcastAssistantPeripheralEntrustment()
                        || leaudioBroadcastResyncHelper()) {
@@ -3794,8 +3883,6 @@ public class BassClientService extends ProfileService {
                                "resumeReceiversSourceSynchronization: failed to get metadata to"
                                        + " resume sink: "
                                        + sink);
                    // remove the device from mPausedBroadcastSinks
                    iterator.remove();
                        continue;
                    }

@@ -3817,7 +3904,6 @@ public class BassClientService extends ProfileService {
                                    || receiveState.get().getPaSyncState()
                                            == BluetoothLeBroadcastReceiveState
                                                    .PA_SYNC_STATE_SYNCHRONIZED)) {
                    iterator.remove();
                        continue;
                    }

@@ -3827,7 +3913,8 @@ public class BassClientService extends ProfileService {
                            && (!leaudioBroadcastResyncHelper()
                                    || isLocalBroadcast(metadata)
                                    || activeSyncedSrc.contains(
                                        getSyncHandleForBroadcastId(metadata.getBroadcastId())))) {
                                            getSyncHandleForBroadcastId(
                                                    metadata.getBroadcastId())))) {
                        int sourceId = receiveState.get().getSourceId();
                        updateSourceToResumeBroadcast(sink, sourceId, metadata);
                    } else {
@@ -3845,6 +3932,7 @@ public class BassClientService extends ProfileService {
                                        + sink);
                    }
                }
            }
            // remove the device from mPausedBroadcastSinks
            iterator.remove();
        }