Merge "Take advantage of new audio-coupled haptic patterns." into pi-dev
diff --git a/src/com/android/server/telecom/AsyncRingtonePlayer.java b/src/com/android/server/telecom/AsyncRingtonePlayer.java
index 7ed1c85..8a7be4d 100644
--- a/src/com/android/server/telecom/AsyncRingtonePlayer.java
+++ b/src/com/android/server/telecom/AsyncRingtonePlayer.java
@@ -92,7 +92,7 @@
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) {
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index e8b2b26..c4f9b63 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -24,6 +24,7 @@
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 @@
*/
@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 @@
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 @@
stopCallWaiting();
+ VibrationEffect effect;
if (isRingerAudible) {
mRingingCall = foregroundCall;
Log.addEvent(foregroundCall, LogUtils.Events.START_RINGER);
@@ -182,15 +185,16 @@
// 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 @@
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;
diff --git a/tests/src/com/android/server/telecom/tests/RingerTest.java b/tests/src/com/android/server/telecom/tests/RingerTest.java
index 2a45649..25460de 100644
--- a/tests/src/com/android/server/telecom/tests/RingerTest.java
+++ b/tests/src/com/android/server/telecom/tests/RingerTest.java
@@ -18,9 +18,11 @@
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.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 @@
@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 @@
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 @@
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