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

Commit c106fbce authored by Grzegorz Kolodziejczyk's avatar Grzegorz Kolodziejczyk Committed by Automerger Merge Worker
Browse files

Merge "le_audio: Handle pause and resume of local broadcast" into main am:...

Merge "le_audio: Handle pause and resume of local broadcast" into main am: 8b0e1160 am: d608b1f7

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2817762



Change-Id: I8902eeab85f5e59a3f843a79ba40baa0593e1620
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 56c0aaa0 d608b1f7
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -90,6 +91,9 @@ public class BassClientService extends ProfileService {
            new ConcurrentHashMap<>();
    private final Map<BluetoothDevice, List<Integer>> mActiveSourceMap = new ConcurrentHashMap<>();
    private final FeatureFlags mFeatureFlags;
    private final Map<BluetoothDevice, BluetoothLeBroadcastMetadata> mBroadcastMetadataMap =
            new ConcurrentHashMap<>();
    private final LinkedList<BluetoothDevice> mPausedBroadcastSinks = new LinkedList<>();

    private HandlerThread mStateMachinesThread;
    private HandlerThread mCallbackHandlerThread;
@@ -424,6 +428,9 @@ public class BassClientService extends ProfileService {
        if (mCachedBroadcasts != null) {
            mCachedBroadcasts.clear();
        }
        if (mBroadcastMetadataMap != null) {
            mBroadcastMetadataMap.clear();
        }
        if (mSyncHandleToBroadcastIdMap != null) {
            mSyncHandleToBroadcastIdMap.clear();
            mSyncHandleToBroadcastIdMap = null;
@@ -1210,6 +1217,9 @@ public class BassClientService extends ProfileService {
            return;
        }

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

        byte[] code = sourceMetadata.getBroadcastCode();
        for (BluetoothDevice device : devices) {
            BassClientStateMachine stateMachine = getOrCreateStateMachine(device);
@@ -1301,6 +1311,9 @@ public class BassClientService extends ProfileService {
            return;
        }

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

        byte[] code = updatedMetadata.getBroadcastCode();
        for (Map.Entry<BluetoothDevice, Integer> deviceSourceIdPair : devices.entrySet()) {
            BluetoothDevice device = deviceSourceIdPair.getKey();
@@ -1379,6 +1392,12 @@ public class BassClientService extends ProfileService {
            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,
@@ -1510,6 +1529,54 @@ public class BassClientService extends ProfileService {
        }
    }

    private void stopLocalSourceReceivers(int broadcastId, boolean store) {
        if (DBG) {
            Log.d(TAG, "stopLocalSourceReceivers()");
        }

        if (store && !mPausedBroadcastSinks.isEmpty()) {
            Log.w(TAG, "stopLocalSourceReceivers(), paused broadcast sinks are replaced");
            mPausedBroadcastSinks.clear();
        }

        for (BluetoothDevice device : getConnectedDevices()) {
            for (BluetoothLeBroadcastReceiveState receiveState : getAllSources(device)) {
                /* Check if local/last broadcast is the synced one */
                if (receiveState.getBroadcastId() != broadcastId) continue;

                removeSource(device, receiveState.getSourceId());

                if (store && !mPausedBroadcastSinks.contains(device)) {
                    mPausedBroadcastSinks.add(device);
                }
            }
        }
    }

    /** Request receivers to suspend broadcast sources synchronization */
    public void suspendReceiversSourceSynchronization(int broadcastId) {
        sEventLogger.logd(DBG, TAG, "Suspend receivers source synchronization: " + broadcastId);
        stopLocalSourceReceivers(broadcastId, true);
    }

    /** Request receivers to stop broadcast sources synchronization and remove them */
    public void stopReceiversSourceSynchronization(int broadcastId) {
        sEventLogger.logd(DBG, TAG, "Stop receivers source synchronization: " + broadcastId);
        stopLocalSourceReceivers(broadcastId, false);
    }

    /** Request receivers to resume broadcast source synchronization */
    public void resumeReceiversSourceSynchronization(int broadcastId) {
        sEventLogger.logd(DBG, TAG, "Resume receivers source synchronization: " + broadcastId);

        while (!mPausedBroadcastSinks.isEmpty()) {
            BluetoothDevice sink = mPausedBroadcastSinks.remove();
            BluetoothLeBroadcastMetadata metadata = mBroadcastMetadataMap.get(sink);

            addSource(sink, metadata, true);
        }
    }

    /**
     * Callback handler
     */
+30 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.csip.CsipSetCoordinatorService;
import com.android.bluetooth.bass_client.BassClientService;
import com.android.bluetooth.flags.FeatureFlags;
import com.android.bluetooth.flags.FeatureFlagsImpl;
import com.android.bluetooth.hap.HapClientService;
@@ -167,6 +168,8 @@ public class LeAudioService extends ProfileService {
    @VisibleForTesting
    CsipSetCoordinatorService mCsipSetCoordinatorService;

    @VisibleForTesting BassClientService mBassClientService;

    @VisibleForTesting
    RemoteCallbackList<IBluetoothLeBroadcastCallback> mBroadcastCallbacks;

@@ -489,6 +492,7 @@ public class LeAudioService extends ProfileService {
        mTbsService = null;
        mVolumeControlService = null;
        mCsipSetCoordinatorService = null;
        mBassClientService = null;

        return true;
    }
@@ -528,6 +532,16 @@ public class LeAudioService extends ProfileService {
        return mVolumeControlService;
    }

    BassClientService getBassClientService() {
        if (mBassClientService == null) {
            mBassClientService = mServiceFactory.getBassClientService();
            if (mBassClientService == null) {
                Log.e(TAG, "BASS service is not available");
            }
        }
        return mBassClientService;
    }

    @VisibleForTesting
    int getAudioDeviceGroupVolume(int groupId) {
        VolumeControlService volumeControlService = getVolumeControlService();
@@ -2543,6 +2557,11 @@ public class LeAudioService extends ProfileService {
            // TODO: Improve reason reporting or extend the native stack event with reason code
            notifyOnBroadcastStopped(broadcastId, BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);

            BassClientService bassClientService = getBassClientService();
            if (bassClientService != null) {
                bassClientService.stopReceiversSourceSynchronization(broadcastId);
            }

            LeAudioBroadcastDescriptor descriptor = mBroadcastDescriptors.get(broadcastId);
            if (descriptor == null) {
                Log.e(TAG, "EVENT_TYPE_BROADCAST_DESTROYED: No valid descriptor for broadcastId: "
@@ -2570,6 +2589,7 @@ public class LeAudioService extends ProfileService {
            }
            previousState = descriptor.mState;
            descriptor.mState = state;
            BassClientService bassClientService = getBassClientService();

            switch (descriptor.mState) {
                case LeAudioStackEvent.BROADCAST_STATE_STOPPED:
@@ -2610,6 +2630,10 @@ public class LeAudioService extends ProfileService {
                    notifyPlaybackStopped(broadcastId,
                            BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST);

                    if (bassClientService != null) {
                        bassClientService.suspendReceiversSourceSynchronization(broadcastId);
                    }

                    // Notify audio manager
                    updateBroadcastActiveDevice(null, mActiveAudioOutDevice);

@@ -2626,6 +2650,12 @@ public class LeAudioService extends ProfileService {
                    notifyPlaybackStarted(broadcastId,
                            BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST);

                    if (previousState == LeAudioStackEvent.BROADCAST_STATE_PAUSED) {
                        if (bassClientService != null) {
                            bassClientService.resumeReceiversSourceSynchronization(broadcastId);
                        }
                    }

                    // Notify audio manager
                    if (mBroadcastDescriptors.values().stream()
                            .anyMatch(