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

Commit 1929e74f authored by Yuyang Huang's avatar Yuyang Huang Committed by Automerger Merge Worker
Browse files

Merge "Integrate bluetooth.sco.managed_by_audio system property with aconfig...

Merge "Integrate bluetooth.sco.managed_by_audio system property with aconfig flag" into main am: 072c39e5

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



Change-Id: I5fc30643e6eeea7adac427deefec475c8d1ade89
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 1e5962c9 072c39e5
Loading
Loading
Loading
Loading
+32 −0
Original line number Original line Diff line number Diff line
@@ -63,8 +63,11 @@ import android.provider.DeviceConfig;
import android.provider.Telephony;
import android.provider.Telephony;
import android.util.Log;
import android.util.Log;


import androidx.annotation.VisibleForTesting;

import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.flags.Flags;


import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserException;
@@ -95,6 +98,11 @@ public final class Utils {
    private static boolean sDualModeEnabled =
    private static boolean sDualModeEnabled =
            SystemProperties.getBoolean(ENABLE_DUAL_MODE_AUDIO, false);
            SystemProperties.getBoolean(ENABLE_DUAL_MODE_AUDIO, false);


    private static final String ENABLE_SCO_MANAGED_BY_AUDIO = "bluetooth.sco.managed_by_audio";

    private static boolean isScoManagedByAudioEnabled =
            SystemProperties.getBoolean(ENABLE_SCO_MANAGED_BY_AUDIO, false);

    private static final String KEY_TEMP_ALLOW_LIST_DURATION_MS = "temp_allow_list_duration_ms";
    private static final String KEY_TEMP_ALLOW_LIST_DURATION_MS = "temp_allow_list_duration_ms";
    private static final long DEFAULT_TEMP_ALLOW_LIST_DURATION_MS = 20_000;
    private static final long DEFAULT_TEMP_ALLOW_LIST_DURATION_MS = 20_000;


@@ -143,6 +151,30 @@ public final class Utils {
        return sDualModeEnabled;
        return sDualModeEnabled;
    }
    }


    /**
     * Check if SCO managed by Audio is enabled. This is set via the system property
     * bluetooth.sco.managed_by_audio.
     *
     * <p>When set to {@code false}, Bluetooth will managed the start and end of the SCO.
     *
     * <p>When set to {@code true}, Audio will manage the start and end of the SCO through HAL.
     *
     * @return true if SCO managed by Audio is enabled, false otherwise
     */
    public static boolean isScoManagedByAudioEnabled() {
        if (Flags.isScoManagedByAudio()) {
            Log.d(TAG, "isScoManagedByAudioEnabled state is: " + isScoManagedByAudioEnabled);
            return isScoManagedByAudioEnabled;
        }
        return false;
    }

    @VisibleForTesting
    public static void setIsScoManagedByAudioEnabled(boolean enabled) {
        Log.i(TAG, "Updating isScoManagedByAudioEnabled for testing to: " + enabled);
        isScoManagedByAudioEnabled = enabled;
    }

    /**
    /**
     * Only exposed for testing, do not invoke this method outside of tests.
     * Only exposed for testing, do not invoke this method outside of tests.
     * @param enabled true if the dual mode state is enabled, false otherwise
     * @param enabled true if the dual mode state is enabled, false otherwise
+5 −4
Original line number Original line Diff line number Diff line
@@ -1255,7 +1255,7 @@ public class HeadsetService extends ProfileService {
            }
            }
            mVoiceRecognitionStarted = false;
            mVoiceRecognitionStarted = false;
            stateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_STOP, device);
            stateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_STOP, device);
            if (Flags.isScoManagedByAudio()) {
            if (Utils.isScoManagedByAudioEnabled()) {
                mSystemInterface.getAudioManager().clearCommunicationDevice();
                mSystemInterface.getAudioManager().clearCommunicationDevice();
                return true;
                return true;
            }
            }
@@ -1919,7 +1919,7 @@ public class HeadsetService extends ProfileService {
            // Suspend A2DP when call about is about to become active
            // Suspend A2DP when call about is about to become active
            if (mActiveDevice != null && callState != HeadsetHalConstants.CALL_STATE_DISCONNECTED
            if (mActiveDevice != null && callState != HeadsetHalConstants.CALL_STATE_DISCONNECTED
                && !mSystemInterface.isCallIdle() && isCallIdleBefore
                && !mSystemInterface.isCallIdle() && isCallIdleBefore
                && !Flags.isScoManagedByAudio()) {
                && !Utils.isScoManagedByAudioEnabled()) {
                mSystemInterface.getAudioManager().setA2dpSuspended(true);
                mSystemInterface.getAudioManager().setA2dpSuspended(true);
                if (isAtLeastU()) {
                if (isAtLeastU()) {
                    mSystemInterface.getAudioManager().setLeAudioSuspended(true);
                    mSystemInterface.getAudioManager().setLeAudioSuspended(true);
@@ -1929,7 +1929,7 @@ public class HeadsetService extends ProfileService {
        doForEachConnectedStateMachine(
        doForEachConnectedStateMachine(
                stateMachine -> stateMachine.sendMessage(HeadsetStateMachine.CALL_STATE_CHANGED,
                stateMachine -> stateMachine.sendMessage(HeadsetStateMachine.CALL_STATE_CHANGED,
                        new HeadsetCallState(numActive, numHeld, callState, number, type, name)));
                        new HeadsetCallState(numActive, numHeld, callState, number, type, name)));
        if (Flags.isScoManagedByAudio()) {
        if (Utils.isScoManagedByAudioEnabled()) {
            if (mActiveDevice == null) {
            if (mActiveDevice == null) {
                Log.i(TAG, "HeadsetService's active device is null");
                Log.i(TAG, "HeadsetService's active device is null");
            } else {
            } else {
@@ -1947,7 +1947,8 @@ public class HeadsetService extends ProfileService {
        }
        }
        getStateMachinesThreadHandler().post(() -> {
        getStateMachinesThreadHandler().post(() -> {
            if (callState == HeadsetHalConstants.CALL_STATE_IDLE
            if (callState == HeadsetHalConstants.CALL_STATE_IDLE
                && mSystemInterface.isCallIdle() && !isAudioOn() && !Flags.isScoManagedByAudio()) {
                && mSystemInterface.isCallIdle() && !isAudioOn()
                && !Utils.isScoManagedByAudioEnabled()) {
                // Resume A2DP when call ended and SCO is not connected
                // Resume A2DP when call ended and SCO is not connected
                mSystemInterface.getAudioManager().setA2dpSuspended(false);
                mSystemInterface.getAudioManager().setA2dpSuspended(false);
                if (isAtLeastU()) {
                if (isAtLeastU()) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -1735,7 +1735,7 @@ public class HeadsetStateMachine extends StateMachine {
    }
    }


    private void setAudioParameters() {
    private void setAudioParameters() {
        if (Flags.isScoManagedByAudio()) {
        if (Utils.isScoManagedByAudioEnabled()) {
            Log.i(TAG, "isScoManagedByAudio enabled, do not setAudioParameters");
            Log.i(TAG, "isScoManagedByAudio enabled, do not setAudioParameters");
            return;
            return;
        }
        }
+12 −0
Original line number Original line Diff line number Diff line
@@ -56,6 +56,7 @@ import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.runner.AndroidJUnit4;


import com.android.bluetooth.TestUtils;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.ActiveDeviceManager;
import com.android.bluetooth.btservice.ActiveDeviceManager;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.RemoteDevices;
import com.android.bluetooth.btservice.RemoteDevices;
@@ -704,6 +705,8 @@ public class HeadsetServiceAndStateMachineTest {
    @Test
    @Test
    public void testVoiceRecognition_SingleHfInitiatedSuccess_ScoManagedByAudio() {
    public void testVoiceRecognition_SingleHfInitiatedSuccess_ScoManagedByAudio() {
        mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO);
        mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO);
        Utils.setIsScoManagedByAudioEnabled(true);

        // Connect HF
        // Connect HF
        BluetoothDevice device = TestUtils.getTestDevice(mAdapter, 0);
        BluetoothDevice device = TestUtils.getTestDevice(mAdapter, 0);
        connectTestDevice(device);
        connectTestDevice(device);
@@ -714,6 +717,8 @@ public class HeadsetServiceAndStateMachineTest {
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(eq(device), eq(true));
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(eq(device), eq(true));
        // Start voice recognition
        // Start voice recognition
        startVoiceRecognitionFromHf_ScoManagedByAudio(device);
        startVoiceRecognitionFromHf_ScoManagedByAudio(device);

        Utils.setIsScoManagedByAudioEnabled(false);
    }
    }


    /**
    /**
@@ -863,6 +868,8 @@ public class HeadsetServiceAndStateMachineTest {
    @Test
    @Test
    public void testVoiceRecognition_SingleAgInitiatedSuccess_ScoManagedByAudio() {
    public void testVoiceRecognition_SingleAgInitiatedSuccess_ScoManagedByAudio() {
        mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO);
        mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO);
        Utils.setIsScoManagedByAudioEnabled(true);

        // Connect HF
        // Connect HF
        BluetoothDevice device = TestUtils.getTestDevice(mAdapter, 0);
        BluetoothDevice device = TestUtils.getTestDevice(mAdapter, 0);
        connectTestDevice(device);
        connectTestDevice(device);
@@ -873,6 +880,8 @@ public class HeadsetServiceAndStateMachineTest {
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(eq(device), eq(true));
        verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).sendBsir(eq(device), eq(true));
        // Start voice recognition
        // Start voice recognition
        startVoiceRecognitionFromAg_ScoManagedByAudio();
        startVoiceRecognitionFromAg_ScoManagedByAudio();

        Utils.setIsScoManagedByAudioEnabled(false);
    }
    }


    /**
    /**
@@ -1681,6 +1690,7 @@ public class HeadsetServiceAndStateMachineTest {
    @Test
    @Test
    public void testPhoneStateChange_SynchronousCallStateChanged() {
    public void testPhoneStateChange_SynchronousCallStateChanged() {
        mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO);
        mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO);
        Utils.setIsScoManagedByAudioEnabled(true);


        BluetoothDevice device = TestUtils.getTestDevice(mAdapter, 0);
        BluetoothDevice device = TestUtils.getTestDevice(mAdapter, 0);
        Assert.assertNotNull(device);
        Assert.assertNotNull(device);
@@ -1711,6 +1721,8 @@ public class HeadsetServiceAndStateMachineTest {
        // verify phoneStateChanged runs synchronously, which means when phoneStateChange returns,
        // verify phoneStateChanged runs synchronously, which means when phoneStateChange returns,
        // HeadsetStateMachine completes processing CALL_STATE_CHANGED message
        // HeadsetStateMachine completes processing CALL_STATE_CHANGED message
        verify(mNativeInterface, times(1)).phoneStateChange(device, headsetCallState);
        verify(mNativeInterface, times(1)).phoneStateChange(device, headsetCallState);

        Utils.setIsScoManagedByAudioEnabled(false);
    }
    }


    private void connectTestDevice(BluetoothDevice device) {
    private void connectTestDevice(BluetoothDevice device) {
+3 −0
Original line number Original line Diff line number Diff line
@@ -51,6 +51,7 @@ import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.runner.AndroidJUnit4;


import com.android.bluetooth.TestUtils;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.ActiveDeviceManager;
import com.android.bluetooth.btservice.ActiveDeviceManager;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.RemoteDevices;
import com.android.bluetooth.btservice.RemoteDevices;
@@ -1731,6 +1732,7 @@ public class HeadsetStateMachineTest {
    @Test
    @Test
    public void testSetAudioParameters_isScoManagedByAudio() {
    public void testSetAudioParameters_isScoManagedByAudio() {
        mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO);
        mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO);
        Utils.setIsScoManagedByAudioEnabled(true);


        setUpConnectedState();
        setUpConnectedState();
        mHeadsetStateMachine.sendMessage(
        mHeadsetStateMachine.sendMessage(
@@ -1749,6 +1751,7 @@ public class HeadsetStateMachineTest {
                        mTestDevice));
                        mTestDevice));


        verify(mAudioManager, times(0)).setParameters(any());
        verify(mAudioManager, times(0)).setParameters(any());
        Utils.setIsScoManagedByAudioEnabled(false);
    }
    }


    /**
    /**