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

Commit 684e9336 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Take advantage of new audio-coupled haptic patterns." into pi-dev

parents 4203e2a7 76888bbc
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ public class AsyncRingtonePlayer {
        HandlerThread thread = new HandlerThread("ringtone-player");
        thread.start();

        return new Handler(thread.getLooper()) {
        return new Handler(thread.getLooper(), null /*callback*/, true /*async*/) {
            @Override
            public void handleMessage(Message msg) {
                switch(msg.what) {
+24 −6
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.telecom.Log;
import android.telecom.TelecomManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
@@ -37,7 +38,8 @@ import java.util.ArrayList;
 */
@VisibleForTesting
public class Ringer {
    VibrationEffect mVibrationEffect;
    @VisibleForTesting
    public VibrationEffect mDefaultVibrationEffect;

    private static final long[] PULSE_PATTERN = {0,12,250,12,500, // priming  + interval
            50,50,50,50,50,50,50,50,50,50,50,50,50,50, // ease-in
@@ -125,11 +127,11 @@ public class Ringer {
        mInCallController = inCallController;

        if (mContext.getResources().getBoolean(R.bool.use_simple_vibration_pattern)) {
            mVibrationEffect = VibrationEffect.createWaveform(SIMPLE_VIBRATION_PATTERN,
            mDefaultVibrationEffect = VibrationEffect.createWaveform(SIMPLE_VIBRATION_PATTERN,
                    SIMPLE_VIBRATION_AMPLITUDE, REPEAT_SIMPLE_VIBRATION_AT);
        } else {
            mVibrationEffect = VibrationEffect.createWaveform(PULSE_PATTERN, PULSE_AMPLITUDE,
                    REPEAT_VIBRATION_AT);
            mDefaultVibrationEffect = VibrationEffect.createWaveform(PULSE_PATTERN,
                    PULSE_AMPLITUDE, REPEAT_VIBRATION_AT);
        }
    }

@@ -174,6 +176,7 @@ public class Ringer {

        stopCallWaiting();

        VibrationEffect effect;
        if (isRingerAudible) {
            mRingingCall = foregroundCall;
            Log.addEvent(foregroundCall, LogUtils.Events.START_RINGER);
@@ -182,15 +185,16 @@ public class Ringer {
            // 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);
            effect = getVibrationEffectForCall(mRingtoneFactory, foregroundCall);
        } else {
            Log.i(this, "startRinging: skipping because ringer would not be audible. " +
                    "isVolumeOverZero=%s, shouldRingForContact=%s, isRingtonePresent=%s",
                    isVolumeOverZero, shouldRingForContact, isRingtonePresent);
            effect = mDefaultVibrationEffect;
        }

        if (shouldVibrate(mContext, foregroundCall) && !mIsVibrating && shouldRingForContact) {
            mVibratingCall = foregroundCall;
            mVibrator.vibrate(mVibrationEffect, VIBRATION_ATTRIBUTES);
            mVibrator.vibrate(effect, VIBRATION_ATTRIBUTES);
            mIsVibrating = true;
        } else if (mIsVibrating) {
            Log.addEvent(foregroundCall, LogUtils.Events.SKIP_VIBRATION, "already vibrating");
@@ -199,6 +203,20 @@ public class Ringer {
        return shouldAcquireAudioFocus;
    }

    private VibrationEffect getVibrationEffectForCall(RingtoneFactory factory, Call call) {
        VibrationEffect effect = null;
        Ringtone ringtone = factory.getRingtone(call);
        Uri ringtoneUri = ringtone != null ? ringtone.getUri() : null;
        if (ringtoneUri != null) {
            effect = VibrationEffect.get(ringtoneUri, mContext);
        }

        if (effect == null) {
            effect = mDefaultVibrationEffect;
        }
        return effect;
    }

    public void startCallWaiting(Call call) {
        if (mSystemSettingsUtil.isTheaterModeOn(mContext)) {
            return;
+27 −2
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ package com.android.server.telecom.tests;

import android.app.NotificationManager;
import android.content.Context;
import android.content.res.Resources;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.net.Uri;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
@@ -45,6 +47,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -52,6 +55,8 @@ import static org.mockito.Mockito.when;

@RunWith(JUnit4.class)
public class RingerTest extends TelecomTestCase {
    private static final Uri FAKE_RINGTONE_URI = Uri.parse("content://media/fake/audio/1729");

    @Mock InCallTonePlayer.Factory mockPlayerFactory;
    @Mock SystemSettingsUtil mockSystemSettingsUtil;
    @Mock AsyncRingtonePlayer mockRingtonePlayer;
@@ -179,7 +184,8 @@ public class RingerTest extends TelecomTestCase {
        assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
        verify(mockTonePlayer).stopTone();
        verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class));
        verify(mockVibrator).vibrate(any(VibrationEffect.class), any(AudioAttributes.class));
        verify(mockVibrator).vibrate(eq(mRingerUnderTest.mDefaultVibrationEffect),
                any(AudioAttributes.class));
    }

    @SmallTest
@@ -194,7 +200,26 @@ public class RingerTest extends TelecomTestCase {
        assertFalse(mRingerUnderTest.startRinging(mockCall2, false));
        verify(mockTonePlayer).stopTone();
        verify(mockRingtonePlayer, never()).play(any(RingtoneFactory.class), any(Call.class));
        verify(mockVibrator).vibrate(any(VibrationEffect.class), any(AudioAttributes.class));
        verify(mockVibrator).vibrate(eq(mRingerUnderTest.mDefaultVibrationEffect),
                any(AudioAttributes.class));
    }

    @SmallTest
    @Test
    public void testCustomVibrationForRingtone() {
        Resources resources = mContext.getResources();
        when(resources.getStringArray(com.android.internal.R.array.config_ringtoneEffectUris))
                .thenReturn(new String[] { FAKE_RINGTONE_URI.toString() });
        mRingerUnderTest.startCallWaiting(mockCall1);
        Ringtone mockRingtone = mock(Ringtone.class);
        when(mockRingtoneFactory.getRingtone(any(Call.class))).thenReturn(mockRingtone);
        when(mockRingtone.getUri()).thenReturn(FAKE_RINGTONE_URI);
        enableVibrationWhenRinging();
        assertTrue(mRingerUnderTest.startRinging(mockCall2, false));
        verify(mockTonePlayer).stopTone();
        verify(mockRingtonePlayer).play(any(RingtoneFactory.class), any(Call.class));
        verify(mockVibrator).vibrate(eq(VibrationEffect.get(FAKE_RINGTONE_URI, mContext)),
                any(AudioAttributes.class));
    }

    @SmallTest