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

Commit dec5c4e2 authored by Yuyang Huang's avatar Yuyang Huang Committed by Gerrit Code Review
Browse files

Merge "phoneStateChange wait until mActiveDevice's CALL_STATE_CHANGED...

Merge "phoneStateChange wait until mActiveDevice's CALL_STATE_CHANGED completes when isScoManagedByAudio enabled" into main
parents 97fc2c3b c0595229
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.FutureTask;

/**
 * Provides Bluetooth Headset and Handsfree profile, as a service in the Bluetooth application.
@@ -1889,7 +1890,8 @@ public class HeadsetService extends ProfileService {
            mSystemInterface.getHeadsetPhoneState().setCallState(callState);
            // Suspend A2DP when call about is about to become active
            if (mActiveDevice != null && callState != HeadsetHalConstants.CALL_STATE_DISCONNECTED
                    && !mSystemInterface.isCallIdle() && isCallIdleBefore) {
                && !mSystemInterface.isCallIdle() && isCallIdleBefore
                && !Flags.isScoManagedByAudio()) {
                mSystemInterface.getAudioManager().setA2dpSuspended(true);
                if (isAtLeastU()) {
                    mSystemInterface.getAudioManager().setLeAudioSuspended(true);
@@ -1899,9 +1901,25 @@ public class HeadsetService extends ProfileService {
        doForEachConnectedStateMachine(
                stateMachine -> stateMachine.sendMessage(HeadsetStateMachine.CALL_STATE_CHANGED,
                        new HeadsetCallState(numActive, numHeld, callState, number, type, name)));
        if (Flags.isScoManagedByAudio()) {
            if (mActiveDevice == null) {
                Log.i(TAG, "HeadsetService's active device is null");
            } else {
                // wait until mActiveDevice's state machine processed CALL_STATE_CHANGED message,
                // then Audio Framework starts the SCO connection
                FutureTask task = new FutureTask(() -> {}, null);
                mStateMachines.get(mActiveDevice).getHandler().post(task);
                try {
                    task.get();
                } catch (Exception e) {
                    Log.e(TAG,
                        "Exception when waiting for CALL_STATE_CHANGED message" + e.toString());
                }
            }
        }
        getStateMachinesThreadHandler().post(() -> {
            if (callState == HeadsetHalConstants.CALL_STATE_IDLE
                    && mSystemInterface.isCallIdle() && !isAudioOn()) {
                && mSystemInterface.isCallIdle() && !isAudioOn() && !Flags.isScoManagedByAudio()) {
                // Resume A2DP when call ended and SCO is not connected
                mSystemInterface.getAudioManager().setA2dpSuspended(false);
                if (isAtLeastU()) {
+40 −0
Original line number Diff line number Diff line
@@ -1262,6 +1262,46 @@ public class HeadsetServiceAndStateMachineTest {
        verify(mNativeInterface, times(0)).connectAudio(device);
    }

    /**
     * Test to verify the following behavior regarding phoneStateChanged when the SCO is managed by
     * the Audio: When phoneStateChange returns, HeadsetStateMachine completes processing
     * mActiveDevice's CALL_STATE_CHANGED message
     */
    @Test
    public void testPhoneStateChange_SynchronousCallStateChanged() {
        mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO);

        BluetoothDevice device = TestUtils.getTestDevice(mAdapter, 0);
        Assert.assertNotNull(device);
        connectTestDevice(device);

        BluetoothDevice device2 = TestUtils.getTestDevice(mAdapter, 1);
        Assert.assertNotNull(device2);
        connectTestDevice(device2);

        BluetoothDevice device3 = TestUtils.getTestDevice(mAdapter, 2);
        Assert.assertNotNull(device3);
        connectTestDevice(device3);

        mHeadsetService.setActiveDevice(device);
        Assert.assertTrue(mHeadsetService.setActiveDevice(device));

        HeadsetCallState headsetCallState =
                new HeadsetCallState(
                        0, 0, HeadsetHalConstants.CALL_STATE_INCOMING, TEST_PHONE_NUMBER, 128, "");
        mHeadsetService.phoneStateChanged(
                headsetCallState.mNumActive,
                headsetCallState.mNumHeld,
                headsetCallState.mCallState,
                headsetCallState.mNumber,
                headsetCallState.mType,
                headsetCallState.mName,
                false);
        // verify phoneStateChanged runs synchronously, which means when phoneStateChange returns,
        // HeadsetStateMachine completes processing CALL_STATE_CHANGED message
        verify(mNativeInterface, times(1)).phoneStateChange(device, headsetCallState);
    }

    private void connectTestDevice(BluetoothDevice device) {
        when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HEADSET))
                .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN);