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

Commit ec461ec8 authored by Yiwen Chen's avatar Yiwen Chen Committed by Android (Google) Code Review
Browse files

Merge "Make Telephony support ramping ringer."

parents 50dd80b1 895ecb17
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.server.telecom;

import android.annotation.Nullable;
import android.media.Ringtone;
import android.media.VolumeShaper;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
@@ -67,15 +69,22 @@ public class AsyncRingtonePlayer {
        mShouldPauseBetweenRepeat = shouldPauseBetweenRepeat;
    }

    /** Plays the ringtone. */
    public void play(RingtoneFactory factory, Call incomingCall) {
    /** Plays the ringtone with ramping ringer if required. */
    public void play(RingtoneFactory factory, Call incomingCall,
            @Nullable VolumeShaper.Configuration volumeShaperConfig) {
        Log.d(this, "Posting play.");
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = factory;
        args.arg2 = incomingCall;
        args.arg3 = volumeShaperConfig;
        postMessage(EVENT_PLAY, true /* shouldCreateHandler */, args);
    }

    /** Plays the ringtone. */
    public void play(RingtoneFactory factory, Call incomingCall) {
        play(factory, incomingCall, null);
    }

    /** Stops playing the ringtone. */
    public void stop() {
        Log.d(this, "Posting stop.");
@@ -136,6 +145,7 @@ public class AsyncRingtonePlayer {
    private void handlePlay(SomeArgs args) {
        RingtoneFactory factory = (RingtoneFactory) args.arg1;
        Call incomingCall = (Call) args.arg2;
        VolumeShaper.Configuration volumeShaperConfig = (VolumeShaper.Configuration) args.arg3;
        args.recycle();
        // don't bother with any of this if there is an EVENT_STOP waiting.
        if (mHandler.hasMessages(EVENT_STOP)) {
@@ -153,7 +163,7 @@ public class AsyncRingtonePlayer {
        Log.i(this, "Play ringtone.");

        if (mRingtone == null) {
            mRingtone = factory.getRingtone(incomingCall);
            mRingtone = factory.getRingtone(incomingCall, volumeShaperConfig);
            if (mRingtone == null) {
                Uri ringtoneUri = incomingCall.getRingtone();
                String ringtoneUriString = (ringtoneUri == null) ? "null" :
@@ -183,7 +193,6 @@ public class AsyncRingtonePlayer {
        if (mRingtone == null) {
            return;
        }

        if (mRingtone.isPlaying()) {
            Log.d(this, "Ringtone already playing.");
        } else {
+27 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.telecom.TelecomManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.VolumeShaper;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
@@ -82,11 +83,17 @@ public class Ringer {

    private static final int REPEAT_SIMPLE_VIBRATION_AT = 1;

    private static final int DEFAULT_RAMPING_RINGER_DURATION = 15000;  // 15 seconds

    private static int rampingRingerDuration = -1;

    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
            .build();

    private static VolumeShaper.Configuration volumeShaperConfig;

    /**
     * Used to keep ordering of unanswered incoming calls. There can easily exist multiple incoming
     * calls and explicit ordering is useful for maintaining the proper state of the ringer.
@@ -197,7 +204,26 @@ public class Ringer {
            // call (for the purposes of direct-to-voicemail), the information about custom
            // ringtones should be available by the time this code executes. We can safely
            // request the custom ringtone from the call and expect it to be current.
            mRingtonePlayer.play(mRingtoneFactory, foregroundCall);
            if (mSystemSettingsUtil.applyRampingRinger(mContext)
                || mSystemSettingsUtil.enableRampingRingerFromDeviceConfig()) {
                Log.i(this, "start ramping ringer.");
                int previousRampingRingerDuration = rampingRingerDuration;
                rampingRingerDuration =
                    mSystemSettingsUtil.getRampingRingerDuration() > 0
                        ? mSystemSettingsUtil.getRampingRingerDuration()
                        : DEFAULT_RAMPING_RINGER_DURATION;
                if ((rampingRingerDuration != previousRampingRingerDuration)
                    || volumeShaperConfig == null) {
                    volumeShaperConfig = new VolumeShaper.Configuration.Builder()
                        .setDuration(rampingRingerDuration)
                        .setCurve(new float[] {0.f, 1.f}, new float[] {0.f, 1.f})
                        .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
                        .build();
                }
                mRingtonePlayer.play(mRingtoneFactory, foregroundCall, volumeShaperConfig);
            } else {
                mRingtonePlayer.play(mRingtoneFactory, foregroundCall, null);
            }
            effect = getVibrationEffectForCall(mRingtoneFactory, foregroundCall);
        } else {
            String reason = String.format(
+11 −3
Original line number Diff line number Diff line
@@ -16,12 +16,14 @@

package com.android.server.telecom;

import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.media.RingtoneManager;
import android.media.Ringtone;
import android.media.VolumeShaper;
import android.net.Uri;
import android.os.UserHandle;
import android.os.UserManager;
@@ -52,7 +54,8 @@ public class RingtoneFactory {
        mCallsManager = callsManager;
    }

    public Ringtone getRingtone(Call incomingCall) {
    public Ringtone getRingtone(Call incomingCall,
            @Nullable VolumeShaper.Configuration volumeShaperConfig) {
        // Use the default ringtone of the work profile if the contact is a work profile contact.
        Context userContext = isWorkContact(incomingCall) ?
                getWorkProfileContextForUser(mCallsManager.getCurrentUserHandle()) :
@@ -62,7 +65,7 @@ public class RingtoneFactory {

        if(ringtoneUri != null && userContext != null) {
            // Ringtone URI is explicitly specified. First, try to create a Ringtone with that.
            ringtone = RingtoneManager.getRingtone(userContext, ringtoneUri);
            ringtone = RingtoneManager.getRingtone(userContext, ringtoneUri, volumeShaperConfig);
        }
        if(ringtone == null) {
            // Contact didn't specify ringtone or custom Ringtone creation failed. Get default
@@ -78,7 +81,8 @@ public class RingtoneFactory {
            if (defaultRingtoneUri == null) {
                return null;
            }
            ringtone = RingtoneManager.getRingtone(contextToUse, defaultRingtoneUri);
            ringtone = RingtoneManager.getRingtone(
                contextToUse, defaultRingtoneUri, volumeShaperConfig);
        }
        if (ringtone != null) {
            ringtone.setStreamType(AudioManager.STREAM_RING);
@@ -86,6 +90,10 @@ public class RingtoneFactory {
        return ringtone;
    }

    public Ringtone getRingtone(Call incomingCall) {
        return getRingtone(incomingCall, null);
    }

    private Context getWorkProfileContextForUser(UserHandle userHandle) {
        // UserManager.getEnabledProfiles returns the enabled profiles along with the user's handle
        // itself (so we must filter out the user).
+42 −0
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
package com.android.server.telecom;

import android.content.Context;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.telecom.Log;

import com.android.internal.annotations.VisibleForTesting;

@@ -46,4 +48,44 @@ public class SystemSettingsUtil {
        return Settings.System.putInt(context.getContentResolver(),
                Settings.System.DEBUG_ENABLE_ENHANCED_CALL_BLOCKING, enabled ? 1 : 0);
    }

    public boolean applyRampingRinger(Context context) {
        return Settings.Global.getInt(context.getContentResolver(),
            Settings.Global.APPLY_RAMPING_RINGER, 0) == 1;
    }

    public boolean enableRampingRingerFromDeviceConfig() {
        String enableRampingRinger = DeviceConfig.getProperty(
            DeviceConfig.Telephony.NAMESPACE,
            DeviceConfig.Telephony.PROPERTY_ENABLE_RAMPING_RINGER);
        if (enableRampingRinger == null) {
            Log.i(this, "DeviceConfig.Telephony.PROPERTY_ENABLE_RAMPING_RINGER is null");
            return false;
        }
        try {
            return Boolean.valueOf(enableRampingRinger);
        } catch (Exception e) {
            Log.wtf(this,
                "Error paring DeviceConfig.Telephony.PROPERTY_ENABLE_RAMPING_RINGER: " + e);
            return false;
        }
    }

    public int getRampingRingerDuration() {
        String rampingRingerDuration = DeviceConfig.getProperty(
            DeviceConfig.Telephony.NAMESPACE,
            DeviceConfig.Telephony.PROPERTY_RAMPING_RINGER_DURATION);
        if (rampingRingerDuration == null) {
            Log.i(this, "DeviceConfig.Telephony.PROPERTY_RAMPING_RINGER_DURATION is null");
            return -1;
        }
        try {
            return Integer.parseInt(rampingRingerDuration);
        } catch (Exception e) {
            Log.wtf(this,
                "Error paring DeviceConfig.Telephony.PROPERTY_RAMPING_RINGER_DURATION: " + e);
            return -1;
        }
    }
}
+19 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.VolumeShaper;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
@@ -257,7 +258,7 @@ public class RingerTest extends TelecomTestCase {
        enableVibrationWhenRinging();
        assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
        verify(mockTonePlayer).stopTone();
        verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class));
        verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class), eq(null));
        verify(mockVibrator).vibrate(eq(spyVibrationEffectProxy.get(FAKE_RINGTONE_URI, mContext)),
                any(AudioAttributes.class));
    }
@@ -270,11 +271,23 @@ public class RingerTest extends TelecomTestCase {
        enableVibrationOnlyWhenNotRinging();
        assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
        verify(mockTonePlayer).stopTone();
        verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class));
        verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class), eq(null));
        verify(mockVibrator, never())
                .vibrate(any(VibrationEffect.class), any(AudioAttributes.class));
    }

    @SmallTest
    @Test
    public void testRingWithRampingRinger() {
        mRingerUnderTest.startCallWaiting(mockCall1);
        ensureRingerIsAudible();
        enableRampingRinger();
        assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
        verify(mockTonePlayer).stopTone();
        verify(mockRingtonePlayer).play(
            any(RingtoneFactory.class), any(Call.class), any(VolumeShaper.Configuration.class));
    }

    @SmallTest
    @Test
    public void testSilentRingWithHfpStillAcquiresFocus1() {
@@ -322,4 +335,8 @@ public class RingerTest extends TelecomTestCase {
        when(mockVibrator.hasVibrator()).thenReturn(true);
        when(mockSystemSettingsUtil.canVibrateWhenRinging(any(Context.class))).thenReturn(false);
    }

    private void enableRampingRinger() {
        when(mockSystemSettingsUtil.applyRampingRinger(any(Context.class))).thenReturn(true);
    }
}