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

Commit 7f872859 authored by chelseahao's avatar chelseahao
Browse files

Handle existed source first, then handle QR code.

If the source in the QR code already exists (either streaming or paused) on a device, we don't need to start a targeted scan for that source.

Flag: com.android.settingslib.flags.audio_stream_scan_with_filter
Test: atest
Bug: 395978182
Change-Id: Iccedaa82f95a609a99cc0a9275c1c57f90329dd7
parent 4107895f
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -77,13 +77,20 @@ public class AudioStreamScanHelper implements
        mScanStateChangedListener = scanStateChangedListener;
    }

    /**
     * Returns if the scanning has already started or in the process of starting.
     */
    public boolean hasStartedScanning() {
        return mState == STATE_ON || mState == STATE_TURNING_ON;
    }

    /**
     * Starts the scanning process for available audio stream sources.
     * This method will do nothing if scanning is already active or in the process of starting.
     */
    public void startScanning() {
        mExecutor.execute(() -> {
            if (mState == STATE_ON || mState == STATE_TURNING_ON) {
            if (hasStartedScanning()) {
                Log.d(TAG, "startScanning() : do nothing, state = " + mState);
                return;
            }
@@ -101,7 +108,7 @@ public class AudioStreamScanHelper implements
     */
    public void startScanningWithFilter(@NonNull BluetoothLeBroadcastMetadata metadata) {
        mExecutor.execute(() -> {
            if (mState == STATE_ON || mState == STATE_TURNING_ON) {
            if (hasStartedScanning()) {
                Log.d(TAG, "startScanningWithFilter() : do nothing, state = " + mState);
                return;
            }
@@ -212,8 +219,8 @@ public class AudioStreamScanHelper implements
    }

    private void setState(State newState) {
        mScanStateChangedListener.accept(newState == STATE_ON || newState == STATE_TURNING_ON);
        Log.d(TAG, "setState: from " + mState + " to " + newState);
        mState = newState;
        mScanStateChangedListener.accept(hasStartedScanning());
    }
}
+24 −22
Original line number Diff line number Diff line
@@ -631,28 +631,30 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
        mLeBroadcastAssistant.registerServiceCallBack(mExecutor, mBroadcastAssistantCallback);
        mBroadcastAssistantCallback.setSourceStateListener(this);
        mBroadcastAssistantCallback.setScanStateListener(mScanHelper);
        mExecutor.execute(
                () -> {
                    // Handle QR code scan, display currently streaming or paused streams then start
                    // scanning sequentially
                    handleSourceFromQrCodeIfExists();
        Map<BluetoothDevice, List<BluetoothLeBroadcastReceiveState>> sources =
                mAudioStreamsHelper.getAllSourcesByDevice();
        // Handle currently paused sources on connected devices
        if (mHysteresisModeFixAvailable) {
            getPausedSourcesByDevice(sources).forEach(
                    (device, stateList) ->
                            stateList.forEach(
                                    state -> handleSourcePaused(device, state)));
        }
                    // If a source is streaming in one device and paused in another, we handle the
                    // source as it's streaming
        // Handle currently streaming sources on connected devices, if a source is streaming in one
        // device and paused in another, we handle the source as it's streaming
        getStreamSourcesByDevice(sources).forEach(
                (device, stateList) ->
                        stateList.forEach(
                                state -> handleSourceStreaming(device, state)));
        // In handleSourceFromQrCodeIfExists(), we might start scanning with scan filter targeting
        // the specific source from the QR code. That's why we keep this function after the handling
        // of existed paused and streaming sources, so that we can skip the targeted scanning if the
        // source from the QR code is already present on the connected devices.
        handleSourceFromQrCodeIfExists();
        if (!mScanHelper.hasStartedScanning()) {
            mScanHelper.startScanning();
        }
        mMediaControlHelper.start();
                });
    }

    private Map<BluetoothDevice, List<BluetoothLeBroadcastReceiveState>> getStreamSourcesByDevice(
+7 −7
Original line number Diff line number Diff line
@@ -449,19 +449,19 @@ public class AudioStreamsProgressCategoryControllerTest {
        mController.setSourceFromQrCode(
                metadataWithNoIdAndSameName, SourceOriginForLogging.UNKNOWN);

        // Handle both source from qr code and already connected source in onStart
        mController.displayPreference(mScreen);
        mController.onStart(mLifecycleOwner);
        shadowOf(Looper.getMainLooper()).idle();

        // Setup a connected source with name BROADCAST_NAME_1 and id
        BluetoothLeBroadcastReceiveState connected =
                createConnectedMock(ALREADY_CONNECTED_BROADCAST_ID);
        var data = mock(BluetoothLeAudioContentMetadata.class);
        when(connected.getSubgroupMetadata()).thenReturn(ImmutableList.of(data));
        when(data.getProgramInfo()).thenReturn(BROADCAST_NAME_1);
        when(mAudioStreamsHelper.getAllSourcesByDevice())
                .thenReturn(Map.of(mSourceDevice, ImmutableList.of(connected)));

        // Handle both source from qr code and already connected source in onStart
        mController.displayPreference(mScreen);
        mController.onStart(mLifecycleOwner);
        shadowOf(Looper.getMainLooper()).idle();
        when(mDevice.getDevice()).thenReturn(mSourceDevice);
        mController.handleSourceStreaming(mSourceDevice, connected);

        // Verify two preferences created, one moved to state WAIT_FOR_SYNC, one to SOURCE_ADDED.
        // Both has ALREADY_CONNECTED_BROADCAST_ID as the UNSET_ID is updated to match.