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

Commit 7c417153 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Use STREAM_VOICE_CALL for ToneGenerator" into main

parents 677d849b e19f4524
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -26,3 +26,14 @@ flag {
      purpose: PURPOSE_BUGFIX
    }
}

# OWNER=breadley TARGET=24Q4
flag {
  name: "use_stream_voice_call_tones"
  namespace: "telecom"
  description: "Use STREAM_VOICE_CALL only for ToneGenerator"
  bug: "363262590"
  metadata {
      purpose: PURPOSE_BUGFIX
    }
}
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -680,7 +680,7 @@ public class CallsManager extends Call.ListenerBase
                                        audioManager.generateAudioSessionId()));
        InCallTonePlayer.Factory playerFactory = new InCallTonePlayer.Factory(
                callAudioRoutePeripheralAdapter, lock, toneGeneratorFactory, mediaPlayerFactory,
                () -> audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0);
                () -> audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0, featureFlags);

        SystemSettingsUtil systemSettingsUtil = new SystemSettingsUtil();
        RingtoneFactory ringtoneFactory = new RingtoneFactory(this, context, featureFlags);
+36 −14
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.telecom.Logging.Runnable;
import android.telecom.Logging.Session;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.telecom.flags.FeatureFlags;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -54,15 +55,18 @@ public class InCallTonePlayer extends Thread {
        private final ToneGeneratorFactory mToneGeneratorFactory;
        private final MediaPlayerFactory mMediaPlayerFactory;
        private final AudioManagerAdapter mAudioManagerAdapter;
        private final FeatureFlags mFeatureFlags;

        public Factory(CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter,
                TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory,
                MediaPlayerFactory mediaPlayerFactory, AudioManagerAdapter audioManagerAdapter) {
                MediaPlayerFactory mediaPlayerFactory, AudioManagerAdapter audioManagerAdapter,
                FeatureFlags flags) {
            mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter;
            mLock = lock;
            mToneGeneratorFactory = toneGeneratorFactory;
            mMediaPlayerFactory = mediaPlayerFactory;
            mAudioManagerAdapter = audioManagerAdapter;
            mFeatureFlags = flags;
        }

        public void setCallAudioManager(CallAudioManager callAudioManager) {
@@ -72,7 +76,7 @@ public class InCallTonePlayer extends Thread {
        public InCallTonePlayer createPlayer(Call call, int tone) {
            return new InCallTonePlayer(call, tone, mCallAudioManager,
                    mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory,
                    mMediaPlayerFactory, mAudioManagerAdapter);
                    mMediaPlayerFactory, mAudioManagerAdapter, mFeatureFlags);
        }
    }

@@ -216,6 +220,7 @@ public class InCallTonePlayer extends Thread {
    private final ToneGeneratorFactory mToneGenerator;
    private final MediaPlayerFactory mMediaPlayerFactory;
    private final AudioManagerAdapter mAudioManagerAdapter;
    private final FeatureFlags mFeatureFlags;

    /**
     * Latch used for awaiting on playback, which may be interrupted if the tone is stopped from
@@ -236,7 +241,8 @@ public class InCallTonePlayer extends Thread {
            TelecomSystem.SyncRoot lock,
            ToneGeneratorFactory toneGeneratorFactory,
            MediaPlayerFactory mediaPlayerFactor,
            AudioManagerAdapter audioManagerAdapter) {
            AudioManagerAdapter audioManagerAdapter,
            FeatureFlags flags) {
        mCall = call;
        mState = STATE_OFF;
        mToneId = toneId;
@@ -246,6 +252,7 @@ public class InCallTonePlayer extends Thread {
        mToneGenerator = toneGeneratorFactory;
        mMediaPlayerFactory = mediaPlayerFactor;
        mAudioManagerAdapter = audioManagerAdapter;
        mFeatureFlags = flags;
    }

    /** {@inheritDoc} */
@@ -364,6 +371,27 @@ public class InCallTonePlayer extends Thread {
                    throw new IllegalStateException("Bad toneId: " + mToneId);
            }

            int stream = getStreamType(toneType);
            if (toneType != ToneGenerator.TONE_UNKNOWN) {
                playToneGeneratorTone(stream, toneVolume, toneType, toneLengthMillis);
            } else if (mediaResourceId != TONE_RESOURCE_ID_UNDEFINED) {
                playMediaTone(stream, mediaResourceId);
            }
        } finally {
            cleanUpTonePlayer();
            Log.endSession();
        }
    }

    /**
     * @param toneType The ToneGenerator tone type
     * @return The ToneGenerator stream type
     */
    private int getStreamType(int toneType) {
        if (mFeatureFlags.useStreamVoiceCallTones()) {
            return AudioManager.STREAM_VOICE_CALL;
        }

        int stream = AudioManager.STREAM_VOICE_CALL;
        if (mCallAudioRoutePeripheralAdapter.isBluetoothAudioOn()) {
            stream = AudioManager.STREAM_BLUETOOTH_SCO;
@@ -376,14 +404,8 @@ public class InCallTonePlayer extends Thread {
                    stream = AudioManager.STREAM_VOICE_CALL;
                }
            }
                playToneGeneratorTone(stream, toneVolume, toneType, toneLengthMillis);
            } else if (mediaResourceId != TONE_RESOURCE_ID_UNDEFINED) {
                playMediaTone(stream, mediaResourceId);
            }
        } finally {
            cleanUpTonePlayer();
            Log.endSession();
        }
        return stream;
    }

    /**
+73 −30
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.media.AudioManager;
import android.media.MediaPlayer;
@@ -43,10 +42,10 @@ import com.android.server.telecom.CallAudioRouteStateMachine;
import com.android.server.telecom.DockManager;
import com.android.server.telecom.InCallTonePlayer;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;
import com.android.server.telecom.WiredHeadsetManager;
import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.flags.FeatureFlags;

import org.junit.After;
import org.junit.Before;
@@ -64,7 +63,6 @@ public class InCallTonePlayerTest extends TelecomTestCase {

    @Mock private BluetoothRouteManager mBluetoothRouteManager;
    @Mock private CallAudioRouteStateMachine mCallAudioRouteStateMachine;
    @Mock private Timeouts.Adapter mTimeoutsAdapter;
    @Mock private BluetoothDeviceManager mBluetoothDeviceManager;
    @Mock private TelecomSystem.SyncRoot mLock;
    @Mock private ToneGenerator mToneGenerator;
@@ -73,7 +71,6 @@ public class InCallTonePlayerTest extends TelecomTestCase {
    @Mock private DockManager mDockManager;
    @Mock private AsyncRingtonePlayer mRingtonePlayer;
    @Mock private BluetoothDevice mDevice;
    @Mock private BluetoothAdapter mBluetoothAdapter;

    private InCallTonePlayer.MediaPlayerAdapter mMediaPlayerAdapter =
            new InCallTonePlayer.MediaPlayerAdapter() {
@@ -115,7 +112,6 @@ public class InCallTonePlayerTest extends TelecomTestCase {
    private CallAudioManager mCallAudioManager;
    @Mock
    private Call mCall;

    private InCallTonePlayer mInCallTonePlayer;

    @Override
@@ -131,7 +127,7 @@ public class InCallTonePlayerTest extends TelecomTestCase {
                mCallAudioRouteStateMachine, mBluetoothRouteManager, mWiredHeadsetManager,
                mDockManager, mRingtonePlayer);
        mFactory = new InCallTonePlayer.Factory(mCallAudioRoutePeripheralAdapter, mLock,
                mToneGeneratorFactory, mMediaPlayerFactory, mAudioManagerAdapter);
                mToneGeneratorFactory, mMediaPlayerFactory, mAudioManagerAdapter, mFeatureFlags);
        mFactory.setCallAudioManager(mCallAudioManager);
        mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_CALL_ENDED);
    }
@@ -209,55 +205,78 @@ public class InCallTonePlayerTest extends TelecomTestCase {
                eq(true));
    }

    /**
     * Only applicable when {@link FeatureFlags#useStreamVoiceCallTones()} is false and we use
     * STREAM_BLUETOOTH_SCO for tones.
     */
    @SmallTest
    @Test
    public void testRingbackToneAudioStreamHeadset() {
        when(mFeatureFlags.useStreamVoiceCallTones()).thenReturn(false);
        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);
        setConnectedBluetoothDevice(false /*isLe*/, false /*isHearingAid*/);

        mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_RING_BACK);
        assertTrue(mInCallTonePlayer.startTone());

        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_BLUETOOTH_SCO), anyInt());
        verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true));
    }

    /**
     * Only applicable when {@link FeatureFlags#useStreamVoiceCallTones()} is false and we use
     * STREAM_BLUETOOTH_SCO for tones.
     */
    @SmallTest
    @Test
    public void testCallWaitingToneAudioStreamHeadset() {
        when(mFeatureFlags.useStreamVoiceCallTones()).thenReturn(false);
        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);
        setConnectedBluetoothDevice(false /*isLe*/, false /*isHearingAid*/);

        mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_CALL_WAITING);
        assertTrue(mInCallTonePlayer.startTone());

        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_BLUETOOTH_SCO), anyInt());
        verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true));
    }


    /**
     * Only applicable when {@link FeatureFlags#useStreamVoiceCallTones()} is true and we use
     * STREAM_VOICE_CALL for ALL tones.
     */
    @SmallTest
    @Test
    public void testRingbackToneAudioStreamHearingAid() {
    public void testRingbackToneAudioStreamSco() {
        when(mFeatureFlags.useStreamVoiceCallTones()).thenReturn(true);
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        mBluetoothDeviceManager.setBluetoothRouteManager(mBluetoothRouteManager);
        when(mBluetoothRouteManager.getBluetoothAudioConnectedDevice()).thenReturn(mDevice);
        when(mBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(true);
        setConnectedBluetoothDevice(false /*isLe*/, false /*isHearingAid*/);

        mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_RING_BACK);
        assertTrue(mInCallTonePlayer.startTone());

        when(mBluetoothRouteManager.isCachedLeAudioDevice(mDevice)).thenReturn(false);
        when(mBluetoothRouteManager.isCachedHearingAidDevice(mDevice)).thenReturn(true);
        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_VOICE_CALL), anyInt());
        verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true));
    }

    /**
     * Only applicable when {@link FeatureFlags#useStreamVoiceCallTones()} is true and we use
     * STREAM_VOICE_CALL for ALL tones.
     */
    @SmallTest
    @Test
    public void testRingbackToneAudioStreamLe() {
        when(mFeatureFlags.useStreamVoiceCallTones()).thenReturn(true);
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        setConnectedBluetoothDevice(true /*isLe*/, false /*isHearingAid*/);

        mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_RING_BACK);
        assertTrue(mInCallTonePlayer.startTone());

        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_VOICE_CALL), anyInt());
        verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true));
