Report service info callback metrics data
Bug: 287546772
Test: atest FrameworksNetTestCases
Change-Id: I630c0e4921f7acf42bf29812d9790ee5a894d60b
diff --git a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
index 052019f..665c41c 100644
--- a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
+++ b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
@@ -221,4 +221,52 @@
builder.setEventDurationMillisec(durationMs);
mDependencies.statsWrite(builder.build());
}
+
+ /**
+ * Report service info callback registered metric data.
+ *
+ * @param transactionId The transaction id of service info callback registration.
+ */
+ public void reportServiceInfoCallbackRegistered(int transactionId) {
+ final Builder builder = makeReportedBuilder();
+ builder.setTransactionId(transactionId);
+ builder.setType(NsdEventType.NET_SERVICE_INFO_CALLBACK);
+ builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_INFO_CALLBACK_REGISTERED);
+ mDependencies.statsWrite(builder.build());
+ }
+
+ /**
+ * Report service info callback registration failed metric data.
+ *
+ * @param transactionId The transaction id of service callback registration.
+ */
+ public void reportServiceInfoCallbackRegistrationFailed(int transactionId) {
+ final Builder builder = makeReportedBuilder();
+ builder.setTransactionId(transactionId);
+ builder.setType(NsdEventType.NET_SERVICE_INFO_CALLBACK);
+ builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_INFO_CALLBACK_REGISTRATION_FAILED);
+ mDependencies.statsWrite(builder.build());
+ }
+
+ /**
+ * Report service callback unregistered metric data.
+ *
+ * @param transactionId The transaction id of service callback registration.
+ * @param durationMs The duration of service callback stayed registered.
+ * @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.
+ */
+ public void reportServiceInfoCallbackUnregistered(int transactionId, long durationMs,
+ int updateCallbackCount, int lostCallbackCount, boolean isServiceFromCache) {
+ final Builder builder = makeReportedBuilder();
+ builder.setTransactionId(transactionId);
+ builder.setType(NsdEventType.NET_SERVICE_INFO_CALLBACK);
+ builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_INFO_CALLBACK_UNREGISTERED);
+ builder.setEventDurationMillisec(durationMs);
+ builder.setFoundCallbackCount(updateCallbackCount);
+ builder.setLostCallbackCount(lostCallbackCount);
+ builder.setIsKnownService(isServiceFromCache);
+ 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 0a7ac9b..e189d69 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -1114,6 +1114,7 @@
resolveServiceType, listener, options);
storeDiscoveryManagerRequestMap(clientRequestId, transactionId, listener,
clientInfo, info.getNetwork());
+ clientInfo.onServiceInfoCallbackRegistered(transactionId);
clientInfo.log("Register a ServiceInfoListener " + transactionId
+ " for service type:" + resolveServiceType);
break;
@@ -1140,7 +1141,7 @@
if (request instanceof DiscoveryManagerRequest) {
stopDiscoveryManagerRequest(
request, clientRequestId, transactionId, clientInfo);
- clientInfo.onServiceInfoCallbackUnregistered(clientRequestId);
+ clientInfo.onServiceInfoCallbackUnregistered(clientRequestId, request);
clientInfo.log("Unregister the ServiceInfoListener " + transactionId);
} else {
loge("Unregister failed with non-DiscoveryManagerRequest.");
@@ -1478,11 +1479,17 @@
final List<InetAddress> addresses = getInetAddresses(serviceInfo);
info.setHostAddresses(addresses);
- clientInfo.onServiceUpdated(clientRequestId, info);
+ clientInfo.onServiceUpdated(clientRequestId, info, request);
+ // Set the ServiceFromCache flag only if the service is actually being
+ // retrieved from the cache. This flag should not be overridden by later
+ // service updates, which may not be cached.
+ if (event.mIsServiceFromCache) {
+ request.setServiceFromCache(true);
+ }
break;
}
case NsdManager.SERVICE_UPDATED_LOST:
- clientInfo.onServiceUpdatedLost(clientRequestId);
+ clientInfo.onServiceUpdatedLost(clientRequestId, request);
break;
default:
return false;
@@ -2396,6 +2403,12 @@
} else if (listener instanceof ResolutionListener) {
mMetrics.reportServiceResolutionStop(transactionId,
request.calculateRequestDurationMs(mClock.elapsedRealtime()));
+ } else if (listener instanceof ServiceInfoListener) {
+ mMetrics.reportServiceInfoCallbackUnregistered(transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()),
+ request.getFoundServiceCount(),
+ request.getLostServiceCount(),
+ request.isServiceFromCache());
}
continue;
}
@@ -2622,6 +2635,7 @@
}
void onServiceInfoCallbackRegistrationFailed(int listenerKey, int error) {
+ mMetrics.reportServiceInfoCallbackRegistrationFailed(NO_TRANSACTION);
try {
mCb.onServiceInfoCallbackRegistrationFailed(listenerKey, error);
} catch (RemoteException e) {
@@ -2629,7 +2643,12 @@
}
}
- void onServiceUpdated(int listenerKey, NsdServiceInfo info) {
+ void onServiceInfoCallbackRegistered(int transactionId) {
+ mMetrics.reportServiceInfoCallbackRegistered(transactionId);
+ }
+
+ void onServiceUpdated(int listenerKey, NsdServiceInfo info, ClientRequest request) {
+ request.onServiceFound(info.getServiceName());
try {
mCb.onServiceUpdated(listenerKey, info);
} catch (RemoteException e) {
@@ -2637,7 +2656,8 @@
}
}
- void onServiceUpdatedLost(int listenerKey) {
+ void onServiceUpdatedLost(int listenerKey, ClientRequest request) {
+ request.onServiceLost();
try {
mCb.onServiceUpdatedLost(listenerKey);
} catch (RemoteException e) {
@@ -2645,7 +2665,13 @@
}
}
- void onServiceInfoCallbackUnregistered(int listenerKey) {
+ void onServiceInfoCallbackUnregistered(int listenerKey, ClientRequest request) {
+ mMetrics.reportServiceInfoCallbackUnregistered(
+ request.mTransactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()),
+ request.getFoundServiceCount(),
+ request.getLostServiceCount(),
+ request.isServiceFromCache());
try {
mCb.onServiceInfoCallbackUnregistered(listenerKey);
} catch (RemoteException e) {
diff --git a/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt b/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt
index 97aa575..740aa88 100644
--- a/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt
+++ b/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt
@@ -221,4 +221,67 @@
assertEquals(durationMs, it.eventDurationMillisec)
}
}
+
+ @Test
+ fun testReportServiceInfoCallbackRegistered() {
+ val clientId = 99
+ val transactionId = 100
+ val metrics = NetworkNsdReportedMetrics(false /* isLegacy */, clientId, deps)
+ metrics.reportServiceInfoCallbackRegistered(transactionId)
+
+ val eventCaptor = ArgumentCaptor.forClass(NetworkNsdReported::class.java)
+ verify(deps).statsWrite(eventCaptor.capture())
+ eventCaptor.value.let {
+ assertFalse(it.isLegacy)
+ assertEquals(clientId, it.clientId)
+ assertEquals(transactionId, it.transactionId)
+ assertEquals(NsdEventType.NET_SERVICE_INFO_CALLBACK, it.type)
+ assertEquals(MdnsQueryResult.MQR_SERVICE_INFO_CALLBACK_REGISTERED, it.queryResult)
+ }
+ }
+
+ @Test
+ fun testReportServiceInfoCallbackRegistrationFailed() {
+ val clientId = 99
+ val transactionId = 100
+ val metrics = NetworkNsdReportedMetrics(true /* isLegacy */, clientId, deps)
+ metrics.reportServiceInfoCallbackRegistrationFailed(transactionId)
+
+ val eventCaptor = ArgumentCaptor.forClass(NetworkNsdReported::class.java)
+ verify(deps).statsWrite(eventCaptor.capture())
+ eventCaptor.value.let {
+ assertTrue(it.isLegacy)
+ assertEquals(clientId, it.clientId)
+ assertEquals(transactionId, it.transactionId)
+ assertEquals(NsdEventType.NET_SERVICE_INFO_CALLBACK, it.type)
+ assertEquals(
+ MdnsQueryResult.MQR_SERVICE_INFO_CALLBACK_REGISTRATION_FAILED, it.queryResult)
+ }
+ }
+
+ @Test
+ fun testReportServiceInfoCallbackUnregistered() {
+ val clientId = 99
+ val transactionId = 100
+ val durationMs = 10L
+ val updateCallbackCount = 100
+ val lostCallbackCount = 10
+ val metrics = NetworkNsdReportedMetrics(false /* isLegacy */, clientId, deps)
+ metrics.reportServiceInfoCallbackUnregistered(transactionId, durationMs,
+ updateCallbackCount, lostCallbackCount, false /* isServiceFromCache */)
+
+ val eventCaptor = ArgumentCaptor.forClass(NetworkNsdReported::class.java)
+ verify(deps).statsWrite(eventCaptor.capture())
+ eventCaptor.value.let {
+ assertFalse(it.isLegacy)
+ assertEquals(clientId, it.clientId)
+ assertEquals(transactionId, it.transactionId)
+ assertEquals(NsdEventType.NET_SERVICE_INFO_CALLBACK, it.type)
+ assertEquals(MdnsQueryResult.MQR_SERVICE_INFO_CALLBACK_UNREGISTERED, it.queryResult)
+ assertEquals(durationMs, it.eventDurationMillisec)
+ assertEquals(updateCallbackCount, it.foundCallbackCount)
+ assertEquals(lostCallbackCount, it.lostCallbackCount)
+ assertFalse(it.isKnownService)
+ }
+ }
}
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index c715c8e..ffc7904 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -822,13 +822,17 @@
client.registerServiceInfoCallback(request, Runnable::run, serviceInfoCallback);
waitForIdle();
// Verify the registration callback start.
- final ArgumentCaptor<MdnsServiceBrowserListener> listenerCaptor =
- ArgumentCaptor.forClass(MdnsServiceBrowserListener.class);
+ final ArgumentCaptor<MdnsListener> listenerCaptor =
+ ArgumentCaptor.forClass(MdnsListener.class);
verify(mSocketProvider).startMonitoringSockets();
verify(mDiscoveryManager).registerListener(eq(serviceTypeWithLocalDomain),
listenerCaptor.capture(), argThat(options -> network.equals(options.getNetwork())));
- final MdnsServiceBrowserListener listener = listenerCaptor.getValue();
+ final MdnsListener listener = listenerCaptor.getValue();
+ final int servInfoId = listener.mTransactionId;
+ // Verify the service info callback registered.
+ verify(mMetrics).reportServiceInfoCallbackRegistered(servInfoId);
+
final MdnsServiceInfo mdnsServiceInfo = new MdnsServiceInfo(
SERVICE_NAME,
serviceTypeWithLocalDomain.split("\\."),
@@ -842,8 +846,11 @@
1234,
network);
+ // Callbacks for query sent.
+ listener.onDiscoveryQuerySent(Collections.emptyList(), 1 /* transactionId */);
+
// Verify onServiceFound callback
- listener.onServiceFound(mdnsServiceInfo, false /* isServiceFromCache */);
+ listener.onServiceFound(mdnsServiceInfo, true /* isServiceFromCache */);
final ArgumentCaptor<NsdServiceInfo> updateInfoCaptor =
ArgumentCaptor.forClass(NsdServiceInfo.class);
verify(serviceInfoCallback, timeout(TIMEOUT_MS).times(1))
@@ -878,10 +885,18 @@
List.of(parseNumericAddress(v4Address), parseNumericAddress(v6Address)),
PORT, IFACE_IDX_ANY, new Network(999));
+ // Service lost then recovered.
+ listener.onServiceRemoved(updatedServiceInfo);
+ listener.onServiceFound(updatedServiceInfo, false /* isServiceFromCache */);
+
// Verify service callback unregistration.
+ doReturn(TEST_TIME_MS + 10L).when(mClock).elapsedRealtime();
client.unregisterServiceInfoCallback(serviceInfoCallback);
waitForIdle();
verify(serviceInfoCallback, timeout(TIMEOUT_MS)).onServiceInfoCallbackUnregistered();
+ verify(mMetrics).reportServiceInfoCallbackUnregistered(servInfoId, 10L /* durationMs */,
+ 3 /* updateCallbackCount */, 1 /* lostCallbackCount */,
+ true /* isServiceFromCache */);
}
@Test
@@ -897,6 +912,7 @@
// Fail to register service callback.
verify(serviceInfoCallback, timeout(TIMEOUT_MS))
.onServiceInfoCallbackRegistrationFailed(eq(FAILURE_BAD_PARAMETERS));
+ verify(mMetrics).reportServiceInfoCallbackRegistrationFailed(NO_TRANSACTION);
}
@Test