Report sent query count

Report the sent query count when the discovery is stopped.

Bug: 287546772
Test: atest FrameworksNetTestCases NsdManagerTest
Change-Id: I47b91c0c530eee2f00920ee5ea99e8d7b6e2e9ee
diff --git a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
index 665c41c..597c06f 100644
--- a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
+++ b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
@@ -160,9 +160,10 @@
      * @param foundCallbackCount The count of found service callbacks before stop discovery.
      * @param lostCallbackCount The count of lost service callbacks before stop discovery.
      * @param servicesCount The count of found services.
+     * @param sentQueryCount The count of sent queries before stop discovery.
      */
     public void reportServiceDiscoveryStop(int transactionId, long durationMs,
-            int foundCallbackCount, int lostCallbackCount, int servicesCount) {
+            int foundCallbackCount, int lostCallbackCount, int servicesCount, int sentQueryCount) {
         final Builder builder = makeReportedBuilder();
         builder.setTransactionId(transactionId);
         builder.setType(NsdEventType.NET_DISCOVER);
@@ -171,6 +172,7 @@
         builder.setFoundCallbackCount(foundCallbackCount);
         builder.setLostCallbackCount(lostCallbackCount);
         builder.setFoundServiceCount(servicesCount);
+        builder.setSentQueryCount(sentQueryCount);
         mDependencies.statsWrite(builder.build());
     }
 
@@ -180,15 +182,17 @@
      * @param transactionId The transaction id of service resolution.
      * @param durationMs The duration of resolving services.
      * @param isServiceFromCache Whether the resolved service is from cache.
+     * @param sentQueryCount The count of sent queries during resolving.
      */
     public void reportServiceResolved(int transactionId, long durationMs,
-            boolean isServiceFromCache) {
+            boolean isServiceFromCache, int sentQueryCount) {
         final Builder builder = makeReportedBuilder();
         builder.setTransactionId(transactionId);
         builder.setType(NsdEventType.NET_RESOLVE);
         builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_RESOLVED);
         builder.setEventDurationMillisec(durationMs);
         builder.setIsKnownService(isServiceFromCache);
+        builder.setSentQueryCount(sentQueryCount);
         mDependencies.statsWrite(builder.build());
     }
 
@@ -256,9 +260,11 @@
      * @param updateCallbackCount The count of service update callbacks during this registration.
      * @param lostCallbackCount The count of service lost callbacks during this registration.
      * @param isServiceFromCache Whether the resolved service is from cache.
+     * @param sentQueryCount The count of sent queries during this registration.
      */
     public void reportServiceInfoCallbackUnregistered(int transactionId, long durationMs,
-            int updateCallbackCount, int lostCallbackCount, boolean isServiceFromCache) {
+            int updateCallbackCount, int lostCallbackCount, boolean isServiceFromCache,
+            int sentQueryCount) {
         final Builder builder = makeReportedBuilder();
         builder.setTransactionId(transactionId);
         builder.setType(NsdEventType.NET_SERVICE_INFO_CALLBACK);
@@ -267,6 +273,7 @@
         builder.setFoundCallbackCount(updateCallbackCount);
         builder.setLostCallbackCount(lostCallbackCount);
         builder.setIsKnownService(isServiceFromCache);
+        builder.setSentQueryCount(sentQueryCount);
         mDependencies.statsWrite(builder.build());
     }
 }
diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java
index e189d69..ff1f02d 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -172,6 +172,8 @@
     private static final int MAX_SERVICES_COUNT_METRIC_PER_CLIENT = 100;
     @VisibleForTesting
     static final int NO_TRANSACTION = -1;
+    private static final int NO_SENT_QUERY_COUNT = 0;
+    private static final int DISCOVERY_QUERY_SENT_CALLBACK = 1000;
     private static final SharedLog LOGGER = new SharedLog("serviceDiscovery");
 
     private final Context mContext;