@@ -265,19 +284,43 @@ public class InCallTonePlayerTest extends TelecomTestCase {

    @SmallTest
    @Test
    public void testCallWaitingToneAudioStreamHearingAid() {
    public void testRingbackToneAudioStreamHearingAid() {
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        mBluetoothDeviceManager.setBluetoothRouteManager(mBluetoothRouteManager);
        when(mBluetoothRouteManager.getBluetoothAudioConnectedDevice()).thenReturn(mDevice);
        when(mBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(true);
        setConnectedBluetoothDevice(false /*isLe*/, true /*isHearingAid*/);

        mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_RING_BACK);
        assertTrue(mInCallTonePlayer.startTone());

        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_VOICE_CALL), anyInt());
        verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true));
    }

        when(mBluetoothRouteManager.isCachedLeAudioDevice(mDevice)).thenReturn(false);
        when(mBluetoothRouteManager.isCachedHearingAidDevice(mDevice)).thenReturn(true);
    @SmallTest
    @Test
    public void testCallWaitingToneAudioStreamHearingAid() {
        when(mAudioManagerAdapter.isVolumeOverZero()).thenReturn(true);
        setConnectedBluetoothDevice(false /*isLe*/, true /*isHearingAid*/);

        mInCallTonePlayer = mFactory.createPlayer(mCall, InCallTonePlayer.TONE_CALL_WAITING);
        assertTrue(mInCallTonePlayer.startTone());

        verify(mToneGeneratorFactory, timeout(TEST_TIMEOUT))
                .get(eq(AudioManager.STREAM_VOICE_CALL), anyInt());
        verify(mCallAudioManager).setIsTonePlaying(any(Call.class), eq(true));
    }

    /**
     * Set a connected BT device. If not LE or Hearing Aid, it will be configured as SCO
     * @param isLe true if LE
     * @param isHearingAid true if hearing aid
     */
    private void setConnectedBluetoothDevice(boolean isLe, boolean isHearingAid) {
        mBluetoothDeviceManager.setBluetoothRouteManager(mBluetoothRouteManager);
        when(mBluetoothRouteManager.getBluetoothAudioConnectedDevice()).thenReturn(mDevice);
        when(mBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(true);

        when(mBluetoothRouteManager.isCachedLeAudioDevice(mDevice)).thenReturn(isLe);
        when(mBluetoothRouteManager.isCachedHearingAidDevice(mDevice)).thenReturn(isHearingAid);
    }
}