blob: 1d27f452a3eb0c0859cbf18651888de1b3690b13 [file] [log] [blame]
Sailesh Nepal6aca10a2014-03-24 16:11:02 -07001/*
Hall Liue091ab92015-12-18 17:05:30 -08002 * Copyright (C) 2015 The Android Open Source Project
Sailesh Nepal6aca10a2014-03-24 16:11:02 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
Hall Liue091ab92015-12-18 17:05:30 -080014 * limitations under the License
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070015 */
16
Tyler Gunn7cc70b42014-09-12 22:17:27 -070017package com.android.server.telecom;
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070018
Yorke Lee8a736a82014-08-30 17:19:16 -070019import android.app.Notification;
20import android.app.NotificationManager;
Selim Cinekb59795b2018-03-24 02:21:38 -070021import android.app.Person;
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070022import android.content.Context;
Tyler Gunn9d52d392017-07-31 09:48:16 -070023import android.os.VibrationEffect;
Brad Ebinger953e1af2016-10-05 15:45:22 -070024import android.telecom.Log;
Joseph Pirozzoee4089c2017-12-13 16:38:10 -080025import android.telecom.TelecomManager;
John Spurlock44b18102014-07-18 19:10:16 -040026import android.media.AudioAttributes;
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070027import android.media.AudioManager;
Michael Wright76888bb2018-03-08 00:12:36 +000028import android.media.Ringtone;
Yorke Lee8a736a82014-08-30 17:19:16 -070029import android.net.Uri;
30import android.os.Bundle;
Evan Charlton198fde82014-04-07 10:53:11 -070031import android.os.Vibrator;
Brad Ebingerd931a012015-10-21 12:54:08 -070032
33import com.android.internal.annotations.VisibleForTesting;
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070034
Tyler Gunn296489e2018-01-16 21:40:43 -080035import java.util.ArrayList;
36
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070037/**
38 * Controls the ringtone player.
39 */
Brad Ebingerd931a012015-10-21 12:54:08 -070040@VisibleForTesting
Hall Liue792b332016-04-19 14:23:09 -070041public class Ringer {
Michael Wright76888bb2018-03-08 00:12:36 +000042 @VisibleForTesting
43 public VibrationEffect mDefaultVibrationEffect;
Tyler Gunn9d52d392017-07-31 09:48:16 -070044
45 private static final long[] PULSE_PATTERN = {0,12,250,12,500, // priming + interval
46 50,50,50,50,50,50,50,50,50,50,50,50,50,50, // ease-in
47 300, // Peak
48 1000}; // pause before repetition
49
50 private static final int[] PULSE_AMPLITUDE = {0,255,0,255,0, // priming + interval
51 77,77,78,79,81,84,87,93,101,114,133,162,205,255, // ease-in (min amplitude = 30%)
52 255, // Peak
53 0}; // pause before repetition
54
Tyler Gunn4d8cd292018-03-06 11:04:26 -080055 private static final long[] SIMPLE_VIBRATION_PATTERN = {
56 0, // No delay before starting
57 1000, // How long to vibrate
58 1000, // How long to wait before vibrating again
59 };
60
61 private static final int[] SIMPLE_VIBRATION_AMPLITUDE = {
62 0, // No delay before starting
63 255, // Vibrate full amplitude
64 0, // No amplitude while waiting
65 };
66
Tyler Gunn9d52d392017-07-31 09:48:16 -070067 /**
68 * Indicates that vibration should be repeated at element 5 in the {@link #PULSE_AMPLITUDE} and
69 * {@link #PULSE_PATTERN} arrays. This means repetition will happen for the main ease-in/peak
70 * pattern, but the priming + interval part will not be repeated.
71 */
72 private static final int REPEAT_VIBRATION_AT = 5;
Evan Charlton198fde82014-04-07 10:53:11 -070073
Tyler Gunn4d8cd292018-03-06 11:04:26 -080074 private static final int REPEAT_SIMPLE_VIBRATION_AT = 1;
75
John Spurlock44b18102014-07-18 19:10:16 -040076 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
77 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
Jean-Michel Trivi29e52ae2014-07-20 13:23:45 -070078 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
John Spurlock44b18102014-07-18 19:10:16 -040079 .build();
80
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070081 /**
82 * Used to keep ordering of unanswered incoming calls. There can easily exist multiple incoming
83 * calls and explicit ordering is useful for maintaining the proper state of the ringer.
84 */
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070085
Brad Ebingerd931a012015-10-21 12:54:08 -070086 private final SystemSettingsUtil mSystemSettingsUtil;
Santos Cordon40f78c22014-04-07 02:11:42 -070087 private final InCallTonePlayer.Factory mPlayerFactory;
Brad Ebingerd931a012015-10-21 12:54:08 -070088 private final AsyncRingtonePlayer mRingtonePlayer;
Santos Cordon40f78c22014-04-07 02:11:42 -070089 private final Context mContext;
Evan Charlton198fde82014-04-07 10:53:11 -070090 private final Vibrator mVibrator;
Santos Cordonf0f99f32016-02-18 16:13:57 -080091 private final InCallController mInCallController;
Evan Charlton198fde82014-04-07 10:53:11 -070092
Santos Cordon40f78c22014-04-07 02:11:42 -070093 private InCallTonePlayer mCallWaitingPlayer;
Brad Ebingerd931a012015-10-21 12:54:08 -070094 private RingtoneFactory mRingtoneFactory;
Santos Cordon40f78c22014-04-07 02:11:42 -070095
Evan Charlton198fde82014-04-07 10:53:11 -070096 /**
Tyler Gunn68d2f862017-01-10 15:00:23 -080097 * Call objects that are ringing, vibrating or call-waiting. These are used only for logging
98 * purposes.
Hall Liue091ab92015-12-18 17:05:30 -080099 */
100 private Call mRingingCall;
Tyler Gunn68d2f862017-01-10 15:00:23 -0800101 private Call mVibratingCall;
Hall Liue091ab92015-12-18 17:05:30 -0800102 private Call mCallWaitingCall;
103
104 /**
Evan Charlton198fde82014-04-07 10:53:11 -0700105 * Used to track the status of {@link #mVibrator} in the case of simultaneous incoming calls.
106 */
107 private boolean mIsVibrating = false;
108
Santos Cordon40f78c22014-04-07 02:11:42 -0700109 /** Initializes the Ringer. */
Brad Ebingerd931a012015-10-21 12:54:08 -0700110 @VisibleForTesting
111 public Ringer(
Santos Cordon40f78c22014-04-07 02:11:42 -0700112 InCallTonePlayer.Factory playerFactory,
Brad Ebingerd931a012015-10-21 12:54:08 -0700113 Context context,
114 SystemSettingsUtil systemSettingsUtil,
115 AsyncRingtonePlayer asyncRingtonePlayer,
116 RingtoneFactory ringtoneFactory,
Santos Cordonf0f99f32016-02-18 16:13:57 -0800117 Vibrator vibrator,
118 InCallController inCallController) {
Evan Charlton198fde82014-04-07 10:53:11 -0700119
Brad Ebingerd931a012015-10-21 12:54:08 -0700120 mSystemSettingsUtil = systemSettingsUtil;
Santos Cordon40f78c22014-04-07 02:11:42 -0700121 mPlayerFactory = playerFactory;
122 mContext = context;
Evan Charlton198fde82014-04-07 10:53:11 -0700123 // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure this
124 // vibrator object will be isolated from others.
Brad Ebingerd931a012015-10-21 12:54:08 -0700125 mVibrator = vibrator;
126 mRingtonePlayer = asyncRingtonePlayer;
127 mRingtoneFactory = ringtoneFactory;
Santos Cordonf0f99f32016-02-18 16:13:57 -0800128 mInCallController = inCallController;
Tyler Gunn9d52d392017-07-31 09:48:16 -0700129
Tyler Gunn4d8cd292018-03-06 11:04:26 -0800130 if (mContext.getResources().getBoolean(R.bool.use_simple_vibration_pattern)) {
Michael Wright76888bb2018-03-08 00:12:36 +0000131 mDefaultVibrationEffect = VibrationEffect.createWaveform(SIMPLE_VIBRATION_PATTERN,
Tyler Gunn4d8cd292018-03-06 11:04:26 -0800132 SIMPLE_VIBRATION_AMPLITUDE, REPEAT_SIMPLE_VIBRATION_AT);
133 } else {
Michael Wright76888bb2018-03-08 00:12:36 +0000134 mDefaultVibrationEffect = VibrationEffect.createWaveform(PULSE_PATTERN,
135 PULSE_AMPLITUDE, REPEAT_VIBRATION_AT);
Tyler Gunn4d8cd292018-03-06 11:04:26 -0800136 }
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700137 }
138
Hall Liu136f4c92017-04-04 13:35:18 -0700139 public boolean startRinging(Call foregroundCall, boolean isHfpDeviceAttached) {
Hall Liu5648f362016-02-02 15:12:04 -0800140 if (foregroundCall == null) {
141 Log.wtf(this, "startRinging called with null foreground call.");
Hall Liu6a5995e2016-09-08 16:00:14 -0700142 return false;
Hall Liu5648f362016-02-02 15:12:04 -0800143 }
144
Hall Liu136f4c92017-04-04 13:35:18 -0700145 AudioManager audioManager =
146 (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
147 boolean isVolumeOverZero = audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0;
148 boolean shouldRingForContact = shouldRingForContact(foregroundCall.getContactUri());
149 boolean isRingtonePresent = !(mRingtoneFactory.getRingtone(foregroundCall) == null);
150 boolean isSelfManaged = foregroundCall.isSelfManaged();
Sailesh Nepalc07b8e12016-01-23 16:43:10 -0800151
Hall Liu136f4c92017-04-04 13:35:18 -0700152 boolean isRingerAudible = isVolumeOverZero && shouldRingForContact && isRingtonePresent;
Joseph Pirozzoee4089c2017-12-13 16:38:10 -0800153 boolean hasExternalRinger = hasExternalRinger(foregroundCall);
Hall Liu136f4c92017-04-04 13:35:18 -0700154 // Acquire audio focus under any of the following conditions:
155 // 1. Should ring for contact and there's an HFP device attached
156 // 2. Volume is over zero, we should ring for the contact, and there's a audible ringtone
157 // present.
158 // 3. The call is self-managed.
159 boolean shouldAcquireAudioFocus =
160 isRingerAudible || (isHfpDeviceAttached && shouldRingForContact) || isSelfManaged;
161
162 // Don't do call waiting operations or vibration unless these are false.
163 boolean isTheaterModeOn = mSystemSettingsUtil.isTheaterModeOn(mContext);
164 boolean letDialerHandleRinging = mInCallController.doesConnectedDialerSupportRinging();
Joseph Pirozzoee4089c2017-12-13 16:38:10 -0800165 boolean endEarly = isTheaterModeOn || letDialerHandleRinging || isSelfManaged ||
166 hasExternalRinger;
Hall Liu136f4c92017-04-04 13:35:18 -0700167
168 if (endEarly) {
169 if (letDialerHandleRinging) {
170 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING);
171 }
172 Log.i(this, "Ending early -- isTheaterModeOn=%s, letDialerHandleRinging=%s, " +
Joseph Pirozzoee4089c2017-12-13 16:38:10 -0800173 "isSelfManaged=%s, hasExternalRinger=%s", isTheaterModeOn,
174 letDialerHandleRinging, isSelfManaged, hasExternalRinger);
Hall Liu136f4c92017-04-04 13:35:18 -0700175 return shouldAcquireAudioFocus;
Tyler Gunn638f1802017-04-03 15:49:48 -0700176 }
177
Hall Liue091ab92015-12-18 17:05:30 -0800178 stopCallWaiting();
Santos Cordon40f78c22014-04-07 02:11:42 -0700179
Michael Wright76888bb2018-03-08 00:12:36 +0000180 VibrationEffect effect;
Hall Liu6a5995e2016-09-08 16:00:14 -0700181 if (isRingerAudible) {
Hall Liue091ab92015-12-18 17:05:30 -0800182 mRingingCall = foregroundCall;
Brad Ebinger953e1af2016-10-05 15:45:22 -0700183 Log.addEvent(foregroundCall, LogUtils.Events.START_RINGER);
Hall Liue091ab92015-12-18 17:05:30 -0800184 // Because we wait until a contact info query to complete before processing a
185 // call (for the purposes of direct-to-voicemail), the information about custom
186 // ringtones should be available by the time this code executes. We can safely
187 // request the custom ringtone from the call and expect it to be current.
Brad Ebingerc9286f42016-03-10 16:02:54 -0800188 mRingtonePlayer.play(mRingtoneFactory, foregroundCall);
Michael Wright76888bb2018-03-08 00:12:36 +0000189 effect = getVibrationEffectForCall(mRingtoneFactory, foregroundCall);
Hall Liue091ab92015-12-18 17:05:30 -0800190 } else {
Hall Liu136f4c92017-04-04 13:35:18 -0700191 Log.i(this, "startRinging: skipping because ringer would not be audible. " +
192 "isVolumeOverZero=%s, shouldRingForContact=%s, isRingtonePresent=%s",
193 isVolumeOverZero, shouldRingForContact, isRingtonePresent);
Michael Wright76888bb2018-03-08 00:12:36 +0000194 effect = mDefaultVibrationEffect;
Hall Liue091ab92015-12-18 17:05:30 -0800195 }
196
Hall Liu136f4c92017-04-04 13:35:18 -0700197 if (shouldVibrate(mContext, foregroundCall) && !mIsVibrating && shouldRingForContact) {
Michael Wright76888bb2018-03-08 00:12:36 +0000198 mVibrator.vibrate(effect, VIBRATION_ATTRIBUTES);
Hall Liue091ab92015-12-18 17:05:30 -0800199 mIsVibrating = true;
Tyler Gunn68d2f862017-01-10 15:00:23 -0800200 } else if (mIsVibrating) {
201 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_VIBRATION, "already vibrating");
Hall Liue091ab92015-12-18 17:05:30 -0800202 }
Hall Liu6a5995e2016-09-08 16:00:14 -0700203
Hall Liu136f4c92017-04-04 13:35:18 -0700204 return shouldAcquireAudioFocus;
Hall Liue091ab92015-12-18 17:05:30 -0800205 }
206
Michael Wright76888bb2018-03-08 00:12:36 +0000207 private VibrationEffect getVibrationEffectForCall(RingtoneFactory factory, Call call) {
208 VibrationEffect effect = null;
209 Ringtone ringtone = factory.getRingtone(call);
210 Uri ringtoneUri = ringtone != null ? ringtone.getUri() : null;
211 if (ringtoneUri != null) {
212 effect = VibrationEffect.get(ringtoneUri, mContext);
213 }
214
215 if (effect == null) {
216 effect = mDefaultVibrationEffect;
217 }
218 return effect;
219 }
220
Hall Liue091ab92015-12-18 17:05:30 -0800221 public void startCallWaiting(Call call) {
222 if (mSystemSettingsUtil.isTheaterModeOn(mContext)) {
223 return;
224 }
225
Santos Cordonf0f99f32016-02-18 16:13:57 -0800226 if (mInCallController.doesConnectedDialerSupportRinging()) {
Brad Ebinger953e1af2016-10-05 15:45:22 -0700227 Log.addEvent(call, LogUtils.Events.SKIP_RINGING);
Sailesh Nepalc07b8e12016-01-23 16:43:10 -0800228 return;
229 }
230
Tyler Gunn638f1802017-04-03 15:49:48 -0700231 if (call.isSelfManaged()) {
232 Log.addEvent(call, LogUtils.Events.SKIP_RINGING, "Self-managed");
233 return;
234 }
235
Hall Liue091ab92015-12-18 17:05:30 -0800236 Log.v(this, "Playing call-waiting tone.");
237
238 stopRinging();
239
240 if (mCallWaitingPlayer == null) {
Brad Ebinger953e1af2016-10-05 15:45:22 -0700241 Log.addEvent(call, LogUtils.Events.START_CALL_WAITING_TONE);
Hall Liue091ab92015-12-18 17:05:30 -0800242 mCallWaitingCall = call;
243 mCallWaitingPlayer =
244 mPlayerFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING);
245 mCallWaitingPlayer.startTone();
246 }
247 }
248
249 public void stopRinging() {
250 if (mRingingCall != null) {
Brad Ebinger953e1af2016-10-05 15:45:22 -0700251 Log.addEvent(mRingingCall, LogUtils.Events.STOP_RINGER);
Hall Liue091ab92015-12-18 17:05:30 -0800252 mRingingCall = null;
253 }
254
255 mRingtonePlayer.stop();
256
257 if (mIsVibrating) {
Tyler Gunn68d2f862017-01-10 15:00:23 -0800258 Log.addEvent(mVibratingCall, LogUtils.Events.STOP_VIBRATOR);
Hall Liue091ab92015-12-18 17:05:30 -0800259 mVibrator.cancel();
260 mIsVibrating = false;
Tyler Gunn68d2f862017-01-10 15:00:23 -0800261 mVibratingCall = null;
Hall Liue091ab92015-12-18 17:05:30 -0800262 }
263 }
264
265 public void stopCallWaiting() {
266 Log.v(this, "stop call waiting.");
267 if (mCallWaitingPlayer != null) {
268 if (mCallWaitingCall != null) {
Brad Ebinger953e1af2016-10-05 15:45:22 -0700269 Log.addEvent(mCallWaitingCall, LogUtils.Events.STOP_CALL_WAITING_TONE);
Hall Liue091ab92015-12-18 17:05:30 -0800270 mCallWaitingCall = null;
Yorke Lee8a736a82014-08-30 17:19:16 -0700271 }
272
Hall Liue091ab92015-12-18 17:05:30 -0800273 mCallWaitingPlayer.stopTone();
274 mCallWaitingPlayer = null;
Evan Charlton198fde82014-04-07 10:53:11 -0700275 }
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700276 }
277
Yorke Lee8a736a82014-08-30 17:19:16 -0700278 private boolean shouldRingForContact(Uri contactUri) {
279 final NotificationManager manager =
280 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Tyler Gunn296489e2018-01-16 21:40:43 -0800281 final Bundle peopleExtras = new Bundle();
Yorke Lee8a736a82014-08-30 17:19:16 -0700282 if (contactUri != null) {
Selim Cinekb59795b2018-03-24 02:21:38 -0700283 ArrayList<Person> personList = new ArrayList<>();
284 personList.add(new Person.Builder().setUri(contactUri.toString()).build());
Tyler Gunn296489e2018-01-16 21:40:43 -0800285 peopleExtras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, personList);
Yorke Lee8a736a82014-08-30 17:19:16 -0700286 }
Tyler Gunn296489e2018-01-16 21:40:43 -0800287 return manager.matchesCallFilter(peopleExtras);
Yorke Lee8a736a82014-08-30 17:19:16 -0700288 }
289
Joseph Pirozzoee4089c2017-12-13 16:38:10 -0800290 private boolean hasExternalRinger(Call foregroundCall) {
291 Bundle intentExtras = foregroundCall.getIntentExtras();
292 if (intentExtras != null) {
293 return intentExtras.getBoolean(TelecomManager.EXTRA_CALL_EXTERNAL_RINGER, false);
294 } else {
295 return false;
296 }
297 }
298
Tyler Gunn68d2f862017-01-10 15:00:23 -0800299 private boolean shouldVibrate(Context context, Call call) {
Evan Charlton198fde82014-04-07 10:53:11 -0700300 AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
John Spurlock15226912014-11-25 08:38:47 -0500301 int ringerMode = audioManager.getRingerModeInternal();
Tyler Gunn68d2f862017-01-10 15:00:23 -0800302 boolean shouldVibrate;
Evan Charlton198fde82014-04-07 10:53:11 -0700303 if (getVibrateWhenRinging(context)) {
Tyler Gunn68d2f862017-01-10 15:00:23 -0800304 shouldVibrate = ringerMode != AudioManager.RINGER_MODE_SILENT;
Evan Charlton198fde82014-04-07 10:53:11 -0700305 } else {
Tyler Gunn68d2f862017-01-10 15:00:23 -0800306 shouldVibrate = ringerMode == AudioManager.RINGER_MODE_VIBRATE;
Evan Charlton198fde82014-04-07 10:53:11 -0700307 }
Tyler Gunn68d2f862017-01-10 15:00:23 -0800308
309 // Technically this should be in the calling method, but it seemed a little odd to pass
310 // around a whole bunch of state just for logging purposes.
311 if (shouldVibrate) {
312 Log.addEvent(call, LogUtils.Events.START_VIBRATOR,
313 "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
314 mVibrator.hasVibrator(), mSystemSettingsUtil.canVibrateWhenRinging(context),
315 ringerMode, mIsVibrating);
316 } else {
317 Log.addEvent(call, LogUtils.Events.SKIP_VIBRATION,
318 "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
319 mVibrator.hasVibrator(), mSystemSettingsUtil.canVibrateWhenRinging(context),
320 ringerMode, mIsVibrating);
321 }
322
323 return shouldVibrate;
Evan Charlton198fde82014-04-07 10:53:11 -0700324 }
325
326 private boolean getVibrateWhenRinging(Context context) {
327 if (!mVibrator.hasVibrator()) {
328 return false;
329 }
Brad Ebingerd931a012015-10-21 12:54:08 -0700330 return mSystemSettingsUtil.canVibrateWhenRinging(context);
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700331 }
332}