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