@@ -288,7 +290,8 @@
         public void onSearchFailedToStart() { }
 
         @Override
-        public void onDiscoveryQuerySent(@NonNull List<String> subtypes, int transactionId) { }
+        public void onDiscoveryQuerySent(@NonNull List<String> subtypes,
+                int sentQueryTransactionId) { }
 
         @Override
         public void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode) { }
@@ -315,6 +318,13 @@
                     NsdManager.SERVICE_LOST,
                     new MdnsEvent(mClientRequestId, serviceInfo));
         }
+
+        @Override
+        public void onDiscoveryQuerySent(@NonNull List<String> subtypes,
+                int sentQueryTransactionId) {
+            mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
+                    DISCOVERY_QUERY_SENT_CALLBACK, new MdnsEvent(mClientRequestId));
+        }
     }
 
     private class ResolutionListener extends MdnsListener {
@@ -330,6 +340,13 @@
                     NsdManager.RESOLVE_SERVICE_SUCCEEDED,
                     new MdnsEvent(mClientRequestId, serviceInfo, isServiceFromCache));
         }
+
+        @Override
+        public void onDiscoveryQuerySent(@NonNull List<String> subtypes,
+                int sentQueryTransactionId) {
+            mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
+                    DISCOVERY_QUERY_SENT_CALLBACK, new MdnsEvent(mClientRequestId));
+        }
     }
 
     private class ServiceInfoListener extends MdnsListener {
@@ -360,6 +377,13 @@
                     NsdManager.SERVICE_UPDATED_LOST,
                     new MdnsEvent(mClientRequestId, serviceInfo));
         }
