blob: c4f9b631bde6d19e3872b732c7b14ab7ca10119a [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;
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070021import android.content.Context;
Tyler Gunn9d52d392017-07-31 09:48:16 -070022import android.os.VibrationEffect;
Brad Ebinger953e1af2016-10-05 15:45:22 -070023import android.telecom.Log;
Joseph Pirozzoee4089c2017-12-13 16:38:10 -080024import android.telecom.TelecomManager;
John Spurlock44b18102014-07-18 19:10:16 -040025import android.media.AudioAttributes;
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070026import android.media.AudioManager;
Michael Wright76888bb2018-03-08 00:12:36 +000027import android.media.Ringtone;
Yorke Lee8a736a82014-08-30 17:19:16 -070028import android.net.Uri;
29import android.os.Bundle;
Evan Charlton198fde82014-04-07 10:53:11 -070030import android.os.Vibrator;
Brad Ebingerd931a012015-10-21 12:54:08 -070031
32import com.android.internal.annotations.VisibleForTesting;
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070033
Tyler Gunn296489e2018-01-16 21:40:43 -080034import java.util.ArrayList;
35
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070036/**
37 * Controls the ringtone player.
38 */
Brad Ebingerd931a012015-10-21 12:54:08 -070039@VisibleForTesting
Hall Liue792b332016-04-19 14:23:09 -070040public class Ringer {
Michael Wright76888bb2018-03-08 00:12:36 +000041 @VisibleForTesting
42 public VibrationEffect mDefaultVibrationEffect;
Tyler Gunn9d52d392017-07-31 09:48:16 -070043
44 private static final long[] PULSE_PATTERN = {0,12,250,12,500, // priming + interval
45 50,50,50,50,50,50,50,50,50,50,50,50,50,50, // ease-in
46 300, // Peak
47 1000}; // pause before repetition
48
49 private static final int[] PULSE_AMPLITUDE = {0,255,0,255,0, // priming + interval
50 77,77,78,79,81,84,87,93,101,114,133,162,205,255, // ease-in (min amplitude = 30%)
51 255, // Peak
52 0}; // pause before repetition
53
Tyler Gunn4d8cd292018-03-06 11:04:26 -080054 private static final long[] SIMPLE_VIBRATION_PATTERN = {
55 0, // No delay before starting
56 1000, // How long to vibrate
57 1000, // How long to wait before vibrating again
58 };
59
60 private static final int[] SIMPLE_VIBRATION_AMPLITUDE = {
61 0, // No delay before starting
62 255, // Vibrate full amplitude
63 0, // No amplitude while waiting
64 };
65
Tyler Gunn9d52d392017-07-31 09:48:16 -070066 /**
67 * Indicates that vibration should be repeated at element 5 in the {@link #PULSE_AMPLITUDE} and
68 * {@link #PULSE_PATTERN} arrays. This means repetition will happen for the main ease-in/peak
69 * pattern, but the priming + interval part will not be repeated.
70 */
71 private static final int REPEAT_VIBRATION_AT = 5;
Evan Charlton198fde82014-04-07 10:53:11 -070072
Tyler Gunn4d8cd292018-03-06 11:04:26 -080073 private static final int REPEAT_SIMPLE_VIBRATION_AT = 1;
74
John Spurlock44b18102014-07-18 19:10:16 -040075 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
76 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
Jean-Michel Trivi29e52ae2014-07-20 13:23:45 -070077 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
John Spurlock44b18102014-07-18 19:10:16 -040078 .build();
79
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070080 /**
81 * Used to keep ordering of unanswered incoming calls. There can easily exist multiple incoming
82 * calls and explicit ordering is useful for maintaining the proper state of the ringer.
83 */
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070084
Brad Ebingerd931a012015-10-21 12:54:08 -070085 private final SystemSettingsUtil mSystemSettingsUtil;
Santos Cordon40f78c22014-04-07 02:11:42 -070086 private final InCallTonePlayer.Factory mPlayerFactory;
Brad Ebingerd931a012015-10-21 12:54:08 -070087 private final AsyncRingtonePlayer mRingtonePlayer;
Santos Cordon40f78c22014-04-07 02:11:42 -070088 private final Context mContext;
Evan Charlton198fde82014-04-07 10:53:11 -070089 private final Vibrator mVibrator;
Santos Cordonf0f99f32016-02-18 16:13:57 -080090 private final InCallController mInCallController;
Evan Charlton198fde82014-04-07 10:53:11 -070091
Santos Cordon40f78c22014-04-07 02:11:42 -070092 private InCallTonePlayer mCallWaitingPlayer;
Brad Ebingerd931a012015-10-21 12:54:08 -070093 private RingtoneFactory mRingtoneFactory;
Santos Cordon40f78c22014-04-07 02:11:42 -070094
Evan Charlton198fde82014-04-07 10:53:11 -070095 /**
Tyler Gunn68d2f862017-01-10 15:00:23 -080096 * Call objects that are ringing, vibrating or call-waiting. These are used only for logging
97 * purposes.
Hall Liue091ab92015-12-18 17:05:30 -080098 */
99 private Call mRingingCall;
Tyler Gunn68d2f862017-01-10 15:00:23 -0800100 private Call mVibratingCall;
Hall Liue091ab92015-12-18 17:05:30 -0800101 private Call mCallWaitingCall;
102
103 /**
Evan Charlton198fde82014-04-07 10:53:11 -0700104 * Used to track the status of {@link #mVibrator} in the case of simultaneous incoming calls.
105 */
106 private boolean mIsVibrating = false;
107
Santos Cordon40f78c22014-04-07 02:11:42 -0700108 /** Initializes the Ringer. */
Brad Ebingerd931a012015-10-21 12:54:08 -0700109 @VisibleForTesting
110 public Ringer(
Santos Cordon40f78c22014-04-07 02:11:42 -0700111 InCallTonePlayer.Factory playerFactory,
Brad Ebingerd931a012015-10-21 12:54:08 -0700112 Context context,
113 SystemSettingsUtil systemSettingsUtil,
114 AsyncRingtonePlayer asyncRingtonePlayer,
115 RingtoneFactory ringtoneFactory,
Santos Cordonf0f99f32016-02-18 16:13:57 -0800116 Vibrator vibrator,
117 InCallController inCallController) {
Evan Charlton198fde82014-04-07 10:53:11 -0700118
Brad Ebingerd931a012015-10-21 12:54:08 -0700119 mSystemSettingsUtil = systemSettingsUtil;
Santos Cordon40f78c22014-04-07 02:11:42 -0700120 mPlayerFactory = playerFactory;
121 mContext = context;
Evan Charlton198fde82014-04-07 10:53:11 -0700122 // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure this
123 // vibrator object will be isolated from others.
Brad Ebingerd931a012015-10-21 12:54:08 -0700124 mVibrator = vibrator;
125 mRingtonePlayer = asyncRingtonePlayer;
126 mRingtoneFactory = ringtoneFactory;
Santos Cordonf0f99f32016-02-18 16:13:57 -0800127 mInCallController = inCallController;
Tyler Gunn9d52d392017-07-31 09:48:16 -0700128
Tyler Gunn4d8cd292018-03-06 11:04:26 -0800129 if (mContext.getResources().getBoolean(R.bool.use_simple_vibration_pattern)) {
Michael Wright76888bb2018-03-08 00:12:36 +0000130 mDefaultVibrationEffect = VibrationEffect.createWaveform(SIMPLE_VIBRATION_PATTERN,
Tyler Gunn4d8cd292018-03-06 11:04:26 -0800131 SIMPLE_VIBRATION_AMPLITUDE, REPEAT_SIMPLE_VIBRATION_AT);
132 } else {
Michael Wright76888bb2018-03-08 00:12:36 +0000133 mDefaultVibrationEffect = VibrationEffect.createWaveform(PULSE_PATTERN,
134 PULSE_AMPLITUDE, REPEAT_VIBRATION_AT);
Tyler Gunn4d8cd292018-03-06 11:04:26 -0800135 }
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700136 }
137
Hall Liu136f4c92017-04-04 13:35:18 -0700138 public boolean startRinging(Call foregroundCall, boolean isHfpDeviceAttached) {
Hall Liu5648f362016-02-02 15:12:04 -0800139 if (foregroundCall == null) {
140 Log.wtf(this, "startRinging called with null foreground call.");
Hall Liu6a5995e2016-09-08 16:00:14 -0700141 return false;
Hall Liu5648f362016-02-02 15:12:04 -0800142 }
143
Hall Liu136f4c92017-04-04 13:35:18 -0700144 AudioManager audioManager =
145 (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
146 boolean isVolumeOverZero = audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0;
147 boolean shouldRingForContact = shouldRingForContact(foregroundCall.getContactUri());
148 boolean isRingtonePresent = !(mRingtoneFactory.getRingtone(foregroundCall) == null);
149 boolean isSelfManaged = foregroundCall.isSelfManaged();
Sailesh Nepalc07b8e12016-01-23 16:43:10 -0800150
Hall Liu136f4c92017-04-04 13:35:18 -0700151 boolean isRingerAudible = isVolumeOverZero && shouldRingForContact && isRingtonePresent;
Joseph Pirozzoee4089c2017-12-13 16:38:10 -0800152 boolean hasExternalRinger = hasExternalRinger(foregroundCall);
Hall Liu136f4c92017-04-04 13:35:18 -0700153 // Acquire audio focus under any of the following conditions:
154 // 1. Should ring for contact and there's an HFP device attached
155 // 2. Volume is over zero, we should ring for the contact, and there's a audible ringtone
156 // present.
157 // 3. The call is self-managed.
158 boolean shouldAcquireAudioFocus =
159 isRingerAudible || (isHfpDeviceAttached && shouldRingForContact) || isSelfManaged;
160
161 // Don't do call waiting operations or vibration unless these are false.
162 boolean isTheaterModeOn = mSystemSettingsUtil.isTheaterModeOn(mContext);
163 boolean letDialerHandleRinging = mInCallController.doesConnectedDialerSupportRinging();
Joseph Pirozzoee4089c2017-12-13 16:38:10 -0800164 boolean endEarly = isTheaterModeOn || letDialerHandleRinging || isSelfManaged ||
165 hasExternalRinger;
Hall Liu136f4c92017-04-04 13:35:18 -0700166
167 if (endEarly) {
168 if (letDialerHandleRinging) {
169 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING);
170 }
171 Log.i(this, "Ending early -- isTheaterModeOn=%s, letDialerHandleRinging=%s, " +
Joseph Pirozzoee4089c2017-12-13 16:38:10 -0800172 "isSelfManaged=%s, hasExternalRinger=%s", isTheaterModeOn,
173 letDialerHandleRinging, isSelfManaged, hasExternalRinger);
Hall Liu136f4c92017-04-04 13:35:18 -0700174 return shouldAcquireAudioFocus;
Tyler Gunn638f1802017-04-03 15:49:48 -0700175 }
176
Hall Liue091ab92015-12-18 17:05:30 -0800177 stopCallWaiting();
Santos Cordon40f78c22014-04-07 02:11:42 -0700178
Michael Wright76888bb2018-03-08 00:12:36 +0000179 VibrationEffect effect;
Hall Liu6a5995e2016-09-08 16:00:14 -0700180 if (isRingerAudible) {
Hall Liue091ab92015-12-18 17:05:30 -0800181 mRingingCall = foregroundCall;
Brad Ebinger953e1af2016-10-05 15:45:22 -0700182 Log.addEvent(foregroundCall, LogUtils.Events.START_RINGER);
Hall Liue091ab92015-12-18 17:05:30 -0800183 // Because we wait until a contact info query to complete before processing a
184 // call (for the purposes of direct-to-voicemail), the information about custom
185 // ringtones should be available by the time this code executes. We can safely
186 // request the custom ringtone from the call and expect it to be current.
Brad Ebingerc9286f42016-03-10 16:02:54 -0800187 mRingtonePlayer.play(mRingtoneFactory, foregroundCall);
Michael Wright76888bb2018-03-08 00:12:36 +0000188 effect = getVibrationEffectForCall(mRingtoneFactory, foregroundCall);
Hall Liue091ab92015-12-18 17:05:30 -0800189 } else {
Hall Liu136f4c92017-04-04 13:35:18 -0700190 Log.i(this, "startRinging: skipping because ringer would not be audible. " +
191 "isVolumeOverZero=%s, shouldRingForContact=%s, isRingtonePresent=%s",
192 isVolumeOverZero, shouldRingForContact, isRingtonePresent);
Michael Wright76888bb2018-03-08 00:12:36 +0000193 effect = mDefaultVibrationEffect;
Hall Liue091ab92015-12-18 17:05:30 -0800194 }
195
Hall Liu136f4c92017-04-04 13:35:18 -0700196 if (shouldVibrate(mContext, foregroundCall) && !mIsVibrating && shouldRingForContact) {
Michael Wright76888bb2018-03-08 00:12:36 +0000197 mVibrator.vibrate(effect, VIBRATION_ATTRIBUTES);
Hall Liue091ab92015-12-18 17:05:30 -0800198 mIsVibrating = true;
Tyler Gunn68d2f862017-01-10 15:00:23 -0800199 } else if (mIsVibrating) {
200 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_VIBRATION, "already vibrating");
Hall Liue091ab92015-12-18 17:05:30 -0800201 }
Hall Liu6a5995e2016-09-08 16:00:14 -0700202
Hall Liu136f4c92017-04-04 13:35:18 -0700203 return shouldAcquireAudioFocus;
Hall Liue091ab92015-12-18 17:05:30 -0800204 }
205
Michael Wright76888bb2018-03-08 00:12:36 +0000206 private VibrationEffect getVibrationEffectForCall(RingtoneFactory factory, Call call) {
207 VibrationEffect effect = null;
208 Ringtone ringtone = factory.getRingtone(call);
209 Uri ringtoneUri = ringtone != null ? ringtone.getUri() : null;
210 if (ringtoneUri != null) {
211 effect = VibrationEffect.get(ringtoneUri, mContext);
212 }
213
214 if (effect == null) {
215 effect = mDefaultVibrationEffect;
216 }
217 return effect;
218 }
219
Hall Liue091ab92015-12-18 17:05:30 -0800220 public void startCallWaiting(Call call) {
221 if (mSystemSettingsUtil.isTheaterModeOn(mContext)) {
222 return;
223 }
224
Santos Cordonf0f99f32016-02-18 16:13:57 -0800225 if (mInCallController.doesConnectedDialerSupportRinging()) {
Brad Ebinger953e1af2016-10-05 15:45:22 -0700226 Log.addEvent(call, LogUtils.Events.SKIP_RINGING);
Sailesh Nepalc07b8e12016-01-23 16:43:10 -0800227 return;
228 }
229
Tyler Gunn638f1802017-04-03 15:49:48 -0700230 if (call.isSelfManaged()) {
231 Log.addEvent(call, LogUtils.Events.SKIP_RINGING, "Self-managed");
232 return;
233 }
234
Hall Liue091ab92015-12-18 17:05:30 -0800235 Log.v(this, "Playing call-waiting tone.");
236
237 stopRinging();
238
239 if (mCallWaitingPlayer == null) {
Brad Ebinger953e1af2016-10-05 15:45:22 -0700240 Log.addEvent(call, LogUtils.Events.START_CALL_WAITING_TONE);
Hall Liue091ab92015-12-18 17:05:30 -0800241 mCallWaitingCall = call;
242 mCallWaitingPlayer =
243 mPlayerFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING);
244 mCallWaitingPlayer.startTone();
245 }
246 }
247
248 public void stopRinging() {
249 if (mRingingCall != null) {
Brad Ebinger953e1af2016-10-05 15:45:22 -0700250 Log.addEvent(mRingingCall, LogUtils.Events.STOP_RINGER);
Hall Liue091ab92015-12-18 17:05:30 -0800251 mRingingCall = null;
252 }
253
254 mRingtonePlayer.stop();
255
256 if (mIsVibrating) {
Tyler Gunn68d2f862017-01-10 15:00:23 -0800257 Log.addEvent(mVibratingCall, LogUtils.Events.STOP_VIBRATOR);
Hall Liue091ab92015-12-18 17:05:30 -0800258 mVibrator.cancel();
259 mIsVibrating = false;
Tyler Gunn68d2f862017-01-10 15:00:23 -0800260 mVibratingCall = null;
Hall Liue091ab92015-12-18 17:05:30 -0800261 }
262 }
263
264 public void stopCallWaiting() {
265 Log.v(this, "stop call waiting.");
266 if (mCallWaitingPlayer != null) {
267 if (mCallWaitingCall != null) {
Brad Ebinger953e1af2016-10-05 15:45:22 -0700268 Log.addEvent(mCallWaitingCall, LogUtils.Events.STOP_CALL_WAITING_TONE);
Hall Liue091ab92015-12-18 17:05:30 -0800269 mCallWaitingCall = null;
Yorke Lee8a736a82014-08-30 17:19:16 -0700270 }
271
Hall Liue091ab92015-12-18 17:05:30 -0800272 mCallWaitingPlayer.stopTone();
273 mCallWaitingPlayer = null;
Evan Charlton198fde82014-04-07 10:53:11 -0700274 }
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700275 }
276
Yorke Lee8a736a82014-08-30 17:19:16 -0700277 private boolean shouldRingForContact(Uri contactUri) {
278 final NotificationManager manager =
279 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Tyler Gunn296489e2018-01-16 21:40:43 -0800280 final Bundle peopleExtras = new Bundle();
Yorke Lee8a736a82014-08-30 17:19:16 -0700281 if (contactUri != null) {
Tyler Gunn296489e2018-01-16 21:40:43 -0800282 ArrayList<Notification.Person> personList = new ArrayList<>();
283 personList.add(new Notification.Person().setUri(contactUri.toString()));
284 peopleExtras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, personList);
Yorke Lee8a736a82014-08-30 17:19:16 -0700285 }
Tyler Gunn296489e2018-01-16 21:40:43 -0800286 return manager.matchesCallFilter(peopleExtras);
Yorke Lee8a736a82014-08-30 17:19:16 -0700287 }
288
Joseph Pirozzoee4089c2017-12-13 16:38:10 -0800289 private boolean hasExternalRinger(Call foregroundCall) {
290 Bundle intentExtras = foregroundCall.getIntentExtras();
291 if (intentExtras != null) {
292 return intentExtras.getBoolean(TelecomManager.EXTRA_CALL_EXTERNAL_RINGER, false);
293 } else {
294 return false;
295 }
296 }
297
Tyler Gunn68d2f862017-01-10 15:00:23 -0800298 private boolean shouldVibrate(Context context, Call call) {
Evan Charlton198fde82014-04-07 10:53:11 -0700299 AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
John Spurlock15226912014-11-25 08:38:47 -0500300 int ringerMode = audioManager.getRingerModeInternal();
Tyler Gunn68d2f862017-01-10 15:00:23 -0800301 boolean shouldVibrate;
Evan Charlton198fde82014-04-07 10:53:11 -0700302 if (getVibrateWhenRinging(context)) {
Tyler Gunn68d2f862017-01-10 15:00:23 -0800303 shouldVibrate = ringerMode != AudioManager.RINGER_MODE_SILENT;
Evan Charlton198fde82014-04-07 10:53:11 -0700304 } else {
Tyler Gunn68d2f862017-01-10 15:00:23 -0800305 shouldVibrate = ringerMode == AudioManager.RINGER_MODE_VIBRATE;
Evan Charlton198fde82014-04-07 10:53:11 -0700306 }
Tyler Gunn68d2f862017-01-10 15:00:23 -0800307
308 // Technically this should be in the calling method, but it seemed a little odd to pass
309 // around a whole bunch of state just for logging purposes.
310 if (shouldVibrate) {
311 Log.addEvent(call, LogUtils.Events.START_VIBRATOR,
312 "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
313 mVibrator.hasVibrator(), mSystemSettingsUtil.canVibrateWhenRinging(context),
314 ringerMode, mIsVibrating);
315 } else {
316 Log.addEvent(call, LogUtils.Events.SKIP_VIBRATION,
317 "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b",
318 mVibrator.hasVibrator(), mSystemSettingsUtil.canVibrateWhenRinging(context),
319 ringerMode, mIsVibrating);
320 }
321
322 return shouldVibrate;
Evan Charlton198fde82014-04-07 10:53:11 -0700323 }
324
325 private boolean getVibrateWhenRinging(Context context) {
326 if (!mVibrator.hasVibrator()) {
327 return false;
328 }
Brad Ebingerd931a012015-10-21 12:54:08 -0700329 return mSystemSettingsUtil.canVibrateWhenRinging(context);
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700330 }
331}