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

Commit bc363fdd authored by Michal Belusiak's avatar Michal Belusiak
Browse files

Bass: Broadcast resync helper, out of range case

Helps sinks to resync to external broadcast when out of range.
When there is a SINK PAUSE and BASS cannot sync to the broadcaster,
then it will try to sync till MESSAGE_BROADCAST_MONITOR_TIMEOUT occur,
which is 5 minutes.
If it syncs to the broadcaster then MESSAGE_BROADCAST_MONITOR_TIMEOUT
is removed, but MESSAGE_BIG_MONITOR_TIMEOUT is still counting to the
30 minutes. MESSAGE_BIG_MONITOR_TIMEOUT is used to help sinks to resync
when BIG appear, i.e. when unpausing.

Bug: 363950680
Bug: 363168099
Test: atest BassClientServiceTest
Change-Id: Idee9165dfb756b8eceae92afb0f56a3cc28979fa
parent 43bb005e
Loading
Loading
Loading
Loading
+97 −42
Original line number Diff line number Diff line
@@ -123,8 +123,10 @@ public class BassClientService extends ProfileService {
    private static final int BROADCAST_STATE_STREAMING = 6;

    @VisibleForTesting static final int MESSAGE_SYNC_TIMEOUT = 1;
    @VisibleForTesting static final int MESSAGE_BIG_CHECK_START = 2;
    @VisibleForTesting static final int MESSAGE_BIG_CHECK_STOP = 3;
    @VisibleForTesting static final int MESSAGE_BIG_MONITOR_TIMEOUT = 2;
    @VisibleForTesting static final int MESSAGE_BIG_CHECK_START = 3;
    @VisibleForTesting static final int MESSAGE_BIG_CHECK_STOP = 4;
    @VisibleForTesting static final int MESSAGE_BROADCAST_MONITOR_TIMEOUT = 5;

    /* 1 minute timeout for primary device reconnection in Private Broadcast case */
    private static final int DIALING_OUT_TIMEOUT_MS = 60000;
@@ -135,11 +137,14 @@ public class BassClientService extends ProfileService {
    // 6 seconds to start BIG check. It has to be greater than kPeriodicSyncTimeout
    private static final Duration sBigCheckStart = Duration.ofSeconds(6);

    // 2 second for check if BIG exist
    // 2 seconds for check if BIG exist
    private static final Duration sBigCheckStop = Duration.ofSeconds(2);

    // 5 minutes timeout for monitoring BIG resynchronization
    private static final Duration sBigMonitorTimeout = Duration.ofMinutes(5);
    // 30 minutes timeout for monitoring BIG resynchronization
    private static final Duration sBigMonitorTimeout = Duration.ofMinutes(30);

    // 5 minutes timeout for monitoring broadcaster
    private static final Duration sBroadcasterMonitorTimeout = Duration.ofMinutes(5);

    private enum PauseType {
        HOST_INTENTIONAL,
@@ -219,13 +224,33 @@ public class BassClientService extends ProfileService {
                    switch (msg.what) {
                        case MESSAGE_SYNC_TIMEOUT:
                            {
                                if (!leaudioBroadcastResyncHelper()) {
                                log("MESSAGE_SYNC_TIMEOUT");
                                clearAllSyncData();
                                break;
                            }
                                log("MESSAGE_SYNC_TIMEOUT");
                        case MESSAGE_BROADCAST_MONITOR_TIMEOUT:
                            {
                                log("MESSAGE_BROADCAST_MONITOR_TIMEOUT");
                                int broadcastId = msg.arg1;
                                List<Integer> activeSyncedSrc =
                                        new ArrayList<>(getActiveSyncedSources());
                                if (activeSyncedSrc.contains(
                                        getSyncHandleForBroadcastId(broadcastId))) {
                                    break;
                                }
                                log("Notify broadcast source lost, broadcast id: " + broadcastId);
                                mCallbacks.notifySourceLost(broadcastId);
                                // fall through
                            }
                        case MESSAGE_BIG_MONITOR_TIMEOUT:
                            {
                                log("MESSAGE_BIG_MONITOR_TIMEOUT");
                                int broadcastId = msg.arg1;
                                if (isSinkUnintentionalPauseType(broadcastId)) {
                                    stopSourceReceivers(broadcastId);
                                } else {
                                    stopBigMonitoring(broadcastId, false);
                                }
                                synchronized (mSearchScanCallbackLock) {
                                    // when searching is stopped then clear all sync data
                                    if (mSearchScanCallback == null) {
@@ -242,6 +267,7 @@ public class BassClientService extends ProfileService {
                                mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP);
                                Message newMsg = mHandler.obtainMessage(MESSAGE_BIG_CHECK_STOP);
                                newMsg.arg1 = broadcastId;
                                log("Started MESSAGE_BIG_CHECK_STOP");
                                mHandler.sendMessageDelayed(newMsg, sBigCheckStop.toMillis());
                                break;
                            }
@@ -258,13 +284,6 @@ public class BassClientService extends ProfileService {
                                            broadcastId, PauseType.SINK_UNINTENTIONAL);
                                    cacheSuspendingSources(broadcastId);
                                }
                                // Timer starts even if pause is SINK_INTENTIONAL to keep sync in
                                // case that buds send SyncInfo Request
                                mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT);
                                log("Started timeout for canceling syncs");
                                Message newMsg = mHandler.obtainMessage(MESSAGE_SYNC_TIMEOUT);
                                newMsg.arg1 = broadcastId;
                                mHandler.sendMessageDelayed(newMsg, sBigMonitorTimeout.toMillis());
                                break;
                            }
                        default:
@@ -1066,7 +1085,14 @@ public class BassClientService extends ProfileService {
                    mHandler.removeMessages(MESSAGE_BIG_CHECK_START);
                    Message newMsg = mHandler.obtainMessage(MESSAGE_BIG_CHECK_START);
                    newMsg.arg1 = broadcastId;
                    log("Started MESSAGE_BIG_CHECK_START");
                    mHandler.sendMessageDelayed(newMsg, sBigCheckStart.toMillis());

                    mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT);
                    newMsg = mHandler.obtainMessage(MESSAGE_BIG_MONITOR_TIMEOUT);
                    newMsg.arg1 = broadcastId;
                    log("Started MESSAGE_BIG_MONITOR_TIMEOUT");
                    mHandler.sendMessageDelayed(newMsg, sBigMonitorTimeout.toMillis());
                }
            }
        } else if (isEmptyBluetoothDevice(receiveState.getSourceDevice())) {
@@ -2057,16 +2083,19 @@ public class BassClientService extends ProfileService {
                        null);
                addActiveSyncedSource(syncHandle);

                if (!leaudioBroadcastResyncHelper()) {
                    synchronized (mSearchScanCallbackLock) {
                    // when searching is stopped then start timer to stop active sync
                        // when searching is stopped then start timer to stop active syncs
                        if (mSearchScanCallback == null) {
                            mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT);
                        log("Started timeout for canceling syncs");
                        Message newMsg = mHandler.obtainMessage(MESSAGE_SYNC_TIMEOUT);
                        newMsg.arg1 = broadcastId;
                        mHandler.sendMessageDelayed(newMsg, sSyncActiveTimeout.toMillis());
                            log("Started MESSAGE_SYNC_TIMEOUT");
                            mHandler.sendEmptyMessageDelayed(
                                    MESSAGE_SYNC_TIMEOUT, sSyncActiveTimeout.toMillis());
                        }
                    }
                } else {
                    mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT);
                }

                // update valid sync handle in mPeriodicAdvCallbacksMap
                synchronized (mPeriodicAdvCallbacksMap) {
@@ -2113,17 +2142,26 @@ public class BassClientService extends ProfileService {
                        }
                    }
                }
                stopBigMonitoring(broadcastId, false);
                synchronized (mSourceSyncRequestsQueue) {
                    int failsCounter = mSyncFailureCounter.getOrDefault(broadcastId, 0) + 1;
                    mSyncFailureCounter.put(broadcastId, failsCounter);
                }
                synchronized (mSearchScanCallbackLock) {
                if (isAnySinkPauseType(broadcastId)) {
                    if (!mHandler.hasMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT)) {
                        Message newMsg = mHandler.obtainMessage(MESSAGE_BROADCAST_MONITOR_TIMEOUT);
                        newMsg.arg1 = broadcastId;
                        log("Started MESSAGE_BROADCAST_MONITOR_TIMEOUT");
                        mHandler.sendMessageDelayed(newMsg, sBroadcasterMonitorTimeout.toMillis());
                    }
                    addSelectSourceRequest(broadcastId, true);
                } else {
                    // Clear from cache to make possible sync again (only during active searching)
                    synchronized (mSearchScanCallbackLock) {
                        if (mSearchScanCallback != null) {
                            mCachedBroadcasts.remove(broadcastId);
                        }
                    }
                }
                mPeriodicAdvCallbacksMap.remove(BassConstants.INVALID_SYNC_HANDLE);
            }
            handleSelectSourceRequest();
