Snap for 12763142 from 2b4afe184102aa658d23547704d738a2e11aec4e to 25Q1-release
Change-Id: Ib83bf7667c8fe0fb682e576435f57813414c9fa6
diff --git a/flags/telecom_anomaly_report_flags.aconfig b/flags/telecom_anomaly_report_flags.aconfig
index b060ed0..5d42b86 100644
--- a/flags/telecom_anomaly_report_flags.aconfig
+++ b/flags/telecom_anomaly_report_flags.aconfig
@@ -16,3 +16,14 @@
description: "If a self-managed call is stuck in certain states, disconnect it"
bug: "360298368"
}
+
+# OWNER=tgunn TARGET=25Q2
+flag {
+ name: "dont_timeout_destroyed_calls"
+ namespace: "telecom"
+ description: "When create connection timeout is hit, if call is already destroyed, skip anomaly"
+ bug: "381684580"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/telecom_bluetoothdevicemanager_flags.aconfig b/flags/telecom_bluetoothdevicemanager_flags.aconfig
index 4c91491..9b1b53e 100644
--- a/flags/telecom_bluetoothdevicemanager_flags.aconfig
+++ b/flags/telecom_bluetoothdevicemanager_flags.aconfig
@@ -8,3 +8,13 @@
description: "Fix for Log.wtf in the BinderProxy"
bug: "333417369"
}
+# OWNER=huiwang TARGET=25Q1
+flag {
+ name: "keep_bt_devices_cache_updated"
+ namespace: "telecom"
+ description: "Fix the devices cache issue of BluetoothDeviceManager"
+ bug: "380320985"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
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/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 14c8f62..260c238 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -130,11 +130,7 @@
synchronized (mLock) {
logIncoming("handleCreateConnectionComplete %s", callId);
Call call = mCallIdMapper.getCall(callId);
- if (call != null && mScheduledFutureMap.containsKey(call)) {
- ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
- existingTimeout.cancel(false /* cancelIfRunning */);
- mScheduledFutureMap.remove(call);
- }
+ maybeRemoveCleanupFuture(call);
// Check status hints image for cross user access
if (connection.getStatusHints() != null) {
Icon icon = connection.getStatusHints().getIcon();
@@ -174,11 +170,7 @@
synchronized (mLock) {
logIncoming("handleCreateConferenceComplete %s", callId);
Call call = mCallIdMapper.getCall(callId);
- if (call != null && mScheduledFutureMap.containsKey(call)) {
- ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
- existingTimeout.cancel(false /* cancelIfRunning */);
- mScheduledFutureMap.remove(call);
- }
+ maybeRemoveCleanupFuture(call);
// Check status hints image for cross user access
if (conference.getStatusHints() != null) {
Icon icon = conference.getStatusHints().getIcon();
@@ -1678,6 +1670,9 @@
Log.getExternalSession(TELECOM_ABBREVIATION));
} catch (RemoteException e) {
Log.e(this, e, "Failure to createConference -- %s", getComponentName());
+ if (mFlags.dontTimeoutDestroyedCalls()) {
+ maybeRemoveCleanupFuture(call);
+ }
mPendingResponses.remove(callId).handleCreateConferenceFailure(
new DisconnectCause(DisconnectCause.ERROR, e.toString()));
}
@@ -1708,6 +1703,9 @@
Log.i(ConnectionServiceWrapper.this, "Call not present"
+ " in call id mapper, maybe it was aborted before the bind"
+ " completed successfully?");
+ if (mFlags.dontTimeoutDestroyedCalls()) {
+ maybeRemoveCleanupFuture(call);
+ }
response.handleCreateConnectionFailure(
new DisconnectCause(DisconnectCause.CANCELED));
return;
@@ -1793,6 +1791,9 @@
mScheduledFutureMap.put(call, future);
try {
if (mFlags.cswServiceInterfaceIsNull() && mServiceInterface == null) {
+ if (mFlags.dontTimeoutDestroyedCalls()) {
+ maybeRemoveCleanupFuture(call);
+ }
mPendingResponses.remove(callId).handleCreateConnectionFailure(
new DisconnectCause(DisconnectCause.ERROR,
"CSW#oCC ServiceInterface is null"));
@@ -1807,6 +1808,9 @@
}
} catch (RemoteException e) {
Log.e(this, e, "Failure to createConnection -- %s", getComponentName());
+ if (mFlags.dontTimeoutDestroyedCalls()) {
+ maybeRemoveCleanupFuture(call);
+ }
mPendingResponses.remove(callId).handleCreateConnectionFailure(
new DisconnectCause(DisconnectCause.ERROR, e.toString()));
}
@@ -2286,6 +2290,9 @@
if (response != null) {
response.handleCreateConnectionFailure(disconnectCause);
}
+ if (mFlags.dontTimeoutDestroyedCalls()) {
+ maybeRemoveCleanupFuture(mCallIdMapper.getCall(callId));
+ }
mCallIdMapper.removeCall(callId);
}
@@ -2295,6 +2302,9 @@
if (response != null) {
response.handleCreateConnectionFailure(disconnectCause);
}
+ if (mFlags.dontTimeoutDestroyedCalls()) {
+ maybeRemoveCleanupFuture(call);
+ }
mCallIdMapper.removeCall(call);
}
@@ -2754,4 +2764,20 @@
public void setAnomalyReporterAdapter(AnomalyReporterAdapter mAnomalyReporterAdapter){
mAnomalyReporter = mAnomalyReporterAdapter;
}
+
+ /**
+ * Given a call, unschedule and cancel the cleanup future.
+ * @param call the call.
+ */
+ private void maybeRemoveCleanupFuture(Call call) {
+ if (call == null) {
+ return;
+ }
+ ScheduledFuture<?> future = mScheduledFutureMap.remove(call);
+ if (future == null) {
+ return;
+ }
+ future.cancel(false /* interrupt */);
+
+ }
}
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/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index 4f0aa89..dbc858b 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -519,7 +519,10 @@
Log.i(this, "onDeviceConnected: Adding device with address: %s and devicetype=%s",
device, getDeviceTypeString(deviceType));
targetDeviceMap.put(device.getAddress(), device);
- mBluetoothRouteManager.onDeviceAdded(device.getAddress());
+ if (!mFeatureFlags.keepBtDevicesCacheUpdated()
+ || !mFeatureFlags.useRefactoredAudioRouteSwitching()) {
+ mBluetoothRouteManager.onDeviceAdded(device.getAddress());
+ }
}
}
}
@@ -551,7 +554,10 @@
Log.i(this, "onDeviceDisconnected: Removing device with address: %s, devicetype=%s",
device, getDeviceTypeString(deviceType));
targetDeviceMap.remove(device.getAddress());
- mBluetoothRouteManager.onDeviceLost(device.getAddress());
+ if (!mFeatureFlags.keepBtDevicesCacheUpdated()
+ || !mFeatureFlags.useRefactoredAudioRouteSwitching()) {
+ mBluetoothRouteManager.onDeviceLost(device.getAddress());
+ }
}
}
}
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
index 7fe8246..679db67 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
@@ -211,6 +211,9 @@
if (mFeatureFlags.useRefactoredAudioRouteSwitching()) {
mCallAudioRouteAdapter.sendMessageWithSessionInfo(BT_DEVICE_ADDED,
audioRouteType, device);
+ if (mFeatureFlags.keepBtDevicesCacheUpdated()) {
+ mBluetoothDeviceManager.onDeviceConnected(device, deviceType);
+ }
} else {
mBluetoothDeviceManager.onDeviceConnected(device, deviceType);
}
@@ -219,6 +222,9 @@
if (mFeatureFlags.useRefactoredAudioRouteSwitching()) {
mCallAudioRouteAdapter.sendMessageWithSessionInfo(BT_DEVICE_REMOVED,
audioRouteType, device);
+ if (mFeatureFlags.keepBtDevicesCacheUpdated()) {
+ mBluetoothDeviceManager.onDeviceDisconnected(device, deviceType);
+ }
} else {
mBluetoothDeviceManager.onDeviceDisconnected(device, deviceType);
}
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);
}