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

Commit f4a92737 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Correct issue where ringtone is not heard on BT headset in vibrate mode.

To correct this issue, listening to STREAM_MUTE_CHANGED_ACTION in
AudioManager and triggering re-evaluation of ringtone playback.
Used existing CallAudioManager#onRingerModeChange() method which does
this for other cases already.
This has the nice side effect of cleaning up the long-standing behavior
where the device will not start ringing if you increase the ring stream
volume while ringing is in progress.

Test: Added new unit test to verify the broadcast will trigger ringtone
re-evaluation.
Test: Manual test; verify that if I unmute the ring stream while a call
is ringing, the ringtone starts playing.
Test: Manual test; verify with device in vibrate-only mode that paired BT
headset has audible ringing.  Confirmed in logs that new code path is hit
which caused ringtone to start.
Fixes: 171545132

Change-Id: I638a6f403fba4a8eff0bd9cf7ade0e8ff6afbc1c
parent c01de52d
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -1347,6 +1347,15 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    } else {
                        sendInternalMessage(MUTE_EXTERNALLY_CHANGED);
                    }
                } else if (AudioManager.STREAM_MUTE_CHANGED_ACTION.equals(intent.getAction())) {
                    int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
                    boolean isStreamMuted = intent.getBooleanExtra(
                            AudioManager.EXTRA_STREAM_VOLUME_MUTED, false);

                    if (streamType == AudioManager.STREAM_RING && !isStreamMuted) {
                        Log.i(this, "Ring stream was un-muted.");
                        mCallAudioManager.onRingerModeChange();
                    }
                } else {
                    Log.w(this, "Received non-mute-change intent");
                }
@@ -1530,6 +1539,8 @@ public class CallAudioRouteStateMachine extends StateMachine {
        mWasOnSpeaker = false;
        mContext.registerReceiver(mMuteChangeReceiver,
                new IntentFilter(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED));
        mContext.registerReceiver(mMuteChangeReceiver,
                new IntentFilter(AudioManager.STREAM_MUTE_CHANGED_ACTION));
        mContext.registerReceiver(mSpeakerPhoneChangeReceiver,
                new IntentFilter(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED));

+46 −0
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@
package com.android.server.telecom.tests;

import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.IAudioService;
import android.os.HandlerThread;
@@ -149,6 +152,49 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase {
        assertNotNull(stateMachine);
    }

    @MediumTest
    @Test
    public void testStreamRingMuteChange() {
        CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
                mContext,
                mockCallsManager,
                mockBluetoothRouteManager,
                mockWiredHeadsetManager,
                mockStatusBarNotifier,
                mAudioServiceFactory,
                CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED,
                mThreadHandler.getLooper());
        stateMachine.setCallAudioManager(mockCallAudioManager);
        CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER,
                CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER);
        stateMachine.initialize(initState);

        // Make sure we register a receiver for the STREAM_MUTE_CHANGED_ACTION so we can see if the
        // ring stream unmutes.
        ArgumentCaptor<BroadcastReceiver> brCaptor = ArgumentCaptor.forClass(
                BroadcastReceiver.class);
        ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass(IntentFilter.class);
        verify(mContext, times(3)).registerReceiver(brCaptor.capture(), filterCaptor.capture());
        boolean foundValid = false;
        for (int ix = 0; ix < brCaptor.getAllValues().size(); ix++) {
            BroadcastReceiver receiver = brCaptor.getAllValues().get(ix);
            IntentFilter filter = filterCaptor.getAllValues().get(ix);
            if (!filter.hasAction(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
                continue;
            }

            // Fake out a call to the broadcast receiver and make sure we call into audio manager
            // to trigger re-evaluation of ringing.
            Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
            intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false);
            intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, AudioManager.STREAM_RING);
            receiver.onReceive(mContext, intent);
            verify(mockCallAudioManager).onRingerModeChange();
            foundValid = true;
        }
        assertTrue(foundValid);
    }

    @MediumTest
    @Test
    public void testSpeakerPersistence() {