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

Commit 5a2d8b5e authored by Grace Jia's avatar Grace Jia
Browse files

Use STREAM_VOICE_CALL when device connected to le BT device or hearing

aid device to play tones get from ToneGenerator.

Special tone like ringback tones and call waiting tone need to be routed
to STREAM_VOICE_CALL to play properly.

Bug: 231412487
Test: InCallTonePlayerTest
Change-Id: Idc96edf4904cf96c62813401be945031169b3d71
parent 2385dc0b
Loading
Loading
Loading
Loading
+10 −14
Original line number Diff line number Diff line
@@ -263,7 +263,6 @@ public class InCallTonePlayer extends Thread {
            final int mediaResourceId; // The resourceId of the tone to play.  Used for media-based
                                      // tones.

            int stream = STREAM_INVALID;
            switch (mToneId) {
                case TONE_BUSY:
                    // TODO: CDMA-specific tones
@@ -331,12 +330,6 @@ public class InCallTonePlayer extends Thread {
                    toneVolume = RELATIVE_VOLUME_HIPRI;
                    toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS;
                    mediaResourceId = TONE_RESOURCE_ID_UNDEFINED;
                    // When a hearing aid device or a LE audio device is used, ring back tone should
                    // use STREAM_VOICE_CALL
                    if (mCallAudioRoutePeripheralAdapter.isLeAudioDeviceOn()
                            || mCallAudioRoutePeripheralAdapter.isHearingAidDeviceOn()) {
                        stream = AudioManager.STREAM_VOICE_CALL;
                    }
                    break;
                case TONE_UNOBTAINABLE_NUMBER:
                    toneType = ToneGenerator.TONE_SUP_ERROR;
@@ -368,15 +361,18 @@ public class InCallTonePlayer extends Thread {
                    throw new IllegalStateException("Bad toneId: " + mToneId);
            }

            // Don't override already valid stream values
            if (stream == STREAM_INVALID) {
                stream = AudioManager.STREAM_VOICE_CALL;
            int stream = AudioManager.STREAM_VOICE_CALL;
            if (mCallAudioRoutePeripheralAdapter.isBluetoothAudioOn()) {
                stream = AudioManager.STREAM_BLUETOOTH_SCO;
            }
            }

            if (toneType != ToneGenerator.TONE_UNKNOWN) {
                if (stream == AudioManager.STREAM_BLUETOOTH_SCO) {
                    // Override audio stream for BT le device and hearing aid device
                    if (mCallAudioRoutePeripheralAdapter.isLeAudioDeviceOn()
                            || mCallAudioRoutePeripheralAdapter.isHearingAidDeviceOn()) {
                        stream = AudioManager.STREAM_VOICE_CALL;
                    }
                }
                playToneGeneratorTone(stream, toneVolume, toneType, toneLengthMillis);
            } else if (mediaResourceId != TONE_RESOURCE_ID_UNDEFINED) {
                playMediaTone(stream, mediaResourceId);
+53 −20
Original line number Diff line number Diff line
@@ -16,15 +16,13 @@

package com.android.server.telecom.tests;

import static com.android.server.telecom.bluetooth.BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
@@ -37,8 +35,6 @@ import android.media.MediaPlayer;
import android.media.ToneGenerator;
import android.test.suitebuilder.annotation.SmallTest;

import androidx.test.filters.FlakyTest;

import com.android.server.telecom.CallAudioManager;
import com.android.server.telecom.CallAudioRoutePeripheralAdapter;
import com.android.server.telecom.CallAudioRouteStateMachine;
@@ -55,12 +51,12 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;

@RunWith(JUnit4.class)
public class InCallTonePlayerTest extends TelecomTestCase {

    private static final long TEST_TIMEOUT = 5000L;
    private InCallTonePlayer.Factory mFactory;
    private CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter;

@@ -124,6 +120,7 @@ public class InCallTonePlayerTest extends TelecomTestCase {

        when(mToneGeneratorFactory.get(anyInt(), anyInt())).thenReturn(mToneGenerator);
        when(mMediaPlayerFactory.get(anyInt(), any())).thenReturn(mMediaPlayerAdapter);
        doNothing().when(mCallAudioManager).setIsTonePlaying(anyBoolean());

        mCallAudioRoutePeripheralAdapter = new CallAudioRoutePeripheralAdapter(
                mCallAudioRouteStateMachine, mBluetoothRouteManager, mWiredHeadsetManager,
@@ -158,12 +155,12 @@ public class InCallTonePlayerTest extends TelecomTestCase {
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        assertTrue(mInCallTonePlayer.startTone());
        // Verify we did play a tone.
        verify(mMediaPlayerFactory, timeout(5000)).get(anyInt(), any());
        verify(mMediaPlayerFactory, timeout(TEST_TIMEOUT)).get(anyInt(), any());
        verify(mCallAudioManager).setIsTonePlaying(eq(true));

        mInCallTonePlayer.stopTone();
        // Timeouts due to threads!
        verify(mCallAudioManager, timeout(5000)).setIsTonePlaying(eq(false));
        verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(eq(false));

        // Correctness check: ensure we can't start the tone again.
        assertFalse(mInCallTonePlayer.startTone());
@@ -175,15 +172,15 @@ public class InCallTonePlayerTest extends TelecomTestCase {
        mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_RING_BACK);
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        assertTrue(mInCallTonePlayer.startTone());
        verify(mToneGenerator, timeout(5000)).startTone(anyInt());
        verify(mToneGenerator, timeout(TEST_TIMEOUT)).startTone(anyInt());
        verify(mCallAudioManager).setIsTonePlaying(eq(true));

        mInCallTonePlayer.stopTone();
        // Timeouts due to threads!
        verify(mCallAudioManager, timeout(5000)).setIsTonePlaying(eq(false));
        verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(eq(false));
        // Ideally it would be nice to verify this, however release is a native method so appears to
        // cause flakiness when testing on Cuttlefish.
        // verify(mToneGenerator, timeout(5000)).release();
        // verify(mToneGenerator, timeout(TEST_TIMEOUT)).release();

        // Correctness check: ensure we can't start the tone again.
        assertFalse(mInCallTonePlayer.startTone());
@@ -196,13 +193,13 @@ public class InCallTonePlayerTest extends TelecomTestCase {
        assertTrue(mInCallTonePlayer.startTone());

        // Verify we did play a tone.
        verify(mMediaPlayerFactory, timeout(5000)).get(anyInt(), any());
        verify(mCallAudioManager, timeout(5000)).setIsTonePlaying(eq(true));
        verify(mMediaPlayerFactory, timeout(TEST_TIMEOUT)).get(anyInt(), any());
        verify(mCallAudioManager, timeout(TEST_TIMEOUT)).setIsTonePlaying(eq(true));
    }

    @SmallTest
    @Test
    public void testRingbackAudioStreamHeadset() {
    public void testRingbackToneAudioStreamHeadset() {
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        mBluetoothDeviceManager.setBluetoothRouteManager(mBluetoothRouteManager);
        when(mBluetoothRouteManager.getBluetoothAudioConnectedDevice()).thenReturn(mDevice);
@@ -213,14 +210,32 @@ public class InCallTonePlayerTest extends TelecomTestCase {

        mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_RING_BACK);
        assertTrue(mInCallTonePlayer.startTone());
        verify(mToneGeneratorFactory, timeout(5000))
        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_BLUETOOTH_SCO), anyInt());
        verify(mCallAudioManager).setIsTonePlaying(eq(true));
    }

    @SmallTest
    @Test
    public void testCallWaitingToneAudioStreamHeadset() {
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        mBluetoothDeviceManager.setBluetoothRouteManager(mBluetoothRouteManager);
        when(mBluetoothRouteManager.getBluetoothAudioConnectedDevice()).thenReturn(mDevice);
        when(mBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(true);

        when(mBluetoothRouteManager.isCachedLeAudioDevice(mDevice)).thenReturn(false);
        when(mBluetoothRouteManager.isCachedHearingAidDevice(mDevice)).thenReturn(false);

        mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING);
        assertTrue(mInCallTonePlayer.startTone());
        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_BLUETOOTH_SCO), anyInt());
        verify(mCallAudioManager, timeout(5000)).setIsTonePlaying(eq(true));
        verify(mCallAudioManager).setIsTonePlaying(eq(true));
    }

    @SmallTest
    @Test
    public void testRingbackAudioStreamHearingAid() {
    public void testRingbackToneAudioStreamHearingAid() {
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        mBluetoothDeviceManager.setBluetoothRouteManager(mBluetoothRouteManager);
        when(mBluetoothRouteManager.getBluetoothAudioConnectedDevice()).thenReturn(mDevice);
@@ -231,8 +246,26 @@ public class InCallTonePlayerTest extends TelecomTestCase {

        mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_RING_BACK);
        assertTrue(mInCallTonePlayer.startTone());
        verify(mToneGeneratorFactory, timeout(5000))
        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_VOICE_CALL), anyInt());
        verify(mCallAudioManager, timeout(5000)).setIsTonePlaying(eq(true));
        verify(mCallAudioManager).setIsTonePlaying(eq(true));
    }

    @SmallTest
    @Test
    public void testCallWaitingToneAudioStreamHearingAid() {
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        mBluetoothDeviceManager.setBluetoothRouteManager(mBluetoothRouteManager);
        when(mBluetoothRouteManager.getBluetoothAudioConnectedDevice()).thenReturn(mDevice);
        when(mBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(true);

        when(mBluetoothRouteManager.isCachedLeAudioDevice(mDevice)).thenReturn(false);
        when(mBluetoothRouteManager.isCachedHearingAidDevice(mDevice)).thenReturn(true);

        mInCallTonePlayer = mFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING);
        assertTrue(mInCallTonePlayer.startTone());
        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_VOICE_CALL), anyInt());
        verify(mCallAudioManager).setIsTonePlaying(eq(true));
    }
}