add anom report and more logs to Ringer haptics
Some users reported their incoming calls did not vibrate even though
their settings indicate vibrate. It's not clear what exactly is
happening so more logs should be added to the haptics path.
Flag: com.android.server.telecom.flags.get_ringer_mode_anom_report
Bug: 307389562
Test: manual
Change-Id: If2b88c7c6141007899d870e49e334d758bd02745
diff --git a/flags/telecom_ringer_flag_declarations.aconfig b/flags/telecom_ringer_flag_declarations.aconfig
index 6517e0f..f954b09 100644
--- a/flags/telecom_ringer_flag_declarations.aconfig
+++ b/flags/telecom_ringer_flag_declarations.aconfig
@@ -15,4 +15,16 @@
namespace: "telecom"
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
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 9670d6a..22b28b5 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -703,7 +703,7 @@
ringtoneFactory, systemVibrator,
new Ringer.VibrationEffectProxy(), mInCallController,
mContext.getSystemService(NotificationManager.class),
- accessibilityManagerAdapter, featureFlags);
+ accessibilityManagerAdapter, featureFlags, mAnomalyReporter);
if (featureFlags.telecomResolveHiddenDependencies()) {
// This is now deprecated
mCallRecordingTonePlayer = null;
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 12778b0..bfaadf0 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -59,6 +59,7 @@
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;
@@ -176,6 +177,11 @@
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.
@@ -191,6 +197,8 @@
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)}.
@@ -237,7 +245,8 @@
InCallController inCallController,
NotificationManager notificationManager,
AccessibilityManagerAdapter accessibilityManagerAdapter,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ AnomalyReporterAdapter anomalyReporter) {
mLock = new Object();
mSystemSettingsUtil = systemSettingsUtil;
@@ -252,6 +261,7 @@
mVibrationEffectProxy = vibrationEffectProxy;
mNotificationManager = notificationManager;
mAccessibilityManagerAdapter = accessibilityManagerAdapter;
+ mAnomalyReporter = anomalyReporter;
mDefaultVibrationEffect =
loadDefaultRingVibrationEffect(
@@ -405,10 +415,9 @@
// 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);
- }
+ 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);
@@ -437,7 +446,7 @@
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);
@@ -706,12 +715,43 @@
// 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();
diff --git a/tests/src/com/android/server/telecom/tests/RingerTest.java b/tests/src/com/android/server/telecom/tests/RingerTest.java
index c4d9678..46916fd 100644
--- a/tests/src/com/android/server/telecom/tests/RingerTest.java
+++ b/tests/src/com/android/server/telecom/tests/RingerTest.java
@@ -66,6 +66,7 @@
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;
@@ -123,6 +124,7 @@
@Mock NotificationManager mockNotificationManager;
@Mock Ringer.AccessibilityManagerAdapter mockAccessibilityManagerAdapter;
@Mock private FeatureFlags mFeatureFlags;
+ @Mock private AnomalyReporterAdapter mAnomalyReporterAdapter;
@Spy Ringer.VibrationEffectProxy spyVibrationEffectProxy;
@@ -178,7 +180,7 @@
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);
}