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

Commit 8234b73e authored by Michal Belusiak (xWF)'s avatar Michal Belusiak (xWF) Committed by Gerrit Code Review
Browse files

Merge "Bass: Modify source on duplicate addition" into main

parents 114f3b44 185d7fbe
Loading
Loading
Loading
Loading
+147 −121
Original line number Diff line number Diff line
@@ -1297,9 +1297,9 @@ public class BassClientService extends ProfileService {
        return devices;
    }

    private boolean isValidBroadcastSourceAddition(
    private int checkDuplicateSourceAdditionAndGetSourceId(
            BluetoothDevice device, BluetoothLeBroadcastMetadata metaData) {
        boolean retval = true;
        int sourceId = BassConstants.INVALID_SOURCE_ID;
        List<BluetoothLeBroadcastReceiveState> currentAllSources = getAllSources(device);
        for (int i = 0; i < currentAllSources.size(); i++) {
            BluetoothLeBroadcastReceiveState state = currentAllSources.get(i);
@@ -1307,17 +1307,12 @@ public class BassClientService extends ProfileService {
                    && metaData.getSourceAddressType() == state.getSourceAddressType()
                    && metaData.getSourceAdvertisingSid() == state.getSourceAdvertisingSid()
                    && metaData.getBroadcastId() == state.getBroadcastId()) {
                retval = false;
                Log.e(
                        TAG,
                        "isValidBroadcastSourceAddition: fail for "
                                + device
                                + " metaData: "
                                + metaData);
                sourceId = state.getSourceId();
                log("DuplicatedSourceAddition: for " + device + " metaData: " + metaData);
                break;
            }
        }
        return retval;
        return sourceId;
    }

    private boolean hasRoomForBroadcastSourceAddition(BluetoothDevice device) {
@@ -1512,45 +1507,77 @@ public class BassClientService extends ProfileService {
        }
    }

    private int areValidParametersToModifySource(
            BluetoothLeBroadcastMetadata updatedMetadata,
            BassClientStateMachine stateMachine,
            Integer deviceSourceId,
            BluetoothDevice device) {
        if (updatedMetadata == null || stateMachine == null) {
            log(
                    "areValidParametersToModifySource: Error bad parameters: sourceId = "
                            + deviceSourceId
                            + " updatedMetadata = "
                            + updatedMetadata);
    private int validateParametersForSourceOperation(
            BassClientStateMachine stateMachine, BluetoothDevice device) {
        if (stateMachine == null) {
            log("validateParameters: stateMachine is null for device: " + device);
            return BluetoothStatusCodes.ERROR_BAD_PARAMETERS;
        }
        if (deviceSourceId == BassConstants.INVALID_SOURCE_ID) {
            log("areValidParametersToModifySource: no such sourceId for device: " + device);
            return BluetoothStatusCodes.ERROR_LE_BROADCAST_ASSISTANT_INVALID_SOURCE_ID;
        }

        if (getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
            log("areValidParametersToModifySource: device is not connected");
            log("validateParameters: device is not connected, device: " + device);
            return BluetoothStatusCodes.ERROR_REMOTE_LINK_ERROR;
        }
        byte[] code = updatedMetadata.getBroadcastCode();

        return BluetoothStatusCodes.SUCCESS;
    }

    private int validateParametersForSourceOperation(
            BassClientStateMachine stateMachine,
            BluetoothDevice device,
            BluetoothLeBroadcastMetadata metadata) {
        int status = validateParametersForSourceOperation(stateMachine, device);
        if (status != BluetoothStatusCodes.SUCCESS) {
            return status;
        }

        if (metadata == null) {
            log("validateParameters: metadata is null for device: " + device);
            return BluetoothStatusCodes.ERROR_BAD_PARAMETERS;
        }

        byte[] code = metadata.getBroadcastCode();
        if ((code != null) && (code.length != 0)) {
            if ((code.length > 16) || (code.length < 4)) {
                log(
                        "areValidParametersToModifySource: Invalid broadcast code length: "
                        "validateParameters: Invalid broadcast code length: "
                                + code.length
                                + ", should be between 4 and 16 octets");
                return BluetoothStatusCodes.ERROR_BAD_PARAMETERS;
            }
        }
        if (stateMachine.hasPendingSourceOperation()) {
            Log.w(
                    TAG,
                    "modifySource: source operation already pending, device: "
                            + device
                            + ", broadcastId: "
                            + updatedMetadata.getBroadcastId());
            return BluetoothStatusCodes.ERROR_ALREADY_IN_TARGET_STATE;

        return BluetoothStatusCodes.SUCCESS;
    }

    private int validateParametersForSourceOperation(
            BassClientStateMachine stateMachine, BluetoothDevice device, Integer sourceId) {
        int status = validateParametersForSourceOperation(stateMachine, device);
        if (status != BluetoothStatusCodes.SUCCESS) {
            return status;
        }

        if (sourceId == BassConstants.INVALID_SOURCE_ID) {
            log("validateParameters: no such sourceId for device: " + device);
            return BluetoothStatusCodes.ERROR_LE_BROADCAST_ASSISTANT_INVALID_SOURCE_ID;
        }

        return BluetoothStatusCodes.SUCCESS;
    }

    private int validateParametersForSourceOperation(
            BassClientStateMachine stateMachine,
            BluetoothDevice device,
            BluetoothLeBroadcastMetadata metadata,
            Integer sourceId) {
        int status = validateParametersForSourceOperation(stateMachine, device, metadata);
        if (status != BluetoothStatusCodes.SUCCESS) {
            return status;
        }

        if (sourceId == BassConstants.INVALID_SOURCE_ID) {
            log("validateParameters: no such sourceId for device: " + device);
            return BluetoothStatusCodes.ERROR_LE_BROADCAST_ASSISTANT_INVALID_SOURCE_ID;
        }

        return BluetoothStatusCodes.SUCCESS;
@@ -2942,16 +2969,10 @@ public class BassClientService extends ProfileService {
        byte[] code = sourceMetadata.getBroadcastCode();
        for (BluetoothDevice device : devices) {
            BassClientStateMachine stateMachine = getOrCreateStateMachine(device);
            if (stateMachine == null) {
                log("addSource: Error bad parameter: no state machine for " + device);
                mCallbacks.notifySourceAddFailed(
                        device, sourceMetadata, BluetoothStatusCodes.ERROR_BAD_PARAMETERS);
                continue;
            }
            if (getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
                log("addSource: device is not connected");
                mCallbacks.notifySourceAddFailed(
                        device, sourceMetadata, BluetoothStatusCodes.ERROR_REMOTE_LINK_ERROR);
            int statusCode =
                    validateParametersForSourceOperation(stateMachine, device, sourceMetadata);
            if (statusCode != BluetoothStatusCodes.SUCCESS) {
                mCallbacks.notifySourceAddFailed(device, sourceMetadata, statusCode);
                continue;
            }
            if (stateMachine.hasPendingSourceOperation()) {
@@ -2965,12 +2986,19 @@ public class BassClientService extends ProfileService {
                        device, sourceMetadata, BluetoothStatusCodes.ERROR_ALREADY_IN_TARGET_STATE);
                continue;
            }
            if (leaudioBroadcastResyncHelper()) {
                int sourceId = checkDuplicateSourceAdditionAndGetSourceId(device, sourceMetadata);
                if (sourceId != BassConstants.INVALID_SOURCE_ID) {
                    updateSourceToResumeBroadcast(device, sourceId, sourceMetadata);
                    continue;
                }
            }
            if (!hasRoomForBroadcastSourceAddition(device)) {
                log("addSource: device has no room");
                Integer sourceId = getSourceIdToRemove(device);
                if (sourceId != BassConstants.INVALID_SOURCE_ID) {
                Integer sourceIdToRemove = getSourceIdToRemove(device);
                if (sourceIdToRemove != BassConstants.INVALID_SOURCE_ID) {
                    BluetoothLeBroadcastMetadata metaData =
                            stateMachine.getCurrentBroadcastMetadata(sourceId);
                            stateMachine.getCurrentBroadcastMetadata(sourceIdToRemove);
                    if (metaData != null) {
                        // Add host intentional pause if previous broadcast is different than
                        // current
@@ -2983,7 +3011,7 @@ public class BassClientService extends ProfileService {
                            TAG,
                            "Switch Broadcast Source: "
                                    + ("device: " + device)
                                    + (", old SourceId: " + sourceId)
                                    + (", old SourceId: " + sourceIdToRemove)
                                    + (", new broadcastId: " + sourceMetadata.getBroadcastId())
                                    + (", new broadcastName: "
                                            + sourceMetadata.getBroadcastName()));
@@ -2993,7 +3021,9 @@ public class BassClientService extends ProfileService {
                        // mark group op for both remove and add source
                        // so setSourceGroupManaged will be updated accordingly in callbacks
                        enqueueSourceGroupOp(
                                device, BassClientStateMachine.REMOVE_BCAST_SOURCE, sourceId);
                                device,
                                BassClientStateMachine.REMOVE_BCAST_SOURCE,
                                sourceIdToRemove);
                        enqueueSourceGroupOp(
                                device, BassClientStateMachine.ADD_BCAST_SOURCE, sourceMetadata);
                    }
@@ -3004,7 +3034,7 @@ public class BassClientService extends ProfileService {
                    Message message =
                            stateMachine.obtainMessage(BassClientStateMachine.SWITCH_BCAST_SOURCE);
                    message.obj = sourceMetadata;
                    message.arg1 = sourceId;
                    message.arg1 = sourceIdToRemove;
                    stateMachine.sendMessage(message);
                } else {
                    mCallbacks.notifySourceAddFailed(
@@ -3014,7 +3044,9 @@ public class BassClientService extends ProfileService {
                }
                continue;
            }
            if (!isValidBroadcastSourceAddition(device, sourceMetadata)) {
            if (!leaudioBroadcastResyncHelper()) {
                int sourceId = checkDuplicateSourceAdditionAndGetSourceId(device, sourceMetadata);
                if (sourceId != BassConstants.INVALID_SOURCE_ID) {
                    log("addSource: not a valid broadcast source addition");
                    mCallbacks.notifySourceAddFailed(
                            device,
@@ -3022,16 +3054,6 @@ public class BassClientService extends ProfileService {
                            BluetoothStatusCodes.ERROR_LE_BROADCAST_ASSISTANT_DUPLICATE_ADDITION);
                    continue;
                }
            if ((code != null) && (code.length != 0)) {
                if ((code.length > 16) || (code.length < 4)) {
                    log(
                            "Invalid broadcast code length: "
                                    + code.length
                                    + ", should be between 4 and 16 octets");
                    mCallbacks.notifySourceAddFailed(
                            device, sourceMetadata, BluetoothStatusCodes.ERROR_BAD_PARAMETERS);
                    continue;
                }
            }

            /* Store metadata for sink device */
@@ -3106,14 +3128,24 @@ public class BassClientService extends ProfileService {
            BluetoothDevice device = deviceSourceIdPair.getKey();
            Integer deviceSourceId = deviceSourceIdPair.getValue();
            BassClientStateMachine stateMachine = getOrCreateStateMachine(device);

            int statusCode =
                    areValidParametersToModifySource(
                            updatedMetadata, stateMachine, deviceSourceId, device);
                    validateParametersForSourceOperation(
                            stateMachine, device, updatedMetadata, deviceSourceId);
            if (statusCode != BluetoothStatusCodes.SUCCESS) {
                mCallbacks.notifySourceModifyFailed(device, sourceId, statusCode);
                continue;
            }
            if (stateMachine.hasPendingSourceOperation()) {
                Log.w(
                        TAG,
                        "modifySource: source operation already pending, device: "
                                + device
                                + ", broadcastId: "
                                + updatedMetadata.getBroadcastId());
                mCallbacks.notifySourceModifyFailed(
                        device, sourceId, BluetoothStatusCodes.ERROR_ALREADY_IN_TARGET_STATE);
                continue;
            }

            sEventLogger.logd(
                    TAG,
@@ -3158,32 +3190,17 @@ 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();
            Integer deviceSourceId = deviceSourceIdPair.getValue();
            BassClientStateMachine stateMachine = getOrCreateStateMachine(device);

            /* Removes metadata for sink device if not paused */
            if (!mPausedBroadcastSinks.contains(device)) {
                mBroadcastMetadataMap.remove(device);
            }

            if (stateMachine == null) {
                log("removeSource: Error bad parameters: device = " + device);
                mCallbacks.notifySourceRemoveFailed(
                        device, sourceId, BluetoothStatusCodes.ERROR_BAD_PARAMETERS);
                continue;
            }
            if (deviceSourceId == BassConstants.INVALID_SOURCE_ID) {
                log("removeSource: no such sourceId for device: " + device);
                mCallbacks.notifySourceRemoveFailed(
                        device,
                        sourceId,
                        BluetoothStatusCodes.ERROR_LE_BROADCAST_ASSISTANT_INVALID_SOURCE_ID);
                continue;
            }
            if (getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
                log("removeSource: device is not connected");
                mCallbacks.notifySourceRemoveFailed(
                        device, sourceId, BluetoothStatusCodes.ERROR_REMOTE_LINK_ERROR);
            Integer deviceSourceId = deviceSourceIdPair.getValue();
            BassClientStateMachine stateMachine = getOrCreateStateMachine(device);
            int statusCode =
                    validateParametersForSourceOperation(stateMachine, device, deviceSourceId);
            if (statusCode != BluetoothStatusCodes.SUCCESS) {
                mCallbacks.notifySourceRemoveFailed(device, sourceId, statusCode);
                continue;
            }

@@ -3796,15 +3813,45 @@ public class BassClientService extends ProfileService {
                                || activeSyncedSrc.contains(
                                        getSyncHandleForBroadcastId(metadata.getBroadcastId())))) {
                    int sourceId = receiveState.get().getSourceId();
                    int statusCode =
                            areValidParametersToModifySource(
                                    metadata, stateMachine, sourceId, sink);

                    if (statusCode != BluetoothStatusCodes.SUCCESS) {
                        mCallbacks.notifySourceModifyFailed(sink, sourceId, statusCode);
                    updateSourceToResumeBroadcast(sink, sourceId, metadata);
                } else {
                    addSource(sink, metadata, false);
                }
            } else {
                if (metadata != null) {
                    mPausedBroadcastIds.remove(metadata.getBroadcastId());
                    addSource(sink, metadata, false);
                } else {
                    Log.w(
                            TAG,
                            "resumeReceiversSourceSynchronization: failed to get metadata to"
                                    + " resume sink: "
                                    + sink);
                }
            }
            // remove the device from mPausedBroadcastSinks
            iterator.remove();
                        continue;
        }

        logPausedBroadcastsAndSinks();
    }

    private void updateSourceToResumeBroadcast(
            BluetoothDevice sink, int sourceId, BluetoothLeBroadcastMetadata metadata) {
        BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);
        int statusCode =
                validateParametersForSourceOperation(stateMachine, sink, metadata, sourceId);
        if (statusCode != BluetoothStatusCodes.SUCCESS) {
            return;
        }
        if (stateMachine.hasPendingSourceOperation()) {
            Log.w(
                    TAG,
                    "updateSourceToResumeBroadcast: source operation already pending, device: "
                            + sink
                            + ", broadcastId: "
                            + metadata.getBroadcastId());
            return;
        }

        sEventLogger.logd(
@@ -3814,8 +3861,7 @@ public class BassClientService extends ProfileService {
                        + (", sourceId: " + sourceId)
                        + (", updatedBroadcastId: " + metadata.getBroadcastId())
                        + (", updatedBroadcastName: " + metadata.getBroadcastName()));
                    Message message =
                            stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);
        Message message = stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);
        message.arg1 = sourceId;
        message.arg2 =
                DeviceConfig.getBoolean(
@@ -3826,26 +3872,6 @@ public class BassClientService extends ProfileService {
                        : BassConstants.PA_SYNC_PAST_AVAILABLE;
        message.obj = metadata;
        stateMachine.sendMessage(message);
                } else {
                    addSource(sink, metadata, false);
                }
            } else {
                if (metadata != null) {
                    mPausedBroadcastIds.remove(metadata.getBroadcastId());
                    addSource(sink, metadata, false);
                } else {
                    Log.w(
                            TAG,
                            "resumeReceiversSourceSynchronization: failed to get metadata to"
                                    + " resume sink: "
                                    + sink);
                }
            }
            // remove the device from mPausedBroadcastSinks
            iterator.remove();
        }

        logPausedBroadcastsAndSinks();
    }

    /** Handle Unicast source stream status change */
+3 −1
Original line number Diff line number Diff line
@@ -1916,7 +1916,7 @@ class BassClientStateMachine extends StateMachine {
        res[offset++] = (byte) numSubGroups;

        for (int i = 0; i < numSubGroups; i++) {
            int bisIndexValue = existingState.getBisSyncState().get(i).intValue();
            int bisIndexValue = 0xFFFFFFFF;
            if (paSync == BassConstants.PA_SYNC_DO_NOT_SYNC) {
                bisIndexValue = 0;
            } else if (metaData != null
@@ -1929,6 +1929,8 @@ class BassClientStateMachine extends StateMachine {
                if (bisIndexValue == 0) {
                    bisIndexValue = 0xFFFFFFFF;
                }
            } else if (i < existingState.getBisSyncState().size()) {
                bisIndexValue = existingState.getBisSyncState().get(i).intValue();
            }
            log("UPDATE_BCAST_SOURCE: bisIndexValue : " + bisIndexValue);
            // BIS_Sync