Merge "Add notification cache for VoipCallMonitor to avoid match failure between notifications and calls." into udc-dev
diff --git a/src/com/android/server/telecom/voip/VoipCallMonitor.java b/src/com/android/server/telecom/voip/VoipCallMonitor.java
index 67af11d..84fdb5d 100644
--- a/src/com/android/server/telecom/voip/VoipCallMonitor.java
+++ b/src/com/android/server/telecom/voip/VoipCallMonitor.java
@@ -49,7 +49,9 @@
public class VoipCallMonitor extends CallsManagerListenerBase {
private final List<Call> mPendingCalls;
- private final Map<StatusBarNotification, Call> mNotifications;
+ // Same notification may be passed as different object in onNotificationPosted and
+ // onNotificationRemoved. Use its string as key to cache ongoing notifications.
+ private final Map<String, Call> mNotifications;
private final Map<PhoneAccountHandle, Set<Call>> mPhoneAccountHandleListMap;
private ActivityManagerInternal mActivityManagerInternal;
private final Map<PhoneAccountHandle, ServiceConnection> mServices;
@@ -58,6 +60,7 @@
private final HandlerThread mHandlerThread;
private final Handler mHandler;
private final Context mContext;
+ private List<StatusBarNotification> mPendingSBN;
public VoipCallMonitor(Context context, TelecomSystem.SyncRoot lock) {
mContext = context;
@@ -65,6 +68,7 @@
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
mPendingCalls = new ArrayList<>();
+ mPendingSBN = new ArrayList<>();
mNotifications = new HashMap<>();
mServices = new HashMap<>();
mPhoneAccountHandleListMap = new HashMap<>();
@@ -74,24 +78,21 @@
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
synchronized (mLock) {
- if (mPendingCalls.isEmpty()) {
- return;
- }
if (sbn.getNotification().isStyle(Notification.CallStyle.class)) {
- String packageName = sbn.getPackageName();
- UserHandle userHandle = sbn.getUser();
-
+ boolean sbnMatched = false;
for (Call call : mPendingCalls) {
- if (packageName != null &&
- packageName.equals(call.getTargetPhoneAccount()
- .getComponentName().getPackageName())
- && userHandle != null
- && userHandle.equals(call.getInitiatingUser())) {
+ if (notificationMatchedCall(sbn, call)) {
mPendingCalls.remove(call);
- mNotifications.put(sbn, call);
+ mNotifications.put(sbn.toString(), call);
+ sbnMatched = true;
break;
}
}
+ if (!sbnMatched) {
+ // notification may posted before we started to monitor the call, cache
+ // this notification and try to match it later with new added call.
+ mPendingSBN.add(sbn);
+ }
}
}
}
@@ -99,12 +100,13 @@
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
synchronized (mLock) {
+ mPendingSBN.remove(sbn);
if (mNotifications.isEmpty()) {
return;
}
- Call call = mNotifications.getOrDefault(sbn, null);
+ Call call = mNotifications.getOrDefault(sbn.toString(), null);
if (call != null) {
- mNotifications.remove(sbn, call);
+ mNotifications.remove(sbn.toString(), call);
stopFGSDelegation(call.getTargetPhoneAccount());
}
}
@@ -225,15 +227,31 @@
}
private void startMonitorNotification(Call call) {
- mPendingCalls.add(call);
- mHandler.postDelayed(() -> {
- synchronized (mLock) {
- if (mPendingCalls.contains(call)) {
- stopFGSDelegation(call.getTargetPhoneAccount());
- mPendingCalls.remove(call);
+ synchronized (mLock) {
+ boolean sbnMatched = false;
+ for (StatusBarNotification sbn : mPendingSBN) {
+ if (notificationMatchedCall(sbn, call)) {
+ mPendingSBN.remove(sbn);
+ mNotifications.put(sbn.toString(), call);
+ sbnMatched = true;
+ break;
}
}
- }, 5000L);
+ if (!sbnMatched) {
+ // Only continue to
+ mPendingCalls.add(call);
+ mHandler.postDelayed(() -> {
+ synchronized (mLock) {
+ if (mPendingCalls.contains(call)) {
+ Log.i(this, "Notification for voip-call %s haven't "
+ + "posted in time, stop delegation.", call.getId());
+ stopFGSDelegation(call.getTargetPhoneAccount());
+ mPendingCalls.remove(call);
+ }
+ }
+ }, 5000L);
+ }
+ }
}
private void stopMonitorNotification(Call call) {
@@ -249,4 +267,16 @@
public void setNotificationListenerService(NotificationListenerService listener) {
mNotificationListener = listener;
}
+
+ private boolean notificationMatchedCall(StatusBarNotification sbn, Call call) {
+ String packageName = sbn.getPackageName();
+ UserHandle userHandle = sbn.getUser();
+ PhoneAccountHandle accountHandle = call.getTargetPhoneAccount();
+
+ return packageName != null &&
+ packageName.equals(call.getTargetPhoneAccount()
+ .getComponentName().getPackageName())
+ && userHandle != null
+ && userHandle.equals(accountHandle.getUserHandle());
+ }
}