Loading flags/telecom_ringer_flag_declarations.aconfig +12 −0 Original line number Diff line number Diff line Loading @@ -16,3 +16,15 @@ flag { description: "Gates whether to ensure that when a user is in their car, they are able to hear ringing for an incoming call." bug: "348708398" } # OWNER=tjstuart TARGET=25Q1 flag { name: "get_ringer_mode_anom_report" namespace: "telecom" description: "getRingerMode & getRingerModeInternal should return the same val when dnd is off" bug: "307389562" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file src/com/android/server/telecom/CallsManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -703,7 +703,7 @@ public class CallsManager extends Call.ListenerBase ringtoneFactory, systemVibrator, new Ringer.VibrationEffectProxy(), mInCallController, mContext.getSystemService(NotificationManager.class), accessibilityManagerAdapter, featureFlags); accessibilityManagerAdapter, featureFlags, mAnomalyReporter); if (featureFlags.telecomResolveHiddenDependencies()) { // This is now deprecated mCallRecordingTonePlayer = null; Loading src/com/android/server/telecom/Ringer.java +45 −5 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; Loading Loading @@ -176,6 +177,11 @@ public class Ringer { private static VolumeShaper.Configuration mVolumeShaperConfig; public static final UUID GET_RINGER_MODE_ANOMALY_UUID = UUID.fromString("eb10505b-4d7b-4fab-b4a1-a18186799065"); public static final String GET_RINGER_MODE_ANOMALY_MSG = "AM#GetRingerMode() and" + " AM#GetRingerModeInternal() are returning diff values when DoNotDisturb is OFF!"; /** * Used to keep ordering of unanswered incoming calls. There can easily exist multiple incoming * calls and explicit ordering is useful for maintaining the proper state of the ringer. Loading @@ -191,6 +197,8 @@ public class Ringer { private final boolean mIsHapticPlaybackSupportedByDevice; private final FeatureFlags mFlags; private final boolean mRingtoneVibrationSupported; private final AnomalyReporterAdapter mAnomalyReporter; /** * For unit testing purposes only; when set, {@link #startRinging(Call, boolean)} will complete * the future provided by the test using {@link #setBlockOnRingingFuture(CompletableFuture)}. Loading Loading @@ -237,7 +245,8 @@ public class Ringer { InCallController inCallController, NotificationManager notificationManager, AccessibilityManagerAdapter accessibilityManagerAdapter, FeatureFlags featureFlags) { FeatureFlags featureFlags, AnomalyReporterAdapter anomalyReporter) { mLock = new Object(); mSystemSettingsUtil = systemSettingsUtil; Loading @@ -252,6 +261,7 @@ public class Ringer { mVibrationEffectProxy = vibrationEffectProxy; mNotificationManager = notificationManager; mAccessibilityManagerAdapter = accessibilityManagerAdapter; mAnomalyReporter = anomalyReporter; mDefaultVibrationEffect = loadDefaultRingVibrationEffect( Loading Loading @@ -405,10 +415,9 @@ public class Ringer { // If ringer is not audible for this call, then the phone is in "Vibrate" mode. // Use haptic-only ringtone or do not play anything. isHapticOnly = true; if (DEBUG_RINGER) { Log.i(this, "Set ringtone as haptic only: " + isHapticOnly); } } else { Log.i(this, "ringer & haptics are off, user missed alerts for call"); foregroundCall.setUserMissed(USER_MISSED_NO_VIBRATE); Log.addEvent(foregroundCall, LogUtils.Events.SKIP_VIBRATION, vibratorAttrs); Loading Loading @@ -437,7 +446,7 @@ public class Ringer { ringtoneInfoSupplier = () -> mRingtoneFactory.getRingtone( foregroundCall, null, false); } Log.i(this, "isRingtoneInfoSupplierNull=[%b]", ringtoneInfoSupplier == null); // If vibration will be done, reserve the vibrator. boolean vibratorReserved = isVibratorEnabled && attributes.shouldRingForContact() && tryReserveVibration(foregroundCall); Loading Loading @@ -706,12 +715,43 @@ public class Ringer { // AudioManager#getRingerModeInternal which only useful for volume controllers boolean zenModeOn = mNotificationManager != null && mNotificationManager.getZenMode() != ZEN_MODE_OFF; maybeGenAnomReportForGetRingerMode(zenModeOn, audioManager); return mVibrator.hasVibrator() && mSystemSettingsUtil.isRingVibrationEnabled(context) && (audioManager.getRingerMode() != AudioManager.RINGER_MODE_SILENT || (zenModeOn && shouldRingForContact)); } /** * There are 3 settings for haptics: * - AudioManager.RINGER_MODE_SILENT * - AudioManager.RINGER_MODE_VIBRATE * - AudioManager.RINGER_MODE_NORMAL * If the user does not have {@link AudioManager#RINGER_MODE_SILENT} set, the user should * have haptic feeback * * Note: If DND/ZEN_MODE is on, {@link AudioManager#getRingerMode()} will return * {@link AudioManager#RINGER_MODE_SILENT}, regardless of the user setting. Therefore, * getRingerModeInternal is the source of truth instead of {@link AudioManager#getRingerMode()}. * However, if DND/ZEN_MOD is off, the APIs should return the same value. Generate an anomaly * report if they diverge. */ private void maybeGenAnomReportForGetRingerMode(boolean isZenModeOn, AudioManager am) { if (!mFlags.getRingerModeAnomReport()) { return; } if (!isZenModeOn) { int ringerMode = am.getRingerMode(); int ringerModeInternal = am.getRingerModeInternal(); if (ringerMode != ringerModeInternal) { Log.i(this, "getRingerMode=[%d], getRingerModeInternal=[%d]", ringerMode, ringerModeInternal); mAnomalyReporter.reportAnomaly(GET_RINGER_MODE_ANOMALY_UUID, GET_RINGER_MODE_ANOMALY_MSG); } } } private RingerAttributes getRingerAttributes(Call call, boolean isHfpDeviceAttached) { mAudioManager = mContext.getSystemService(AudioManager.class); RingerAttributes.Builder builder = new RingerAttributes.Builder(); Loading tests/src/com/android/server/telecom/tests/RingerTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import android.util.Pair; import androidx.test.filters.SmallTest; import com.android.server.telecom.AnomalyReporterAdapter; import com.android.server.telecom.AsyncRingtonePlayer; import com.android.server.telecom.Call; import com.android.server.telecom.CallState; Loading Loading @@ -123,6 +124,7 @@ public class RingerTest extends TelecomTestCase { @Mock NotificationManager mockNotificationManager; @Mock Ringer.AccessibilityManagerAdapter mockAccessibilityManagerAdapter; @Mock private FeatureFlags mFeatureFlags; @Mock private AnomalyReporterAdapter mAnomalyReporterAdapter; @Spy Ringer.VibrationEffectProxy spyVibrationEffectProxy; Loading Loading @@ -178,7 +180,7 @@ public class RingerTest extends TelecomTestCase { mRingerUnderTest = new Ringer(mockPlayerFactory, mContext, mockSystemSettingsUtil, asyncRingtonePlayer, mockRingtoneFactory, mockVibrator, spyVibrationEffectProxy, mockInCallController, mockNotificationManager, mockAccessibilityManagerAdapter, mFeatureFlags); mFeatureFlags, mAnomalyReporterAdapter); // This future is used to wait for AsyncRingtonePlayer to finish its part. mRingerUnderTest.setBlockOnRingingFuture(mRingCompletionFuture); } Loading Loading
flags/telecom_ringer_flag_declarations.aconfig +12 −0 Original line number Diff line number Diff line Loading @@ -16,3 +16,15 @@ flag { description: "Gates whether to ensure that when a user is in their car, they are able to hear ringing for an incoming call." bug: "348708398" } # OWNER=tjstuart TARGET=25Q1 flag { name: "get_ringer_mode_anom_report" namespace: "telecom" description: "getRingerMode & getRingerModeInternal should return the same val when dnd is off" bug: "307389562" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file
src/com/android/server/telecom/CallsManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -703,7 +703,7 @@ public class CallsManager extends Call.ListenerBase ringtoneFactory, systemVibrator, new Ringer.VibrationEffectProxy(), mInCallController, mContext.getSystemService(NotificationManager.class), accessibilityManagerAdapter, featureFlags); accessibilityManagerAdapter, featureFlags, mAnomalyReporter); if (featureFlags.telecomResolveHiddenDependencies()) { // This is now deprecated mCallRecordingTonePlayer = null; Loading
src/com/android/server/telecom/Ringer.java +45 −5 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; Loading Loading @@ -176,6 +177,11 @@ public class Ringer { private static VolumeShaper.Configuration mVolumeShaperConfig; public static final UUID GET_RINGER_MODE_ANOMALY_UUID = UUID.fromString("eb10505b-4d7b-4fab-b4a1-a18186799065"); public static final String GET_RINGER_MODE_ANOMALY_MSG = "AM#GetRingerMode() and" + " AM#GetRingerModeInternal() are returning diff values when DoNotDisturb is OFF!"; /** * Used to keep ordering of unanswered incoming calls. There can easily exist multiple incoming * calls and explicit ordering is useful for maintaining the proper state of the ringer. Loading @@ -191,6 +197,8 @@ public class Ringer { private final boolean mIsHapticPlaybackSupportedByDevice; private final FeatureFlags mFlags; private final boolean mRingtoneVibrationSupported; private final AnomalyReporterAdapter mAnomalyReporter; /** * For unit testing purposes only; when set, {@link #startRinging(Call, boolean)} will complete * the future provided by the test using {@link #setBlockOnRingingFuture(CompletableFuture)}. Loading Loading @@ -237,7 +245,8 @@ public class Ringer { InCallController inCallController, NotificationManager notificationManager, AccessibilityManagerAdapter accessibilityManagerAdapter, FeatureFlags featureFlags) { FeatureFlags featureFlags, AnomalyReporterAdapter anomalyReporter) { mLock = new Object(); mSystemSettingsUtil = systemSettingsUtil; Loading @@ -252,6 +261,7 @@ public class Ringer { mVibrationEffectProxy = vibrationEffectProxy; mNotificationManager = notificationManager; mAccessibilityManagerAdapter = accessibilityManagerAdapter; mAnomalyReporter = anomalyReporter; mDefaultVibrationEffect = loadDefaultRingVibrationEffect( Loading Loading @@ -405,10 +415,9 @@ public class Ringer { // If ringer is not audible for this call, then the phone is in "Vibrate" mode. // Use haptic-only ringtone or do not play anything. isHapticOnly = true; if (DEBUG_RINGER) { Log.i(this, "Set ringtone as haptic only: " + isHapticOnly); } } else { Log.i(this, "ringer & haptics are off, user missed alerts for call"); foregroundCall.setUserMissed(USER_MISSED_NO_VIBRATE); Log.addEvent(foregroundCall, LogUtils.Events.SKIP_VIBRATION, vibratorAttrs); Loading Loading @@ -437,7 +446,7 @@ public class Ringer { ringtoneInfoSupplier = () -> mRingtoneFactory.getRingtone( foregroundCall, null, false); } Log.i(this, "isRingtoneInfoSupplierNull=[%b]", ringtoneInfoSupplier == null); // If vibration will be done, reserve the vibrator. boolean vibratorReserved = isVibratorEnabled && attributes.shouldRingForContact() && tryReserveVibration(foregroundCall); Loading Loading @@ -706,12 +715,43 @@ public class Ringer { // AudioManager#getRingerModeInternal which only useful for volume controllers boolean zenModeOn = mNotificationManager != null && mNotificationManager.getZenMode() != ZEN_MODE_OFF; maybeGenAnomReportForGetRingerMode(zenModeOn, audioManager); return mVibrator.hasVibrator() && mSystemSettingsUtil.isRingVibrationEnabled(context) && (audioManager.getRingerMode() != AudioManager.RINGER_MODE_SILENT || (zenModeOn && shouldRingForContact)); } /** * There are 3 settings for haptics: * - AudioManager.RINGER_MODE_SILENT * - AudioManager.RINGER_MODE_VIBRATE * - AudioManager.RINGER_MODE_NORMAL * If the user does not have {@link AudioManager#RINGER_MODE_SILENT} set, the user should * have haptic feeback * * Note: If DND/ZEN_MODE is on, {@link AudioManager#getRingerMode()} will return * {@link AudioManager#RINGER_MODE_SILENT}, regardless of the user setting. Therefore, * getRingerModeInternal is the source of truth instead of {@link AudioManager#getRingerMode()}. * However, if DND/ZEN_MOD is off, the APIs should return the same value. Generate an anomaly * report if they diverge. */ private void maybeGenAnomReportForGetRingerMode(boolean isZenModeOn, AudioManager am) { if (!mFlags.getRingerModeAnomReport()) { return; } if (!isZenModeOn) { int ringerMode = am.getRingerMode(); int ringerModeInternal = am.getRingerModeInternal(); if (ringerMode != ringerModeInternal) { Log.i(this, "getRingerMode=[%d], getRingerModeInternal=[%d]", ringerMode, ringerModeInternal); mAnomalyReporter.reportAnomaly(GET_RINGER_MODE_ANOMALY_UUID, GET_RINGER_MODE_ANOMALY_MSG); } } } private RingerAttributes getRingerAttributes(Call call, boolean isHfpDeviceAttached) { mAudioManager = mContext.getSystemService(AudioManager.class); RingerAttributes.Builder builder = new RingerAttributes.Builder(); Loading
tests/src/com/android/server/telecom/tests/RingerTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import android.util.Pair; import androidx.test.filters.SmallTest; import com.android.server.telecom.AnomalyReporterAdapter; import com.android.server.telecom.AsyncRingtonePlayer; import com.android.server.telecom.Call; import com.android.server.telecom.CallState; Loading Loading @@ -123,6 +124,7 @@ public class RingerTest extends TelecomTestCase { @Mock NotificationManager mockNotificationManager; @Mock Ringer.AccessibilityManagerAdapter mockAccessibilityManagerAdapter; @Mock private FeatureFlags mFeatureFlags; @Mock private AnomalyReporterAdapter mAnomalyReporterAdapter; @Spy Ringer.VibrationEffectProxy spyVibrationEffectProxy; Loading Loading @@ -178,7 +180,7 @@ public class RingerTest extends TelecomTestCase { mRingerUnderTest = new Ringer(mockPlayerFactory, mContext, mockSystemSettingsUtil, asyncRingtonePlayer, mockRingtoneFactory, mockVibrator, spyVibrationEffectProxy, mockInCallController, mockNotificationManager, mockAccessibilityManagerAdapter, mFeatureFlags); mFeatureFlags, mAnomalyReporterAdapter); // This future is used to wait for AsyncRingtonePlayer to finish its part. mRingerUnderTest.setBlockOnRingingFuture(mRingCompletionFuture); } Loading