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

Commit cc4f8bb3 authored by Grant Menke's avatar Grant Menke
Browse files

Use AudioManager API instead of manually checking ringing volume.

This CL ensures that the Ringer class relies on the AudioManager#shouldNotificationSoundPlay API instead of manually checking ringing volume when determining if a ringtone should be played audibly for an MT call. This CL also adds the feature flag for all of the go/ring-my-car Telecom feature work.

Bug: 348707841
Flag: com.android.server.telecom.flags.ensure_in_car_ringing
Test: atest RingerTest

Change-Id: I7df60d54e4e6e8ede69e807a6091647104ea9863
parent 98e2a69f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@
    <!-- Required to determine source of ongoing audio recordings. -->
    <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING"/>
    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
    <!-- Required to query the audio framework to determine if a notification sound should play. -->
    <uses-permission android:name="android.permission.QUERY_AUDIO_STATE"/>
    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
    <!-- Required to check for direct to voicemail, to load custom ringtones for incoming calls
        which are specified on a per contact basis, and also to determine user preferred
+8 −0
Original line number Diff line number Diff line
@@ -8,3 +8,11 @@ flag {
  description: "Gates whether to use a serialized, device-specific ring vibration."
  bug: "282113261"
}

# OWNER=grantmenke TARGET=24Q4
flag {
  name: "ensure_in_car_ringing"
  namespace: "telecom"
  description: "Gates whether to ensure that when a user is in their car, they are able to hear ringing for an incoming call."
  bug: "348708398"
}
 No newline at end of file
+11 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.app.NotificationManager;
import android.app.Person;
import android.content.Context;
import android.content.res.Resources;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.VolumeShaper;
@@ -704,7 +705,16 @@ public class Ringer {

        LogUtils.EventTimer timer = new EventTimer();

        boolean isVolumeOverZero = mAudioManager.getStreamVolume(AudioManager.STREAM_RING) > 0;
        boolean isVolumeOverZero;

        if (mFlags.ensureInCarRinging()) {
            AudioAttributes aa = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();
            isVolumeOverZero = mAudioManager.shouldNotificationSoundPlay(aa);
        } else {
            isVolumeOverZero = mAudioManager.getStreamVolume(AudioManager.STREAM_RING) > 0;
        }
        timer.record("isVolumeOverZero");
        boolean shouldRingForContact = shouldRingForContact(call);
        timer.record("shouldRingForContact");
+4 −1
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@
    <!-- Used to register NotificationListenerService -->
    <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />

    <!-- Used to query the audio framework to determine if a notification sound should play. -->
    <uses-permission android:name="android.permission.QUERY_AUDIO_STATE"/>

    <application android:label="@string/app_name"
                 android:debuggable="true">
        <uses-library android:name="android.test.runner" />
+61 −0
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ public class RingerTest extends TelecomTestCase {
        super.setUp();
        mContext = spy(mComponentContextFixture.getTestDouble().getApplicationContext());
        when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(true);
        when(mFeatureFlags.ensureInCarRinging()).thenReturn(false);
        doReturn(URI_VIBRATION_EFFECT).when(spyVibrationEffectProxy).get(any(), any());
        when(mockPlayerFactory.createPlayer(any(Call.class), anyInt())).thenReturn(mockTonePlayer);
        mockAudioManager = mContext.getSystemService(AudioManager.class);
@@ -436,6 +437,66 @@ public class RingerTest extends TelecomTestCase {
                any(VibrationAttributes.class));
    }

    @SmallTest
    @Test
    public void testAudibleRingWhenNotificationSoundShouldPlay() throws Exception {
        when(mFeatureFlags.ensureInCarRinging()).thenReturn(true);
        Ringtone mockRingtone = ensureRingtoneMocked();

        mRingerUnderTest.startCallWaiting(mockCall1);
        AudioAttributes aa = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();
        // Set AudioManager#shouldNotificationSoundPlay to true:
        when(mockAudioManager.shouldNotificationSoundPlay(aa)).thenReturn(true);
        enableVibrationWhenRinging();

        // This will set AudioManager#getStreamVolume to 0. This test ensures that whether a
        // ringtone is audible is controlled by AudioManager#shouldNotificationSoundPlay instead:
        ensureRingerIsNotAudible();

        // Ensure an audible ringtone is played:
        assertTrue(startRingingAndWaitForAsync(mockCall2, false));
        verify(mockTonePlayer).stopTone();
        verify(mockRingtoneFactory, atLeastOnce()).getRingtone(any(Call.class),
                nullable(VolumeShaper.Configuration.class), anyBoolean());
        verifyNoMoreInteractions(mockRingtoneFactory);
        verify(mockRingtone).play();

        // Ensure a vibration plays:
        verify(mockVibrator).vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
    }

    @SmallTest
    @Test
    public void testNoAudibleRingWhenNotificationSoundShouldNotPlay() throws Exception {
        when(mFeatureFlags.ensureInCarRinging()).thenReturn(true);
        Ringtone mockRingtone = ensureRingtoneMocked();

        mRingerUnderTest.startCallWaiting(mockCall1);
        AudioAttributes aa = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();
        // Set AudioManager#shouldNotificationSoundPlay to false:
        when(mockAudioManager.shouldNotificationSoundPlay(aa)).thenReturn(false);
        enableVibrationWhenRinging();

        // This will set AudioManager#getStreamVolume to 100. This test ensures that whether a
        // ringtone is audible is controlled by AudioManager#shouldNotificationSoundPlay instead:
        ensureRingerIsAudible();

        // Ensure no audible ringtone is played:
        assertFalse(startRingingAndWaitForAsync(mockCall2, false));
        verify(mockTonePlayer).stopTone();
        // Ensure a silent haptics only ringtone is played:
        verify(mockRingtoneFactory, atLeastOnce()).getHapticOnlyRingtone();
        verifyNoMoreInteractions(mockRingtoneFactory);
        verify(mockRingtone).play();

        // Ensure a vibration plays:
        verify(mockVibrator).vibrate(any(VibrationEffect.class), any(VibrationAttributes.class));
    }

    @SmallTest
    @Test
    public void testVibrateButNoRingForNullRingtone() throws Exception {