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

Commit 418eb22b authored by Yuyang Huang's avatar Yuyang Huang
Browse files

HFP: Allow Audio Fwk to change HFP SCO volume when HFP profile is connected...

HFP: Allow Audio Fwk to change HFP SCO volume when HFP profile is connected and SCO is not connected

Align HFP's behavior with A2DP's. In A2DP, when music is not playing, user can change volume from phone. So HFP should do similarly, when HFP connected, and SCO is not connected, user can still change its volume from phone.

Bug: 348724965
Bug: 362313390
Change-Id: Ie17e51831a8911925001ee23c41336ef4267742c
Test: atest HeadsetStateMachine
Flag: com.android.bluetooth.flags.hfp_allow_volume_change_without_sco
parent 84349e1a
Loading
Loading
Loading
Loading
+22 −14
Original line number Diff line number Diff line
@@ -1124,6 +1124,12 @@ class HeadsetStateMachine extends StateMachine {
                        }
                    }
                    break;
                case INTENT_SCO_VOLUME_CHANGED:
                    if (Flags.hfpAllowVolumeChangeWithoutSco()) {
                        // when flag is removed, remove INTENT_SCO_VOLUME_CHANGED case in AudioOn
                        processIntentScoVolume((Intent) message.obj, mDevice);
                    }
                    break;
                case INTENT_CONNECTION_ACCESS_REPLY:
                    handleAccessPermissionResult((Intent) message.obj);
                    break;
@@ -1245,6 +1251,20 @@ class HeadsetStateMachine extends StateMachine {
         * @param state audio state
         */
        public abstract void processAudioEvent(int state);

        void processIntentScoVolume(Intent intent, BluetoothDevice device) {
            int volumeValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
            stateLogD(
                    "processIntentScoVolume: mSpeakerVolume="
                            + mSpeakerVolume
                            + ", volumeValue="
                            + volumeValue);
            if (mSpeakerVolume != volumeValue) {
                mSpeakerVolume = volumeValue;
                mNativeInterface.setVolume(
                        device, HeadsetHalConstants.VOLUME_TYPE_SPK, mSpeakerVolume);
            }
        }
    }

    class Connected extends ConnectedBase {
@@ -1613,6 +1633,8 @@ class HeadsetStateMachine extends StateMachine {
                        break;
                    }
                case INTENT_SCO_VOLUME_CHANGED:
                    // TODO: b/362313390 Remove this case once the fix is in place because this
                    // message will be handled by the ConnectedBase state.
                    processIntentScoVolume((Intent) message.obj, mDevice);
                    break;
                case STACK_EVENT:
@@ -1660,20 +1682,6 @@ class HeadsetStateMachine extends StateMachine {
                    break;
            }
        }

        private void processIntentScoVolume(Intent intent, BluetoothDevice device) {
            int volumeValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
            stateLogD(
                    "processIntentScoVolume: mSpeakerVolume="
                            + mSpeakerVolume
                            + ", volumeValue="
                            + volumeValue);
            if (mSpeakerVolume != volumeValue) {
                mSpeakerVolume = volumeValue;
                mNativeInterface.setVolume(
                        device, HeadsetHalConstants.VOLUME_TYPE_SPK, mSpeakerVolume);
            }
        }
    }

    class AudioDisconnecting extends ConnectedBase {
+44 −1
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
@@ -37,6 +36,7 @@ import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.HandlerThread;
import android.os.UserHandle;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
@@ -1823,6 +1823,49 @@ public class HeadsetStateMachineTest {
        verify(mockAudioManager).setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, 2, 0);
    }

    @Test
    @EnableFlags({Flags.FLAG_HFP_ALLOW_VOLUME_CHANGE_WITHOUT_SCO})
    public void testVolumeChangeEvent_fromIntentWhenConnected() {
        setUpConnectedState();
        int originalVolume = mHeadsetStateMachine.mSpeakerVolume;
        mHeadsetStateMachine.mSpeakerVolume = 0;
        int vol = 10;

        // Send INTENT_SCO_VOLUME_CHANGED message
        Intent volumeChange = new Intent(AudioManager.ACTION_VOLUME_CHANGED);
        volumeChange.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, vol);

        mHeadsetStateMachine.sendMessage(
                HeadsetStateMachine.INTENT_SCO_VOLUME_CHANGED, volumeChange);
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());

        // verify volume processed
        verify(mNativeInterface).setVolume(mTestDevice, HeadsetHalConstants.VOLUME_TYPE_SPK, vol);

        mHeadsetStateMachine.mSpeakerVolume = originalVolume;
    }

    @Test
    public void testVolumeChangeEvent_fromIntentWhenAudioOn() {
        setUpAudioOnState();
        int originalVolume = mHeadsetStateMachine.mSpeakerVolume;
        mHeadsetStateMachine.mSpeakerVolume = 0;
        int vol = 10;

        // Send INTENT_SCO_VOLUME_CHANGED message
        Intent volumeChange = new Intent(AudioManager.ACTION_VOLUME_CHANGED);
        volumeChange.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, vol);

        mHeadsetStateMachine.sendMessage(
                HeadsetStateMachine.INTENT_SCO_VOLUME_CHANGED, volumeChange);
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());

        // verify volume processed
        verify(mNativeInterface).setVolume(mTestDevice, HeadsetHalConstants.VOLUME_TYPE_SPK, vol);

        mHeadsetStateMachine.mSpeakerVolume = originalVolume;
    }

    @Test
    public void testDump_doesNotCrash() {
        StringBuilder sb = new StringBuilder();