@@ -2186,24 +2224,33 @@ public class BassClientService extends ProfileService {
        public void onSyncLost(int syncHandle) {
            int broadcastId = getBroadcastIdForSyncHandle(syncHandle);
            log("OnSyncLost: syncHandle=" + syncHandle + ", broadcastID=" + broadcastId);
            clearAllDataForSyncHandle(syncHandle);
            if (broadcastId != BassConstants.INVALID_BROADCAST_ID) {
                if (leaudioBroadcastMonitorSourceSyncStatus()) {
                    log("Notify broadcast source lost, broadcast id: " + broadcastId);
                    mCallbacks.notifySourceLost(broadcastId);
                }
                stopBigMonitoring(broadcastId, false);
                synchronized (mSourceSyncRequestsQueue) {
                    int failsCounter = mSyncFailureCounter.getOrDefault(broadcastId, 0) + 1;
                    mSyncFailureCounter.put(broadcastId, failsCounter);
                }
                if (isAnySinkPauseType(broadcastId)) {
                    if (!mHandler.hasMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT)) {
                        Message newMsg = mHandler.obtainMessage(MESSAGE_BROADCAST_MONITOR_TIMEOUT);
                        newMsg.arg1 = broadcastId;
                        log("Started MESSAGE_BROADCAST_MONITOR_TIMEOUT");
                        mHandler.sendMessageDelayed(newMsg, sBroadcasterMonitorTimeout.toMillis());
                    }
            clearAllDataForSyncHandle(syncHandle);
                    addSelectSourceRequest(broadcastId, true);
                } else {
                    // Clear from cache to make possible sync again (only during active searching)
                    synchronized (mSearchScanCallbackLock) {
                        if (mSearchScanCallback != null) {
                            mCachedBroadcasts.remove(broadcastId);
                        }
                    }
                    if (leaudioBroadcastMonitorSourceSyncStatus()) {
                        log("Notify broadcast source lost, broadcast id: " + broadcastId);
                        mCallbacks.notifySourceLost(broadcastId);
                    }
                }
            }
        }

        @Override
@@ -3445,14 +3492,20 @@ public class BassClientService extends ProfileService {
                && mPausedBroadcastIds.get(broadcastId).equals(PauseType.HOST_INTENTIONAL));
    }

    private boolean isSinkUnintentionalPauseType(int broadcastId) {
        return (mPausedBroadcastIds.containsKey(broadcastId)
                && mPausedBroadcastIds.get(broadcastId).equals(PauseType.SINK_UNINTENTIONAL));
    }

    public void stopBigMonitoring() {
        if (!leaudioBroadcastResyncHelper()) {
            return;
        }
        log("stopBigMonitoring");
        mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT);
        mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT);
        mHandler.removeMessages(MESSAGE_BIG_CHECK_START);
        mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP);
        mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT);

        mPausedBroadcastSinks.clear();

@@ -3479,9 +3532,10 @@ public class BassClientService extends ProfileService {
        while (iterator.hasNext()) {
            int pausedBroadcastId = iterator.next();
            if (!isAnyReceiverSyncedToBroadcast(pausedBroadcastId)) {
                mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT);
                mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT);
                mHandler.removeMessages(MESSAGE_BIG_CHECK_START);
                mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP);
                mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT);
                iterator.remove();
                synchronized (mSearchScanCallbackLock) {
                    // when searching is stopped then stop active sync
@@ -3499,9 +3553,10 @@ public class BassClientService extends ProfileService {
            return;
        }
        log("stopBigMonitoring broadcastId: " + broadcastId + ", hostInitiated: " + hostInitiated);
        mHandler.removeMessages(MESSAGE_SYNC_TIMEOUT);
        mHandler.removeMessages(MESSAGE_BIG_MONITOR_TIMEOUT);
        mHandler.removeMessages(MESSAGE_BIG_CHECK_START);
        mHandler.removeMessages(MESSAGE_BIG_CHECK_STOP);
        mHandler.removeMessages(MESSAGE_BROADCAST_MONITOR_TIMEOUT);
        if (hostInitiated) {
            mPausedBroadcastIds.put(broadcastId, PauseType.HOST_INTENTIONAL);
        } else {
+198 −20

File changed.

Preview size limit exceeded, changes collapsed.