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

Commit 4dba532e authored by Ted Wang's avatar Ted Wang Committed by Yung Ti Su
Browse files

Add Low Latency Audio Control

Set low latency audio allowed status when follwoing condition to inform
audio hal low latency mode change.
1. A2dp connected
2. Codec config updated
3. Active device changed
4. Optional codec disabled/enabled

Bug: 247680090
Test: atest GoogleBluetoothInstrumentationTests:A2dpStateMachineTest
Ignore-AOSP-First: tm-qpr feature
Change-Id: I41e77973e21f241b160b1a12174892d55f34333b
parent be07b0aa
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -71,6 +71,9 @@ public class A2dpService extends ProfileService {
    private static final boolean DBG = true;
    private static final String TAG = "A2dpService";

    // TODO(b/240635097): remove in U
    private static final int SOURCE_CODEC_TYPE_OPUS = 6;

    private static A2dpService sA2dpService;

    private AdapterService mAdapterService;
@@ -600,6 +603,7 @@ public class A2dpService extends ProfileService {
            // This needs to happen before we inform the audio manager that the device
            // disconnected. Please see comment in updateAndBroadcastActiveDevice() for why.
            updateAndBroadcastActiveDevice(device);
            updateLowLatencyAudioSupport(device);

            BluetoothDevice newActiveDevice = null;
            synchronized (mStateMachines) {
@@ -819,6 +823,7 @@ public class A2dpService extends ProfileService {
            Log.e(TAG, "enableOptionalCodecs: Codec status is null");
            return;
        }
        updateLowLatencyAudioSupport(device);
        mA2dpCodecConfig.enableOptionalCodecs(device, codecStatus.getCodecConfig());
    }

@@ -849,6 +854,7 @@ public class A2dpService extends ProfileService {
            Log.e(TAG, "disableOptionalCodecs: Codec status is null");
            return;
        }
        updateLowLatencyAudioSupport(device);
        mA2dpCodecConfig.disableOptionalCodecs(device, codecStatus.getCodecConfig());
    }

@@ -1208,6 +1214,34 @@ public class A2dpService extends ProfileService {
        }
    }

    /**
     *  Check for low-latency codec support and inform AdapterService
     *
     *  @param device device whose audio low latency will be allowed or disallowed
     */
    @VisibleForTesting
    public void updateLowLatencyAudioSupport(BluetoothDevice device) {
        synchronized (mStateMachines) {
            A2dpStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                return;
            }
            BluetoothCodecStatus codecStatus = sm.getCodecStatus();
            boolean lowLatencyAudioAllow = false;
            BluetoothCodecConfig lowLatencyCodec = new BluetoothCodecConfig.Builder()
                    .setCodecType(SOURCE_CODEC_TYPE_OPUS) // remove in U
                    .build();

            if (codecStatus != null
                    && codecStatus.isCodecConfigSelectable(lowLatencyCodec)
                    && getOptionalCodecsEnabled(device)
                            == BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) {
                lowLatencyAudioAllow = true;
            }
            mAdapterService.allowLowLatencyAudio(lowLatencyAudioAllow, device);
        }
    }

    private void connectionStateChanged(BluetoothDevice device, int fromState, int toState) {
        if ((device == null) || (fromState == toState)) {
            return;
+2 −0
Original line number Diff line number Diff line
@@ -483,6 +483,7 @@ final class A2dpStateMachine extends StateMachine {
            // codecs (perhaps it's had a firmware update, etc.) and save that state if
            // it differs from what we had saved before.
            mA2dpService.updateOptionalCodecsSupport(mDevice);
            mA2dpService.updateLowLatencyAudioSupport(mDevice);
            broadcastConnectionState(mConnectionState, mLastConnectionState);
            // Upon connected, the audio starts out as stopped
            broadcastAudioState(BluetoothA2dp.STATE_NOT_PLAYING,
@@ -655,6 +656,7 @@ final class A2dpStateMachine extends StateMachine {
            // for this codec change event.
            mA2dpService.updateOptionalCodecsSupport(mDevice);
        }
        mA2dpService.updateLowLatencyAudioSupport(mDevice);
        if (mA2dpOffloadEnabled) {
            boolean update = false;
            BluetoothCodecConfig newCodecConfig = mCodecStatus.getCodecConfig();
+15 −0
Original line number Diff line number Diff line
@@ -362,6 +362,7 @@ public class A2dpStateMachineTest {
        // Selected codec = SBC, selectable codec = SBC
        mA2dpStateMachine.processCodecConfigEvent(codecStatusSbcAndSbc);
        verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusSbcAndSbc, false);
        verify(mA2dpService, times(1)).updateLowLatencyAudioSupport(mTestDevice);

        // Inject an event to change state machine to connected state
        A2dpStackEvent connStCh =
@@ -379,6 +380,7 @@ public class A2dpStateMachineTest {

        // Verify that state machine update optional codec when enter connected state
        verify(mA2dpService, times(1)).updateOptionalCodecsSupport(mTestDevice);
        verify(mA2dpService, times(2)).updateLowLatencyAudioSupport(mTestDevice);

        // Change codec status when device connected.
        // Selected codec = SBC, selectable codec = SBC+AAC
@@ -387,12 +389,14 @@ public class A2dpStateMachineTest {
            verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusSbcAndSbcAac, true);
        }
        verify(mA2dpService, times(2)).updateOptionalCodecsSupport(mTestDevice);
        verify(mA2dpService, times(3)).updateLowLatencyAudioSupport(mTestDevice);

        // Update selected codec with selectable codec unchanged.
        // Selected codec = AAC, selectable codec = SBC+AAC
        mA2dpStateMachine.processCodecConfigEvent(codecStatusAacAndSbcAac);
        verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusAacAndSbcAac, false);
        verify(mA2dpService, times(2)).updateOptionalCodecsSupport(mTestDevice);
        verify(mA2dpService, times(4)).updateLowLatencyAudioSupport(mTestDevice);

        // Update selected codec
        // Selected codec = OPUS, selectable codec = SBC+AAC+OPUS
@@ -401,5 +405,16 @@ public class A2dpStateMachineTest {
            verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusOpusAndSbcAacOpus, true);
        }
        verify(mA2dpService, times(3)).updateOptionalCodecsSupport(mTestDevice);
        // Check if low latency audio been updated.
        verify(mA2dpService, times(5)).updateLowLatencyAudioSupport(mTestDevice);

        // Update selected codec with selectable codec changed.
        // Selected codec = SBC, selectable codec = SBC+AAC
        mA2dpStateMachine.processCodecConfigEvent(codecStatusSbcAndSbcAac);
        if (!offloadEnabled) {
            verify(mA2dpService).codecConfigUpdated(mTestDevice, codecStatusSbcAndSbcAac, true);
        }
        // Check if low latency audio been update.
        verify(mA2dpService, times(6)).updateLowLatencyAudioSupport(mTestDevice);
    }
}