+
+        @Override
+        public void onDiscoveryQuerySent(@NonNull List<String> subtypes,
+                int sentQueryTransactionId) {
+            mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
+                    DISCOVERY_QUERY_SENT_CALLBACK, new MdnsEvent(mClientRequestId));
+        }
     }
 
     private class SocketRequestMonitor implements MdnsSocketProvider.SocketRequestMonitor {
@@ -465,15 +489,19 @@
      */
     private static class MdnsEvent {
         final int mClientRequestId;
-        @NonNull
+        @Nullable
         final MdnsServiceInfo mMdnsServiceInfo;
         final boolean mIsServiceFromCache;
 
-        MdnsEvent(int clientRequestId, @NonNull MdnsServiceInfo mdnsServiceInfo) {
+        MdnsEvent(int clientRequestId) {
+            this(clientRequestId, null /* mdnsServiceInfo */, false /* isServiceFromCache */);
+        }
+
+        MdnsEvent(int clientRequestId, @Nullable MdnsServiceInfo mdnsServiceInfo) {
             this(clientRequestId, mdnsServiceInfo, false /* isServiceFromCache */);
         }
 
-        MdnsEvent(int clientRequestId, @NonNull MdnsServiceInfo mdnsServiceInfo,
+        MdnsEvent(int clientRequestId, @Nullable MdnsServiceInfo mdnsServiceInfo,
                 boolean isServiceFromCache) {
             mClientRequestId = clientRequestId;
             mMdnsServiceInfo = mdnsServiceInfo;
@@ -1411,17 +1439,25 @@
 
                 final MdnsEvent event = (MdnsEvent) obj;
                 final int clientRequestId = event.mClientRequestId;
+                final ClientRequest request = clientInfo.mClientRequests.get(clientRequestId);
+                if (request == null) {
+                    Log.e(TAG, "Unknown client request. clientRequestId=" + clientRequestId);
+                    return false;
+                }
+
+                // Deal with the discovery sent callback
+                if (code == DISCOVERY_QUERY_SENT_CALLBACK) {
+                    request.onQuerySent();
+                    return true;
+                }
+
+                // Deal with other callbacks.
                 final NsdServiceInfo info = buildNsdServiceInfoFromMdnsEvent(event, code);
                 // Errors are already logged if null
                 if (info == null) return false;
                 mServiceLogs.log(String.format(
                         "MdnsDiscoveryManager event code=%s transactionId=%d",
                         NsdManager.nameOf(code), transactionId));
-                final ClientRequest request = clientInfo.mClientRequests.get(clientRequestId);
-                if (request == null) {
-                    Log.e(TAG, "Unknown client request. clientRequestId=" + clientRequestId);
-                    return false;
-                }
                 switch (code) {
                     case NsdManager.SERVICE_FOUND:
                         clientInfo.onServiceFound(clientRequestId, info, request);
@@ -2225,6 +2261,7 @@
         private int mLostServiceCount = 0;
         private final Set<String> mServices = new ArraySet<>();
         private boolean mIsServiceFromCache = false;
+        private int mSentQueryCount = NO_SENT_QUERY_COUNT;
 
         private ClientRequest(int transactionId, long startTimeMs) {
             mTransactionId = transactionId;
@@ -2265,6 +2302,14 @@
         public boolean isServiceFromCache() {
             return mIsServiceFromCache;
         }
+
+        public void onQuerySent() {
+            mSentQueryCount++;
+        }
+
+        public int getSentQueryCount() {
+            return mSentQueryCount;
+        }
     }
 
     private static class LegacyClientRequest extends ClientRequest {
@@ -2399,7 +2444,8 @@
                                 request.calculateRequestDurationMs(mClock.elapsedRealtime()),
                                 request.getFoundServiceCount(),
                                 request.getLostServiceCount(),
-                                request.getServicesCount());
+                                request.getServicesCount(),
+                                request.getSentQueryCount());
                     } else if (listener instanceof ResolutionListener) {
                         mMetrics.reportServiceResolutionStop(transactionId,
                                 request.calculateRequestDurationMs(mClock.elapsedRealtime()));
@@ -2408,7 +2454,8 @@
                                 request.calculateRequestDurationMs(mClock.elapsedRealtime()),
                                 request.getFoundServiceCount(),
                                 request.getLostServiceCount(),
-                                request.isServiceFromCache());
+                                request.isServiceFromCache(),
+                                request.getSentQueryCount());
                     }
                     continue;
                 }
@@ -2431,7 +2478,8 @@
                                 request.calculateRequestDurationMs(mClock.elapsedRealtime()),
                                 request.getFoundServiceCount(),
                                 request.getLostServiceCount(),
-                                request.getServicesCount());
+                                request.getServicesCount(),
+                                NO_SENT_QUERY_COUNT);
                         break;
                     case NsdManager.RESOLVE_SERVICE:
                         stopResolveService(transactionId);
@@ -2539,7 +2587,8 @@
                     request.calculateRequestDurationMs(mClock.elapsedRealtime()),
                     request.getFoundServiceCount(),
                     request.getLostServiceCount(),
-                    request.getServicesCount());
+                    request.getServicesCount(),
+                    request.getSentQueryCount());
             try {
                 mCb.onStopDiscoverySucceeded(listenerKey);
             } catch (RemoteException e) {
@@ -2607,7 +2656,8 @@
             mMetrics.reportServiceResolved(
                     request.mTransactionId,
                     request.calculateRequestDurationMs(mClock.elapsedRealtime()),
-                    request.isServiceFromCache());
+                    request.isServiceFromCache(),
+                    request.getSentQueryCount());
             try {
                 mCb.onResolveServiceSucceeded(listenerKey, info);
             } catch (RemoteException e) {
@@ -2671,7 +2721,8 @@
                     request.calculateRequestDurationMs(mClock.elapsedRealtime()),
                     request.getFoundServiceCount(),
                     request.getLostServiceCount(),
-                    request.isServiceFromCache());
+                    request.isServiceFromCache(),
+                    request.getSentQueryCount());
             try {
                 mCb.onServiceInfoCallbackUnregistered(listenerKey);
             } catch (RemoteException e) {