1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 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 14 * limitations under the License 15 */ 16 17 package com.android.server.telecom; 18 19 import static android.provider.CallLog.Calls.USER_MISSED_DND_MODE; 20 import static android.provider.CallLog.Calls.USER_MISSED_LOW_RING_VOLUME; 21 import static android.provider.CallLog.Calls.USER_MISSED_NO_VIBRATE; 22 import static android.provider.Settings.Global.ZEN_MODE_OFF; 23 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.app.Notification; 27 import android.app.NotificationManager; 28 import android.app.Person; 29 import android.content.Context; 30 import android.content.res.Resources; 31 import android.media.AudioManager; 32 import android.media.Ringtone; 33 import android.media.VolumeShaper; 34 import android.net.Uri; 35 import android.os.Bundle; 36 import android.os.Handler; 37 import android.os.HandlerThread; 38 import android.os.UserHandle; 39 import android.os.UserManager; 40 import android.os.VibrationAttributes; 41 import android.os.VibrationEffect; 42 import android.os.Vibrator; 43 import android.os.vibrator.persistence.ParsedVibration; 44 import android.os.vibrator.persistence.VibrationXmlParser; 45 import android.telecom.Log; 46 import android.telecom.TelecomManager; 47 import android.util.Pair; 48 import android.view.accessibility.AccessibilityManager; 49 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.server.telecom.LogUtils.EventTimer; 52 import com.android.server.telecom.flags.FeatureFlags; 53 54 import java.io.InputStream; 55 import java.io.InputStreamReader; 56 import java.io.IOException; 57 import java.nio.charset.StandardCharsets; 58 import java.util.ArrayList; 59 import java.util.concurrent.CompletableFuture; 60 import java.util.concurrent.CountDownLatch; 61 import java.util.concurrent.ExecutionException; 62 import java.util.concurrent.TimeUnit; 63 import java.util.concurrent.TimeoutException; 64 import java.util.function.BiConsumer; 65 import java.util.function.Supplier; 66 67 /** 68 * Controls the ringtone player. 69 */ 70 @VisibleForTesting 71 public class Ringer { 72 private static final String TAG = "TelecomRinger"; 73 74 public interface AccessibilityManagerAdapter { startFlashNotificationSequence(@onNull Context context, @AccessibilityManager.FlashNotificationReason int reason)75 boolean startFlashNotificationSequence(@NonNull Context context, 76 @AccessibilityManager.FlashNotificationReason int reason); stopFlashNotificationSequence(@onNull Context context)77 boolean stopFlashNotificationSequence(@NonNull Context context); 78 } 79 /** 80 * Flag only for local debugging. Do not submit enabled. 81 */ 82 private static final boolean DEBUG_RINGER = false; 83 84 public static class VibrationEffectProxy { createWaveform(long[] timings, int[] amplitudes, int repeat)85 public VibrationEffect createWaveform(long[] timings, int[] amplitudes, int repeat) { 86 return VibrationEffect.createWaveform(timings, amplitudes, repeat); 87 } 88 get(Uri ringtoneUri, Context context)89 public VibrationEffect get(Uri ringtoneUri, Context context) { 90 return VibrationEffect.get(ringtoneUri, context); 91 } 92 } 93 @VisibleForTesting 94 public VibrationEffect mDefaultVibrationEffect; 95 96 // Used for test to notify the completion of RingerAttributes 97 private CountDownLatch mAttributesLatch; 98 99 /** 100 * Delay to be used between consecutive vibrations when a non-repeating vibration effect is 101 * provided by the device. 102 * 103 * <p>If looking to customize the loop delay for a device's ring vibration, the desired repeat 104 * behavior should be encoded directly in the effect specification in the device configuration 105 * rather than changing the here (i.e. in `R.raw.default_ringtone_vibration_effect` resource). 106 */ 107 private static int DEFAULT_RING_VIBRATION_LOOP_DELAY_MS = 1000; 108 109 private static final long[] PULSE_PRIMING_PATTERN = {0,12,250,12,500}; // priming + interval 110 111 private static final int[] PULSE_PRIMING_AMPLITUDE = {0,255,0,255,0}; // priming + interval 112 113 // ease-in + peak + pause 114 private static final long[] PULSE_RAMPING_PATTERN = { 115 50,50,50,50,50,50,50,50,50,50,50,50,50,50,300,1000}; 116 117 // ease-in (min amplitude = 30%) + peak + pause 118 private static final int[] PULSE_RAMPING_AMPLITUDE = { 119 77,77,78,79,81,84,87,93,101,114,133,162,205,255,255,0}; 120 121 @VisibleForTesting 122 public static final long[] PULSE_PATTERN; 123 124 @VisibleForTesting 125 public static final int[] PULSE_AMPLITUDE; 126 127 private static final int RAMPING_RINGER_VIBRATION_DURATION = 5000; 128 private static final int RAMPING_RINGER_DURATION = 10000; 129 130 static { 131 // construct complete pulse pattern 132 PULSE_PATTERN = new long[PULSE_PRIMING_PATTERN.length + PULSE_RAMPING_PATTERN.length]; System.arraycopy( PULSE_PRIMING_PATTERN, 0, PULSE_PATTERN, 0, PULSE_PRIMING_PATTERN.length)133 System.arraycopy( 134 PULSE_PRIMING_PATTERN, 0, PULSE_PATTERN, 0, PULSE_PRIMING_PATTERN.length); System.arraycopy(PULSE_RAMPING_PATTERN, 0, PULSE_PATTERN, PULSE_PRIMING_PATTERN.length, PULSE_RAMPING_PATTERN.length)135 System.arraycopy(PULSE_RAMPING_PATTERN, 0, PULSE_PATTERN, 136 PULSE_PRIMING_PATTERN.length, PULSE_RAMPING_PATTERN.length); 137 138 // construct complete pulse amplitude 139 PULSE_AMPLITUDE = new int[PULSE_PRIMING_AMPLITUDE.length + PULSE_RAMPING_AMPLITUDE.length]; System.arraycopy( PULSE_PRIMING_AMPLITUDE, 0, PULSE_AMPLITUDE, 0, PULSE_PRIMING_AMPLITUDE.length)140 System.arraycopy( 141 PULSE_PRIMING_AMPLITUDE, 0, PULSE_AMPLITUDE, 0, PULSE_PRIMING_AMPLITUDE.length); System.arraycopy(PULSE_RAMPING_AMPLITUDE, 0, PULSE_AMPLITUDE, PULSE_PRIMING_AMPLITUDE.length, PULSE_RAMPING_AMPLITUDE.length)142 System.arraycopy(PULSE_RAMPING_AMPLITUDE, 0, PULSE_AMPLITUDE, 143 PULSE_PRIMING_AMPLITUDE.length, PULSE_RAMPING_AMPLITUDE.length); 144 } 145 146 private static final long[] SIMPLE_VIBRATION_PATTERN = { 147 0, // No delay before starting 148 1000, // How long to vibrate 149 1000, // How long to wait before vibrating again 150 }; 151 152 private static final int[] SIMPLE_VIBRATION_AMPLITUDE = { 153 0, // No delay before starting 154 255, // Vibrate full amplitude 155 0, // No amplitude while waiting 156 }; 157 158 /** 159 * Indicates that vibration should be repeated at element 5 in the {@link #PULSE_AMPLITUDE} and 160 * {@link #PULSE_PATTERN} arrays. This means repetition will happen for the main ease-in/peak 161 * pattern, but the priming + interval part will not be repeated. 162 */ 163 private static final int REPEAT_VIBRATION_AT = 5; 164 165 private static final int REPEAT_SIMPLE_VIBRATION_AT = 1; 166 167 private static final long RINGER_ATTRIBUTES_TIMEOUT = 5000; // 5 seconds 168 169 private static final float EPSILON = 1e-6f; 170 171 private static final VibrationAttributes VIBRATION_ATTRIBUTES = 172 new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_RINGTONE).build(); 173 174 private static VolumeShaper.Configuration mVolumeShaperConfig; 175 176 /** 177 * Used to keep ordering of unanswered incoming calls. There can easily exist multiple incoming 178 * calls and explicit ordering is useful for maintaining the proper state of the ringer. 179 */ 180 181 private final SystemSettingsUtil mSystemSettingsUtil; 182 private final InCallTonePlayer.Factory mPlayerFactory; 183 private final AsyncRingtonePlayer mRingtonePlayer; 184 private final Context mContext; 185 private final Vibrator mVibrator; 186 private final InCallController mInCallController; 187 private final VibrationEffectProxy mVibrationEffectProxy; 188 private final boolean mIsHapticPlaybackSupportedByDevice; 189 private final FeatureFlags mFlags; 190 /** 191 * For unit testing purposes only; when set, {@link #startRinging(Call, boolean)} will complete 192 * the future provided by the test using {@link #setBlockOnRingingFuture(CompletableFuture)}. 193 */ 194 private CompletableFuture<Void> mBlockOnRingingFuture = null; 195 196 private InCallTonePlayer mCallWaitingPlayer; 197 private RingtoneFactory mRingtoneFactory; 198 private AudioManager mAudioManager; 199 private NotificationManager mNotificationManager; 200 private AccessibilityManagerAdapter mAccessibilityManagerAdapter; 201 202 /** 203 * Call objects that are ringing, vibrating or call-waiting. These are used only for logging 204 * purposes (except mVibratingCall is also used to ensure consistency). 205 */ 206 private Call mRingingCall; 207 private Call mVibratingCall; 208 private Call mCallWaitingCall; 209 210 /** 211 * Used to track the status of {@link #mVibrator} in the case of simultaneous incoming calls. 212 */ 213 private boolean mIsVibrating = false; 214 215 private Handler mHandler = null; 216 217 /** 218 * Use lock different from the Telecom sync because ringing process is asynchronous outside that 219 * lock 220 */ 221 private final Object mLock; 222 223 /** Initializes the Ringer. */ 224 @VisibleForTesting Ringer( InCallTonePlayer.Factory playerFactory, Context context, SystemSettingsUtil systemSettingsUtil, AsyncRingtonePlayer asyncRingtonePlayer, RingtoneFactory ringtoneFactory, Vibrator vibrator, VibrationEffectProxy vibrationEffectProxy, InCallController inCallController, NotificationManager notificationManager, AccessibilityManagerAdapter accessibilityManagerAdapter, FeatureFlags featureFlags)225 public Ringer( 226 InCallTonePlayer.Factory playerFactory, 227 Context context, 228 SystemSettingsUtil systemSettingsUtil, 229 AsyncRingtonePlayer asyncRingtonePlayer, 230 RingtoneFactory ringtoneFactory, 231 Vibrator vibrator, 232 VibrationEffectProxy vibrationEffectProxy, 233 InCallController inCallController, 234 NotificationManager notificationManager, 235 AccessibilityManagerAdapter accessibilityManagerAdapter, 236 FeatureFlags featureFlags) { 237 238 mLock = new Object(); 239 mSystemSettingsUtil = systemSettingsUtil; 240 mPlayerFactory = playerFactory; 241 mContext = context; 242 // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure this 243 // vibrator object will be isolated from others. 244 mVibrator = vibrator; 245 mRingtonePlayer = asyncRingtonePlayer; 246 mRingtoneFactory = ringtoneFactory; 247 mInCallController = inCallController; 248 mVibrationEffectProxy = vibrationEffectProxy; 249 mNotificationManager = notificationManager; 250 mAccessibilityManagerAdapter = accessibilityManagerAdapter; 251 252 mDefaultVibrationEffect = 253 loadDefaultRingVibrationEffect( 254 mContext, mVibrator, mVibrationEffectProxy, featureFlags); 255 256 mIsHapticPlaybackSupportedByDevice = 257 mSystemSettingsUtil.isHapticPlaybackSupported(mContext); 258 259 mAudioManager = mContext.getSystemService(AudioManager.class); 260 mFlags = featureFlags; 261 } 262 263 @VisibleForTesting setBlockOnRingingFuture(CompletableFuture<Void> future)264 public void setBlockOnRingingFuture(CompletableFuture<Void> future) { 265 mBlockOnRingingFuture = future; 266 } 267 268 @VisibleForTesting setNotificationManager(NotificationManager notificationManager)269 public void setNotificationManager(NotificationManager notificationManager) { 270 mNotificationManager = notificationManager; 271 } 272 startRinging(Call foregroundCall, boolean isHfpDeviceAttached)273 public boolean startRinging(Call foregroundCall, boolean isHfpDeviceAttached) { 274 boolean deferBlockOnRingingFuture = false; 275 // try-finally to ensure that the block on ringing future is always called. 276 try { 277 if (foregroundCall == null) { 278 Log.wtf(this, "startRinging called with null foreground call."); 279 return false; 280 } 281 282 if (foregroundCall.getState() != CallState.RINGING 283 && foregroundCall.getState() != CallState.SIMULATED_RINGING) { 284 // It's possible for bluetooth to connect JUST as a call goes active, which would 285 // mean the call would start ringing again. 286 Log.i(this, "startRinging called for non-ringing foreground callid=%s", 287 foregroundCall.getId()); 288 return false; 289 } 290 291 // Use completable future to establish a timeout, not intent to make these work outside 292 // the main thread asynchronously 293 // TODO: moving these RingerAttributes calculation out of Telecom lock to avoid blocking 294 CompletableFuture<RingerAttributes> ringerAttributesFuture = CompletableFuture 295 .supplyAsync(() -> getRingerAttributes(foregroundCall, isHfpDeviceAttached), 296 new LoggedHandlerExecutor(getHandler(), "R.sR", null)); 297 298 RingerAttributes attributes = null; 299 try { 300 mAttributesLatch = new CountDownLatch(1); 301 attributes = ringerAttributesFuture.get( 302 RINGER_ATTRIBUTES_TIMEOUT, TimeUnit.MILLISECONDS); 303 } catch (ExecutionException | InterruptedException | TimeoutException e) { 304 // Keep attributes as null 305 Log.i(this, "getAttributes error: " + e); 306 } 307 308 if (attributes == null) { 309 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, 310 "RingerAttributes error"); 311 return false; 312 } 313 314 if (attributes.isEndEarly()) { 315 boolean acquireAudioFocus = attributes.shouldAcquireAudioFocus(); 316 if (attributes.letDialerHandleRinging()) { 317 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, "Dialer handles"); 318 // Dialer will setup a ringtone, provide the audio focus if its audible. 319 acquireAudioFocus |= attributes.isRingerAudible(); 320 } 321 322 if (attributes.isSilentRingingRequested()) { 323 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, "Silent ringing " 324 + "requested"); 325 } 326 if (attributes.isWorkProfileInQuietMode()) { 327 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, 328 "Work profile in quiet mode"); 329 } 330 return acquireAudioFocus; 331 } 332 333 stopCallWaiting(); 334 335 final boolean shouldFlash = attributes.shouldRingForContact(); 336 if (mAccessibilityManagerAdapter != null && shouldFlash) { 337 Log.addEvent(foregroundCall, LogUtils.Events.FLASH_NOTIFICATION_START); 338 getHandler().post(() -> 339 mAccessibilityManagerAdapter.startFlashNotificationSequence(mContext, 340 AccessibilityManager.FLASH_REASON_CALL)); 341 } 342 343 // Determine if the settings and DND mode indicate that the vibrator can be used right 344 // now. 345 final boolean isVibratorEnabled = 346 isVibratorEnabled(mContext, attributes.shouldRingForContact()); 347 boolean shouldApplyRampingRinger = 348 isVibratorEnabled && mSystemSettingsUtil.isRampingRingerEnabled(mContext); 349 350 boolean isHapticOnly = false; 351 boolean useCustomVibrationEffect = false; 352 353 mVolumeShaperConfig = null; 354 355 if (attributes.isRingerAudible()) { 356 mRingingCall = foregroundCall; 357 Log.addEvent(foregroundCall, LogUtils.Events.START_RINGER); 358 // Because we wait until a contact info query to complete before processing a 359 // call (for the purposes of direct-to-voicemail), the information about custom 360 // ringtones should be available by the time this code executes. We can safely 361 // request the custom ringtone from the call and expect it to be current. 362 if (shouldApplyRampingRinger) { 363 Log.i(this, "create ramping ringer."); 364 float silencePoint = (float) (RAMPING_RINGER_VIBRATION_DURATION) 365 / (float) (RAMPING_RINGER_VIBRATION_DURATION + RAMPING_RINGER_DURATION); 366 mVolumeShaperConfig = 367 new VolumeShaper.Configuration.Builder() 368 .setDuration(RAMPING_RINGER_VIBRATION_DURATION 369 + RAMPING_RINGER_DURATION) 370 .setCurve( 371 new float[]{0.f, silencePoint + EPSILON 372 /*keep monotonicity*/, 1.f}, 373 new float[]{0.f, 0.f, 1.f}) 374 .setInterpolatorType( 375 VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR) 376 .build(); 377 if (mSystemSettingsUtil.isAudioCoupledVibrationForRampingRingerEnabled()) { 378 useCustomVibrationEffect = true; 379 } 380 } else { 381 if (DEBUG_RINGER) { 382 Log.i(this, "Create ringer with custom vibration effect"); 383 } 384 // Ramping ringtone is not enabled. 385 useCustomVibrationEffect = true; 386 } 387 } else { 388 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING, 389 "Inaudible: " + attributes.getInaudibleReason() 390 + " isVibratorEnabled=" + isVibratorEnabled); 391 392 if (isVibratorEnabled) { 393 // If ringer is not audible for this call, then the phone is in "Vibrate" mode. 394 // Use haptic-only ringtone or do not play anything. 395 isHapticOnly = true; 396 if (DEBUG_RINGER) { 397 Log.i(this, "Set ringtone as haptic only: " + isHapticOnly); 398 } 399 } else { 400 foregroundCall.setUserMissed(USER_MISSED_NO_VIBRATE); 401 return attributes.shouldAcquireAudioFocus(); // ringer not audible 402 } 403 } 404 405 boolean hapticChannelsMuted = !isVibratorEnabled || !mIsHapticPlaybackSupportedByDevice; 406 if (shouldApplyRampingRinger 407 && !mSystemSettingsUtil.isAudioCoupledVibrationForRampingRingerEnabled() 408 && isVibratorEnabled) { 409 Log.i(this, "Muted haptic channels since audio coupled ramping ringer is disabled"); 410 hapticChannelsMuted = true; 411 } else if (hapticChannelsMuted) { 412 Log.i(this, 413 "Muted haptic channels isVibratorEnabled=%s, hapticPlaybackSupported=%s", 414 isVibratorEnabled, mIsHapticPlaybackSupportedByDevice); 415 } 416 // Defer ringtone creation to the async player thread. 417 Supplier<Pair<Uri, Ringtone>> ringtoneInfoSupplier; 418 final boolean finalHapticChannelsMuted = hapticChannelsMuted; 419 if (isHapticOnly) { 420 if (hapticChannelsMuted) { 421 Log.i(this, 422 "want haptic only ringtone but haptics are muted, skip ringtone play"); 423 ringtoneInfoSupplier = null; 424 } else { 425 ringtoneInfoSupplier = mRingtoneFactory::getHapticOnlyRingtone; 426 } 427 } else { 428 ringtoneInfoSupplier = () -> mRingtoneFactory.getRingtone( 429 foregroundCall, mVolumeShaperConfig, finalHapticChannelsMuted); 430 } 431 432 // If vibration will be done, reserve the vibrator. 433 boolean vibratorReserved = isVibratorEnabled && attributes.shouldRingForContact() 434 && tryReserveVibration(foregroundCall); 435 if (!vibratorReserved) { 436 foregroundCall.setUserMissed(USER_MISSED_NO_VIBRATE); 437 Log.addEvent(foregroundCall, LogUtils.Events.SKIP_VIBRATION, 438 "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, " 439 + "isVibratorEnabled=%b", 440 mVibrator.hasVibrator(), 441 mSystemSettingsUtil.isRingVibrationEnabled(mContext), 442 mAudioManager.getRingerMode(), isVibratorEnabled); 443 } 444 445 // The vibration logic depends on the loaded ringtone, but we need to defer the ringtone 446 // load to the async ringtone thread. Hence, we bundle up the final part of this method 447 // for that thread to run after loading the ringtone. This logic is intended to run even 448 // if the loaded ringtone is null. However if a stop event arrives before the ringtone 449 // creation finishes, then this consumer can be skipped. 450 final boolean finalUseCustomVibrationEffect = useCustomVibrationEffect; 451 BiConsumer<Pair<Uri, Ringtone>, Boolean> afterRingtoneLogic = 452 (Pair<Uri, Ringtone> ringtoneInfo, Boolean stopped) -> { 453 try { 454 Uri ringtoneUri = null; 455 Ringtone ringtone = null; 456 if (ringtoneInfo != null) { 457 ringtoneUri = ringtoneInfo.first; 458 ringtone = ringtoneInfo.second; 459 } else { 460 Log.w(this, "The ringtone could not be loaded."); 461 } 462 463 if (stopped.booleanValue() || !vibratorReserved) { 464 // don't start vibration if the ringing is already abandoned, or the 465 // vibrator wasn't reserved. This still triggers the mBlockOnRingingFuture. 466 return; 467 } 468 final VibrationEffect vibrationEffect; 469 if (ringtone != null && finalUseCustomVibrationEffect) { 470 if (DEBUG_RINGER) { 471 Log.d(this, "Using ringtone defined vibration effect."); 472 } 473 vibrationEffect = getVibrationEffectForRingtone(ringtoneUri); 474 } else { 475 vibrationEffect = mDefaultVibrationEffect; 476 } 477 478 boolean isUsingAudioCoupledHaptics = 479 !finalHapticChannelsMuted && ringtone != null 480 && ringtone.hasHapticChannels(); 481 vibrateIfNeeded(isUsingAudioCoupledHaptics, foregroundCall, vibrationEffect); 482 } finally { 483 // This is used to signal to tests that the async play() call has completed. 484 if (mBlockOnRingingFuture != null) { 485 mBlockOnRingingFuture.complete(null); 486 } 487 } 488 }; 489 deferBlockOnRingingFuture = true; // Run in vibrationLogic. 490 if (ringtoneInfoSupplier != null) { 491 mRingtonePlayer.play(ringtoneInfoSupplier, afterRingtoneLogic, isHfpDeviceAttached); 492 } else { 493 afterRingtoneLogic.accept(/* ringtoneUri, ringtone = */ null, /* stopped= */ false); 494 } 495 496 // shouldAcquireAudioFocus is meant to be true, but that check is deferred to here 497 // because until now is when we actually know if the ringtone loading worked. 498 return attributes.shouldAcquireAudioFocus() 499 || (!isHapticOnly && attributes.isRingerAudible()); 500 } finally { 501 // This is used to signal to tests that the async play() call has completed. It can 502 // be deferred into AsyncRingtonePlayer 503 if (mBlockOnRingingFuture != null && !deferBlockOnRingingFuture) { 504 mBlockOnRingingFuture.complete(null); 505 } 506 } 507 } 508 509 /** 510 * Try to reserve the vibrator for this call, returning false if it's already committed. 511 * The vibration will be started by AsyncRingtonePlayer to ensure timing is aligned with the 512 * audio. The logic uses mVibratingCall to say which call is currently getting ready to vibrate, 513 * or actually vibrating (indicated by mIsVibrating). 514 * 515 * Once reserved, the vibrateIfNeeded method is expected to be called. Note that if 516 * audio-coupled haptics were used instead of vibrator, the reservation still stays until 517 * ringing is stopped, because the vibrator is exclusive to a single vibration source. 518 * 519 * Note that this "reservation" is only local to the Ringer - it's not locking the vibrator, so 520 * if it's busy with some other important vibration, this ringer's one may not displace it. 521 */ tryReserveVibration(Call foregroundCall)522 private boolean tryReserveVibration(Call foregroundCall) { 523 synchronized (mLock) { 524 if (mVibratingCall != null || mIsVibrating) { 525 return false; 526 } 527 mVibratingCall = foregroundCall; 528 return true; 529 } 530 } 531 vibrateIfNeeded(boolean isUsingAudioCoupledHaptics, Call foregroundCall, VibrationEffect effect)532 private void vibrateIfNeeded(boolean isUsingAudioCoupledHaptics, Call foregroundCall, 533 VibrationEffect effect) { 534 if (isUsingAudioCoupledHaptics) { 535 Log.addEvent( 536 foregroundCall, LogUtils.Events.SKIP_VIBRATION, "using audio-coupled haptics"); 537 return; 538 } 539 540 synchronized (mLock) { 541 // Ensure the reservation is live. The mIsVibrating check should be redundant. 542 if (foregroundCall == mVibratingCall && !mIsVibrating) { 543 Log.addEvent(foregroundCall, LogUtils.Events.START_VIBRATOR, 544 "hasVibrator=%b, userRequestsVibrate=%b, ringerMode=%d, isVibrating=%b", 545 mVibrator.hasVibrator(), mSystemSettingsUtil.isRingVibrationEnabled(mContext), 546 mAudioManager.getRingerMode(), mIsVibrating); 547 mIsVibrating = true; 548 mVibrator.vibrate(effect, VIBRATION_ATTRIBUTES); 549 Log.i(this, "start vibration."); 550 } 551 // else stopped already: this isn't started unless a reservation was made. 552 } 553 } 554 getVibrationEffectForRingtone(Uri ringtoneUri)555 private VibrationEffect getVibrationEffectForRingtone(Uri ringtoneUri) { 556 if (ringtoneUri == null) { 557 return mDefaultVibrationEffect; 558 } 559 try { 560 VibrationEffect effect = mVibrationEffectProxy.get(ringtoneUri, mContext); 561 if (effect == null) { 562 Log.i(this, "did not find vibration effect, falling back to default vibration"); 563 return mDefaultVibrationEffect; 564 } 565 return effect; 566 } catch (IllegalArgumentException iae) { 567 // Deep in the bowels of the VibrationEffect class it is possible for an 568 // IllegalArgumentException to be thrown if there is an invalid URI specified in the 569 // device config, or a content provider failure. Rather than crashing the Telecom 570 // process we will just use the default vibration effect. 571 Log.e(this, iae, "getVibrationEffectForRingtone: failed to get vibration effect"); 572 return mDefaultVibrationEffect; 573 } 574 } 575 startCallWaiting(Call call)576 public void startCallWaiting(Call call) { 577 startCallWaiting(call, null); 578 } 579 startCallWaiting(Call call, String reason)580 public void startCallWaiting(Call call, String reason) { 581 if (mSystemSettingsUtil.isTheaterModeOn(mContext)) { 582 return; 583 } 584 585 if (mInCallController.doesConnectedDialerSupportRinging( 586 call.getAssociatedUser())) { 587 Log.addEvent(call, LogUtils.Events.SKIP_RINGING, "Dialer handles"); 588 return; 589 } 590 591 if (call.isSelfManaged()) { 592 Log.addEvent(call, LogUtils.Events.SKIP_RINGING, "Self-managed"); 593 return; 594 } 595 596 Log.v(this, "Playing call-waiting tone."); 597 598 stopRinging(); 599 600 if (mCallWaitingPlayer == null) { 601 Log.addEvent(call, LogUtils.Events.START_CALL_WAITING_TONE, reason); 602 mCallWaitingCall = call; 603 mCallWaitingPlayer = 604 mPlayerFactory.createPlayer(call, InCallTonePlayer.TONE_CALL_WAITING); 605 mCallWaitingPlayer.startTone(); 606 } 607 } 608 stopRinging()609 public void stopRinging() { 610 final Call foregroundCall = mRingingCall != null ? mRingingCall : mVibratingCall; 611 if (mAccessibilityManagerAdapter != null) { 612 Log.addEvent(foregroundCall, LogUtils.Events.FLASH_NOTIFICATION_STOP); 613 getHandler().post(() -> 614 mAccessibilityManagerAdapter.stopFlashNotificationSequence(mContext)); 615 } 616 617 synchronized (mLock) { 618 if (mRingingCall != null) { 619 Log.addEvent(mRingingCall, LogUtils.Events.STOP_RINGER); 620 mRingingCall = null; 621 } 622 623 mRingtonePlayer.stop(); 624 625 if (mIsVibrating) { 626 Log.addEvent(mVibratingCall, LogUtils.Events.STOP_VIBRATOR); 627 mVibrator.cancel(); 628 mIsVibrating = false; 629 } 630 mVibratingCall = null; // Prevents vibrations from starting via AsyncRingtonePlayer. 631 } 632 } 633 stopCallWaiting()634 public void stopCallWaiting() { 635 Log.v(this, "stop call waiting."); 636 if (mCallWaitingPlayer != null) { 637 if (mCallWaitingCall != null) { 638 Log.addEvent(mCallWaitingCall, LogUtils.Events.STOP_CALL_WAITING_TONE); 639 mCallWaitingCall = null; 640 } 641 642 mCallWaitingPlayer.stopTone(); 643 mCallWaitingPlayer = null; 644 } 645 } 646 isRinging()647 public boolean isRinging() { 648 return mRingtonePlayer.isPlaying(); 649 } 650 651 /** 652 * shouldRingForContact checks if the caller matches one of the Do Not Disturb bypass 653 * settings (ex. A contact or repeat caller might be able to bypass DND settings). If 654 * matchesCallFilter returns true, this means the caller can bypass the Do Not Disturb settings 655 * and interrupt the user; otherwise call is suppressed. 656 */ shouldRingForContact(Call call)657 public boolean shouldRingForContact(Call call) { 658 // avoid re-computing manager.matcherCallFilter(Bundle) 659 if (call.wasDndCheckComputedForCall()) { 660 Log.i(this, "shouldRingForContact: returning computation from DndCallFilter."); 661 return !call.isCallSuppressedByDoNotDisturb(); 662 } 663 Uri contactUri = call.getHandle(); 664 if (mFlags.telecomResolveHiddenDependencies()) { 665 if (contactUri == null) { 666 contactUri = Uri.EMPTY; 667 } 668 return mNotificationManager.matchesCallFilter(contactUri); 669 } else { 670 final Bundle peopleExtras = new Bundle(); 671 if (contactUri != null) { 672 ArrayList<Person> personList = new ArrayList<>(); 673 personList.add(new Person.Builder().setUri(contactUri.toString()).build()); 674 peopleExtras.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, personList); 675 } 676 return mNotificationManager.matchesCallFilter(peopleExtras); 677 } 678 } 679 hasExternalRinger(Call foregroundCall)680 private boolean hasExternalRinger(Call foregroundCall) { 681 Bundle intentExtras = foregroundCall.getIntentExtras(); 682 if (intentExtras != null) { 683 return intentExtras.getBoolean(TelecomManager.EXTRA_CALL_HAS_IN_BAND_RINGTONE, false); 684 } else { 685 return false; 686 } 687 } 688 isVibratorEnabled(Context context, boolean shouldRingForContact)689 private boolean isVibratorEnabled(Context context, boolean shouldRingForContact) { 690 AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 691 // Use AudioManager#getRingerMode for more accurate result, instead of 692 // AudioManager#getRingerModeInternal which only useful for volume controllers 693 boolean zenModeOn = mNotificationManager != null 694 && mNotificationManager.getZenMode() != ZEN_MODE_OFF; 695 return mVibrator.hasVibrator() 696 && mSystemSettingsUtil.isRingVibrationEnabled(context) 697 && (audioManager.getRingerMode() != AudioManager.RINGER_MODE_SILENT 698 || (zenModeOn && shouldRingForContact)); 699 } 700 getRingerAttributes(Call call, boolean isHfpDeviceAttached)701 private RingerAttributes getRingerAttributes(Call call, boolean isHfpDeviceAttached) { 702 mAudioManager = mContext.getSystemService(AudioManager.class); 703 RingerAttributes.Builder builder = new RingerAttributes.Builder(); 704 705 LogUtils.EventTimer timer = new EventTimer(); 706 707 boolean isVolumeOverZero = mAudioManager.getStreamVolume(AudioManager.STREAM_RING) > 0; 708 timer.record("isVolumeOverZero"); 709 boolean shouldRingForContact = shouldRingForContact(call); 710 timer.record("shouldRingForContact"); 711 boolean isSelfManaged = call.isSelfManaged(); 712 timer.record("isSelfManaged"); 713 boolean isSilentRingingRequested = call.isSilentRingingRequested(); 714 timer.record("isSilentRingRequested"); 715 716 boolean isRingerAudible = isVolumeOverZero && shouldRingForContact; 717 timer.record("isRingerAudible"); 718 String inaudibleReason = ""; 719 if (!isRingerAudible) { 720 inaudibleReason = String.format("isVolumeOverZero=%s, shouldRingForContact=%s", 721 isVolumeOverZero, shouldRingForContact); 722 } 723 724 boolean hasExternalRinger = hasExternalRinger(call); 725 timer.record("hasExternalRinger"); 726 // Don't do call waiting operations or vibration unless these are false. 727 boolean isTheaterModeOn = mSystemSettingsUtil.isTheaterModeOn(mContext); 728 timer.record("isTheaterModeOn"); 729 boolean letDialerHandleRinging = mInCallController.doesConnectedDialerSupportRinging( 730 call.getAssociatedUser()); 731 timer.record("letDialerHandleRinging"); 732 boolean isWorkProfileInQuietMode = 733 isProfileInQuietMode(call.getAssociatedUser()); 734 timer.record("isWorkProfileInQuietMode"); 735 736 Log.i(this, "startRinging timings: " + timer); 737 boolean endEarly = isTheaterModeOn || letDialerHandleRinging || isSelfManaged || 738 hasExternalRinger || isSilentRingingRequested || isWorkProfileInQuietMode; 739 740 if (endEarly) { 741 Log.i(this, "Ending early -- isTheaterModeOn=%s, letDialerHandleRinging=%s, " + 742 "isSelfManaged=%s, hasExternalRinger=%s, silentRingingRequested=%s, " + 743 "isWorkProfileInQuietMode=%s", 744 isTheaterModeOn, letDialerHandleRinging, isSelfManaged, hasExternalRinger, 745 isSilentRingingRequested, isWorkProfileInQuietMode); 746 } 747 748 // Acquire audio focus under any of the following conditions: 749 // 1. Should ring for contact and there's an HFP device attached 750 // 2. Volume is over zero, we should ring for the contact, and there's a audible ringtone 751 // present. (This check is deferred until ringer knows the ringtone) 752 // 3. The call is self-managed. 753 boolean shouldAcquireAudioFocus = !isWorkProfileInQuietMode && 754 ((isHfpDeviceAttached && shouldRingForContact) || isSelfManaged); 755 756 // Set missed reason according to attributes 757 if (!isVolumeOverZero) { 758 call.setUserMissed(USER_MISSED_LOW_RING_VOLUME); 759 } 760 if (!shouldRingForContact) { 761 call.setUserMissed(USER_MISSED_DND_MODE); 762 } 763 764 mAttributesLatch.countDown(); 765 return builder.setEndEarly(endEarly) 766 .setLetDialerHandleRinging(letDialerHandleRinging) 767 .setAcquireAudioFocus(shouldAcquireAudioFocus) 768 .setRingerAudible(isRingerAudible) 769 .setInaudibleReason(inaudibleReason) 770 .setShouldRingForContact(shouldRingForContact) 771 .setSilentRingingRequested(isSilentRingingRequested) 772 .setWorkProfileQuietMode(isWorkProfileInQuietMode) 773 .build(); 774 } 775 isProfileInQuietMode(UserHandle user)776 private boolean isProfileInQuietMode(UserHandle user) { 777 UserManager um = mContext.getSystemService(UserManager.class); 778 return um.isManagedProfile(user.getIdentifier()) && um.isQuietModeEnabled(user); 779 } 780 getHandler()781 private Handler getHandler() { 782 if (mHandler == null) { 783 HandlerThread handlerThread = new HandlerThread("Ringer"); 784 handlerThread.start(); 785 mHandler = handlerThread.getThreadHandler(); 786 } 787 return mHandler; 788 } 789 790 @VisibleForTesting waitForAttributesCompletion()791 public boolean waitForAttributesCompletion() throws InterruptedException { 792 if (mAttributesLatch != null) { 793 return mAttributesLatch.await(RINGER_ATTRIBUTES_TIMEOUT, TimeUnit.MILLISECONDS); 794 } else { 795 return false; 796 } 797 } 798 799 @Nullable loadSerializedDefaultRingVibration( Resources resources, Vibrator vibrator)800 private static VibrationEffect loadSerializedDefaultRingVibration( 801 Resources resources, Vibrator vibrator) { 802 try { 803 InputStream vibrationInputStream = 804 resources.openRawResource( 805 com.android.internal.R.raw.default_ringtone_vibration_effect); 806 ParsedVibration parsedVibration = VibrationXmlParser 807 .parseDocument( 808 new InputStreamReader(vibrationInputStream, StandardCharsets.UTF_8)); 809 if (parsedVibration == null) { 810 Log.w(TAG, "Got null parsed default ring vibration effect."); 811 return null; 812 } 813 return parsedVibration.resolve(vibrator); 814 } catch (IOException | Resources.NotFoundException e) { 815 Log.e(TAG, e, "Error parsing default ring vibration effect."); 816 return null; 817 } 818 } 819 loadDefaultRingVibrationEffect( Context context, Vibrator vibrator, VibrationEffectProxy vibrationEffectProxy, FeatureFlags featureFlags)820 private static VibrationEffect loadDefaultRingVibrationEffect( 821 Context context, 822 Vibrator vibrator, 823 VibrationEffectProxy vibrationEffectProxy, 824 FeatureFlags featureFlags) { 825 Resources resources = context.getResources(); 826 827 if (resources.getBoolean(R.bool.use_simple_vibration_pattern)) { 828 Log.i(TAG, "Using simple default ring vibration."); 829 return createSimpleRingVibration(vibrationEffectProxy); 830 } 831 832 if (featureFlags.useDeviceProvidedSerializedRingerVibration()) { 833 VibrationEffect parsedEffect = loadSerializedDefaultRingVibration(resources, vibrator); 834 if (parsedEffect != null) { 835 Log.i(TAG, "Using parsed default ring vibration."); 836 // Make the parsed effect repeating to make it vibrate continuously during ring. 837 // If the effect is already repeating, this API call is a no-op. 838 // Otherwise, it uses `DEFAULT_RING_VIBRATION_LOOP_DELAY_MS` when changing a 839 // non-repeating vibration to a repeating vibration. 840 // This is so that we ensure consecutive loops of the vibration play with some gap 841 // in between. 842 return parsedEffect.applyRepeatingIndefinitely( 843 /* wantRepeating= */ true, DEFAULT_RING_VIBRATION_LOOP_DELAY_MS); 844 } 845 // Fallback to the simple vibration if the serialized effect cannot be loaded. 846 return createSimpleRingVibration(vibrationEffectProxy); 847 } 848 849 Log.i(TAG, "Using pulse default ring vibration."); 850 return vibrationEffectProxy.createWaveform( 851 PULSE_PATTERN, PULSE_AMPLITUDE, REPEAT_VIBRATION_AT); 852 } 853 createSimpleRingVibration( VibrationEffectProxy vibrationEffectProxy)854 private static VibrationEffect createSimpleRingVibration( 855 VibrationEffectProxy vibrationEffectProxy) { 856 return vibrationEffectProxy.createWaveform(SIMPLE_VIBRATION_PATTERN, 857 SIMPLE_VIBRATION_AMPLITUDE, REPEAT_SIMPLE_VIBRATION_AT); 858 } 859 } 860