Implement RCS Dedicated Bearer metrics - fix not reporting case

Implement and update to store and pull Dedicated Bearer event atoms.

BUG: 174871215
Test: atest QosCallbackTrackerTest
Merged-In: Ia3106c8422eafa39b7ead632fabe1085f93e5cf4
Change-Id: Ia3106c8422eafa39b7ead632fabe1085f93e5cf4
diff --git a/src/java/com/android/internal/telephony/data/QosCallbackTracker.java b/src/java/com/android/internal/telephony/data/QosCallbackTracker.java
index 4df69e0..8ecd28c 100644
--- a/src/java/com/android/internal/telephony/data/QosCallbackTracker.java
+++ b/src/java/com/android/internal/telephony/data/QosCallbackTracker.java
@@ -39,6 +39,7 @@
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 
@@ -184,13 +185,15 @@
             log("updateSessions: sessions size=" + sessions.size());
 
             int bearerState = DEDICATED_BEARER_EVENT_STATE_NONE;
+
             final List<QosBearerSession> sessionsToAdd = new ArrayList<>();
             final Map<Integer, QosBearerSession> incomingSessions = new HashMap<>();
+            final HashSet<Integer> sessionsReportedToMetric = new HashSet<>();
             for (final QosBearerSession incomingSession : sessions) {
-                incomingSessions.put(incomingSession.getQosBearerSessionId(), incomingSession);
+                int sessionId = incomingSession.getQosBearerSessionId();
+                incomingSessions.put(sessionId, incomingSession);
 
-                final QosBearerSession existingSession = mQosBearerSessions.get(
-                        incomingSession.getQosBearerSessionId());
+                final QosBearerSession existingSession = mQosBearerSessions.get(sessionId);
                 for (final int callbackId : mCallbacksToFilter.keySet()) {
                     final IFilter filter = mCallbacksToFilter.get(callbackId);
 
@@ -214,15 +217,31 @@
                         }
                     }
 
-                    notifyMetricDedicatedBearerEvent(incomingSession, filter, bearerState);
+                    // this QosBearerSession has registered QosCallbackId
+                    if (!sessionsReportedToMetric.contains(sessionId) && incomingSessionMatch) {
+                        // this session has listener
+                        notifyMetricDedicatedBearerEvent(incomingSession, bearerState, true);
+                        sessionsReportedToMetric.add(sessionId);
+                    }
+                }
+
+                // this QosBearerSession does not have registered QosCallbackId
+                if (!sessionsReportedToMetric.contains(sessionId)) {
+                    // no listener is registered to this session
+                    bearerState = DEDICATED_BEARER_EVENT_STATE_ADDED;
+                    notifyMetricDedicatedBearerEvent(incomingSession, bearerState, false);
+                    sessionsReportedToMetric.add(sessionId);
                 }
                 sessionsToAdd.add(incomingSession);
             }
 
             final List<Integer> sessionsToRemove = new ArrayList<>();
+            sessionsReportedToMetric.clear();
+            bearerState = DEDICATED_BEARER_EVENT_STATE_DELETED;
             // Find sessions that no longer exist
             for (final QosBearerSession existingSession : mQosBearerSessions.values()) {
-                if (!incomingSessions.containsKey(existingSession.getQosBearerSessionId())) {
+                final int sessionId = existingSession.getQosBearerSessionId();
+                if (!incomingSessions.containsKey(sessionId)) {
                     for (final int callbackId : mCallbacksToFilter.keySet()) {
                         final IFilter filter = mCallbacksToFilter.get(callbackId);
                         // The filter matches which means it was previously available, and now is
@@ -230,10 +249,15 @@
                         if (doFiltersMatch(existingSession, filter)) {
                             bearerState = DEDICATED_BEARER_EVENT_STATE_DELETED;
                             sendSessionLost(callbackId, existingSession);
-                            notifyMetricDedicatedBearerEvent(existingSession, filter, bearerState);
+                            notifyMetricDedicatedBearerEvent(existingSession, bearerState, true);
+                            sessionsReportedToMetric.add(sessionId);
                         }
                     }
-                    sessionsToRemove.add(existingSession.getQosBearerSessionId());
+                    sessionsToRemove.add(sessionId);
+                    if (!sessionsReportedToMetric.contains(sessionId)) {
+                        notifyMetricDedicatedBearerEvent(existingSession, bearerState, false);
+                        sessionsReportedToMetric.add(sessionId);
+                    }
                 }
             }
 
@@ -410,38 +434,36 @@
         return 0;
     }
 
+    private boolean doesLocalConnectionInfoExist(final QosBearerSession qosBearerSession) {
+        for (final QosBearerFilter sessionFilter : qosBearerSession.getQosBearerFilterList()) {
+            if (!sessionFilter.getLocalAddresses().isEmpty()
+                    && sessionFilter.getLocalPortRange().isValid()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean doesRemoteConnectionInfoExist(final QosBearerSession qosBearerSession) {
+        for (final QosBearerFilter sessionFilter : qosBearerSession.getQosBearerFilterList()) {
+            if (!sessionFilter.getRemoteAddresses().isEmpty()
+                    && sessionFilter.getRemotePortRange().isValid()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void notifyMetricDedicatedBearerEvent(final QosBearerSession session,
-            final IFilter filter, final int bearerState) {
+            final int bearerState, final boolean hasListener) {
+        final int slotId = mPhoneId;
+        int ratAtEnd = getRatInfoFromSessionInfo(session);
+        int qci = getQCIFromSessionInfo(session);
+        boolean localConnectionInfoReceived = doesLocalConnectionInfoExist(session);
+        boolean remoteConnectionInfoReceived = doesRemoteConnectionInfoExist(session);
 
-        int ratAtEnd;
-        int qci;
-        boolean localConnectionInfoReceived = false;
-        boolean remoteConnectionInfoReceived = false;
-
-        QosBearerFilter qosBearerFilter = getMatchingQosBearerFilter(session, filter);
-        if (session.getQos() instanceof EpsQos) {
-            ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE;
-            qci = ((EpsQos) session.getQos()).getQci();
-        } else if (session.getQos() instanceof NrQos) {
-            ratAtEnd = TelephonyManager.NETWORK_TYPE_NR;
-            qci = ((NrQos) session.getQos()).get5Qi();
-        } else {
-            return;
-        }
-
-        if (qosBearerFilter != null) {
-            if (!qosBearerFilter.getLocalAddresses().isEmpty()
-                    && qosBearerFilter.getLocalPortRange().isValid()) {
-                localConnectionInfoReceived = true;
-            }
-            if (!qosBearerFilter.getRemoteAddresses().isEmpty()
-                    && qosBearerFilter.getRemotePortRange().isValid()) {
-                remoteConnectionInfoReceived = true;
-            }
-        }
-
-        mRcsStats.onImsDedicatedBearerEvent(mPhoneId, ratAtEnd, qci, bearerState,
-                localConnectionInfoReceived, remoteConnectionInfoReceived, true);
+        mRcsStats.onImsDedicatedBearerEvent(slotId, ratAtEnd, qci, bearerState,
+                localConnectionInfoReceived, remoteConnectionInfoReceived, hasListener);
     }
 
     /**