Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4a0f46a2 authored by Thomas Stuart's avatar Thomas Stuart Committed by Android (Google) Code Review
Browse files

Merge "Add notification cache for VoipCallMonitor to avoid match failure...

Merge "Add notification cache for VoipCallMonitor to avoid match failure between notifications and calls." into udc-dev
parents c08d1148 8f27d246
Loading
Loading
Loading
Loading
+52 −22
Original line number Diff line number Diff line
@@ -49,7 +49,9 @@ import java.util.Set;
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 @@ public class VoipCallMonitor extends CallsManagerListenerBase {
    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 @@ public class VoipCallMonitor extends CallsManagerListenerBase {
        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 @@ public class VoipCallMonitor extends CallsManagerListenerBase {
            @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 @@ public class VoipCallMonitor extends CallsManagerListenerBase {
            @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,16 +227,32 @@ public class VoipCallMonitor extends CallsManagerListenerBase {
    }

    private void startMonitorNotification(Call 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;
                }
            }
            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) {
        mPendingCalls.remove(call);
@@ -249,4 +267,16 @@ public class VoipCallMonitor extends CallsManagerListenerBase {
    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());
    }
}