Report discovery metrics data
Collect information on discovery start, failure, and stop events,
then use this data to build metrics and report them.
Bug: 287546772
Test: atest FrameworksNetTestCases NsdManagerTest
Change-Id: I2f6a718024870f9658cfeabe8995624a3ad81f05
diff --git a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
index 4594f71..71788d2 100644
--- a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
+++ b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
@@ -123,4 +123,54 @@
// TODO: Report repliedRequestsCount
mDependencies.statsWrite(builder.build());
}
+
+ /**
+ * Report service discovery started metric data.
+ *
+ * @param transactionId The transaction id of service discovery.
+ */
+ public void reportServiceDiscoveryStarted(int transactionId) {
+ final Builder builder = makeReportedBuilder();
+ builder.setTransactionId(transactionId);
+ builder.setType(NsdEventType.NET_DISCOVER);
+ builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_DISCOVERY_STARTED);
+ mDependencies.statsWrite(builder.build());
+ }
+
+ /**
+ * Report service discovery failed metric data.
+ *
+ * @param transactionId The transaction id of service discovery.
+ * @param durationMs The duration of service discovery failed.
+ */
+ public void reportServiceDiscoveryFailed(int transactionId, long durationMs) {
+ final Builder builder = makeReportedBuilder();
+ builder.setTransactionId(transactionId);
+ builder.setType(NsdEventType.NET_DISCOVER);
+ builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_DISCOVERY_FAILED);
+ builder.setEventDurationMillisec(durationMs);
+ mDependencies.statsWrite(builder.build());
+ }
+
+ /**
+ * Report service discovery stop metric data.
+ *
+ * @param transactionId The transaction id of service discovery.
+ * @param durationMs The duration of discovering services.
+ * @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.
+ */
+ public void reportServiceDiscoveryStop(int transactionId, long durationMs,
+ int foundCallbackCount, int lostCallbackCount, int servicesCount) {
+ final Builder builder = makeReportedBuilder();
+ builder.setTransactionId(transactionId);
+ builder.setType(NsdEventType.NET_DISCOVER);
+ builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_DISCOVERY_STOP);
+ builder.setEventDurationMillisec(durationMs);
+ builder.setFoundCallbackCount(foundCallbackCount);
+ builder.setLostCallbackCount(lostCallbackCount);
+ builder.setFoundServiceCount(servicesCount);
+ 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 f7edbe4..786a181 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -104,6 +104,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -168,7 +169,9 @@
public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
private static final long CLEANUP_DELAY_MS = 10000;
private static final int IFACE_IDX_ANY = 0;
- private static final int NO_TRANSACTION = -1;
+ private static final int MAX_SERVICES_COUNT_METRIC_PER_CLIENT = 100;
+ @VisibleForTesting
+ static final int NO_TRANSACTION = -1;
private static final SharedLog LOGGER = new SharedLog("serviceDiscovery");
private final Context mContext;
@@ -239,7 +242,8 @@
}
}
- private static class MdnsListener implements MdnsServiceBrowserListener {
+ @VisibleForTesting
+ static class MdnsListener implements MdnsServiceBrowserListener {
protected final int mClientRequestId;
protected final int mTransactionId;
@NonNull
@@ -583,7 +587,7 @@
case NsdManager.DISCOVER_SERVICES:
cInfo = getClientInfoForReply(msg);
if (cInfo != null) {
- cInfo.onDiscoverServicesFailed(
+ cInfo.onDiscoverServicesFailedImmediately(
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
}
break;
@@ -680,7 +684,7 @@
private void storeLegacyRequestMap(int clientRequestId, int transactionId,
ClientInfo clientInfo, int what) {
clientInfo.mClientRequests.put(clientRequestId, new LegacyClientRequest(
- transactionId, what, mClock, mClock.elapsedRealtime()));
+ transactionId, what, mClock.elapsedRealtime()));
mTransactionIdToClientInfoMap.put(transactionId, clientInfo);
// Remove the cleanup event because here comes a new request.
cancelStop();
@@ -689,7 +693,7 @@
private void storeAdvertiserRequestMap(int clientRequestId, int transactionId,
ClientInfo clientInfo, @Nullable Network requestedNetwork) {
clientInfo.mClientRequests.put(clientRequestId, new AdvertiserClientRequest(
- transactionId, requestedNetwork, mClock, mClock.elapsedRealtime()));
+ transactionId, requestedNetwork, mClock.elapsedRealtime()));
mTransactionIdToClientInfoMap.put(transactionId, clientInfo);
updateMulticastLock();
}
@@ -713,8 +717,7 @@
MdnsListener listener, ClientInfo clientInfo,
@Nullable Network requestedNetwork) {
clientInfo.mClientRequests.put(clientRequestId, new DiscoveryManagerRequest(
- transactionId, listener, requestedNetwork, mClock,
- mClock.elapsedRealtime()));
+ transactionId, listener, requestedNetwork, mClock.elapsedRealtime()));
mTransactionIdToClientInfoMap.put(transactionId, clientInfo);
updateMulticastLock();
}
@@ -758,7 +761,7 @@
}
if (requestLimitReached(clientInfo)) {
- clientInfo.onDiscoverServicesFailed(
+ clientInfo.onDiscoverServicesFailedImmediately(
clientRequestId, NsdManager.FAILURE_MAX_LIMIT);
break;
}
@@ -773,8 +776,8 @@
|| mDeps.isMdnsDiscoveryManagerEnabled(mContext)
|| useDiscoveryManagerForType(serviceType)) {
if (serviceType == null) {
- clientInfo.onDiscoverServicesFailed(clientRequestId,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onDiscoverServicesFailedImmediately(
+ clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
break;
}
@@ -796,7 +799,8 @@
listenServiceType, listener, optionsBuilder.build());
storeDiscoveryManagerRequestMap(clientRequestId, transactionId,
listener, clientInfo, info.getNetwork());
- clientInfo.onDiscoverServicesStarted(clientRequestId, info);
+ clientInfo.onDiscoverServicesStarted(
+ clientRequestId, info, transactionId);
clientInfo.log("Register a DiscoveryListener " + transactionId
+ " for service type:" + listenServiceType);
} else {
@@ -808,11 +812,12 @@
}
storeLegacyRequestMap(
clientRequestId, transactionId, clientInfo, msg.what);
- clientInfo.onDiscoverServicesStarted(clientRequestId, info);
+ clientInfo.onDiscoverServicesStarted(
+ clientRequestId, info, transactionId);
} else {
stopServiceDiscovery(transactionId);
- clientInfo.onDiscoverServicesFailed(clientRequestId,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onDiscoverServicesFailedImmediately(
+ clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
}
}
break;
@@ -842,12 +847,12 @@
if (request instanceof DiscoveryManagerRequest) {
stopDiscoveryManagerRequest(
request, clientRequestId, transactionId, clientInfo);
- clientInfo.onStopDiscoverySucceeded(clientRequestId);
+ clientInfo.onStopDiscoverySucceeded(clientRequestId, request);
clientInfo.log("Unregister the DiscoveryListener " + transactionId);
} else {
removeRequestMap(clientRequestId, transactionId, clientInfo);
if (stopServiceDiscovery(transactionId)) {
- clientInfo.onStopDiscoverySucceeded(clientRequestId);
+ clientInfo.onStopDiscoverySucceeded(clientRequestId, request);
} else {
clientInfo.onStopDiscoveryFailed(
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
@@ -942,14 +947,16 @@
// Note isMdnsAdvertiserEnabled may have changed to false at this point,
// so this needs to check the type of the original request to unregister
// instead of looking at the flag value.
+ final long stopTimeMs = mClock.elapsedRealtime();
if (request instanceof AdvertiserClientRequest) {
mAdvertiser.removeService(transactionId);
clientInfo.onUnregisterServiceSucceeded(clientRequestId, transactionId,
- request.calculateRequestDurationMs());
+ request.calculateRequestDurationMs(stopTimeMs));
} else {
if (unregisterService(transactionId)) {
clientInfo.onUnregisterServiceSucceeded(clientRequestId,
- transactionId, request.calculateRequestDurationMs());
+ transactionId,
+ request.calculateRequestDurationMs(stopTimeMs));
} else {
clientInfo.onUnregisterServiceFailed(
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
@@ -1174,6 +1181,11 @@
code, transactionId));
return false;
}
+ final ClientRequest request = clientInfo.mClientRequests.get(clientRequestId);
+ if (request == null) {
+ Log.e(TAG, "Unknown client request. clientRequestId=" + clientRequestId);
+ return false;
+ }
if (DBG) {
Log.d(TAG, String.format(
"MDns service event code:%d transactionId=%d", code, transactionId));
@@ -1198,7 +1210,8 @@
break;
}
setServiceNetworkForCallback(servInfo, info.netId, info.interfaceIdx);
- clientInfo.onServiceFound(clientRequestId, servInfo);
+
+ clientInfo.onServiceFound(clientRequestId, servInfo, request);
break;
}
case IMDnsEventListener.SERVICE_LOST: {
@@ -1212,29 +1225,27 @@
// TODO: avoid returning null in that case, possibly by remembering
// found services on the same interface index and their network at the time
setServiceNetworkForCallback(servInfo, lostNetId, info.interfaceIdx);
- clientInfo.onServiceLost(clientRequestId, servInfo);
+ clientInfo.onServiceLost(clientRequestId, servInfo, request);
break;
}
case IMDnsEventListener.SERVICE_DISCOVERY_FAILED:
- clientInfo.onDiscoverServicesFailed(
- clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onDiscoverServicesFailed(clientRequestId,
+ NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
break;
case IMDnsEventListener.SERVICE_REGISTERED: {
final RegistrationInfo info = (RegistrationInfo) obj;
final String name = info.serviceName;
servInfo = new NsdServiceInfo(name, null /* serviceType */);
- final ClientRequest request =
- clientInfo.mClientRequests.get(clientRequestId);
clientInfo.onRegisterServiceSucceeded(clientRequestId, servInfo,
- transactionId, request.calculateRequestDurationMs());
+ transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
break;
}
case IMDnsEventListener.SERVICE_REGISTRATION_FAILED:
- final ClientRequest request =
- clientInfo.mClientRequests.get(clientRequestId);
clientInfo.onRegisterServiceFailed(clientRequestId,
NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
- request.calculateRequestDurationMs());
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
break;
case IMDnsEventListener.SERVICE_RESOLVED: {
final ResolutionInfo info = (ResolutionInfo) obj;
@@ -1390,20 +1401,19 @@
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);
+ clientInfo.onServiceFound(clientRequestId, info, request);
break;
case NsdManager.SERVICE_LOST:
- clientInfo.onServiceLost(clientRequestId, info);
+ clientInfo.onServiceLost(clientRequestId, info, request);
break;
case NsdManager.RESOLVE_SERVICE_SUCCEEDED: {
- final ClientRequest request =
- clientInfo.mClientRequests.get(clientRequestId);
- if (request == null) {
- Log.e(TAG, "Unknown client request in RESOLVE_SERVICE_SUCCEEDED");
- break;
- }
final MdnsServiceInfo serviceInfo = event.mMdnsServiceInfo;
info.setPort(serviceInfo.getPort());
@@ -1856,8 +1866,8 @@
// historical behavior.
final NsdServiceInfo cbInfo = new NsdServiceInfo(registeredInfo.getServiceName(), null);
final ClientRequest request = clientInfo.mClientRequests.get(clientRequestId);
- clientInfo.onRegisterServiceSucceeded(
- clientRequestId, cbInfo, transactionId, request.calculateRequestDurationMs());
+ clientInfo.onRegisterServiceSucceeded(clientRequestId, cbInfo, transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
}
@Override
@@ -1869,7 +1879,7 @@
if (clientRequestId < 0) return;
final ClientRequest request = clientInfo.mClientRequests.get(clientRequestId);
clientInfo.onRegisterServiceFailed(clientRequestId, errorCode, transactionId,
- request.calculateRequestDurationMs());
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
}
@Override
@@ -2186,27 +2196,49 @@
private abstract static class ClientRequest {
private final int mTransactionId;
- private final Clock mClock;
private final long mStartTimeMs;
+ private int mFoundServiceCount = 0;
+ private int mLostServiceCount = 0;
+ private final Set<String> mServices = new ArraySet<>();
- private ClientRequest(int transactionId, @NonNull Clock clock, long startTimeMs) {
+ private ClientRequest(int transactionId, long startTimeMs) {
mTransactionId = transactionId;
- mClock = clock;
mStartTimeMs = startTimeMs;
}
- public long calculateRequestDurationMs() {
- final long stopTimeMs = mClock.elapsedRealtime();
+ public long calculateRequestDurationMs(long stopTimeMs) {
return stopTimeMs - mStartTimeMs;
}
+
+ public void onServiceFound(String serviceName) {
+ mFoundServiceCount++;
+ if (mServices.size() <= MAX_SERVICES_COUNT_METRIC_PER_CLIENT) {
+ mServices.add(serviceName);
+ }
+ }
+
+ public void onServiceLost() {
+ mLostServiceCount++;
+ }
+
+ public int getFoundServiceCount() {
+ return mFoundServiceCount;
+ }
+
+ public int getLostServiceCount() {
+ return mLostServiceCount;
+ }
+
+ public int getServicesCount() {
+ return mServices.size();
+ }
}
private static class LegacyClientRequest extends ClientRequest {
private final int mRequestCode;
- private LegacyClientRequest(int transactionId, int requestCode, @NonNull Clock clock,
- long startTimeMs) {
- super(transactionId, clock, startTimeMs);
+ private LegacyClientRequest(int transactionId, int requestCode, long startTimeMs) {
+ super(transactionId, startTimeMs);
mRequestCode = requestCode;
}
}
@@ -2216,8 +2248,8 @@
private final Network mRequestedNetwork;
private JavaBackendClientRequest(int transactionId, @Nullable Network requestedNetwork,
- @NonNull Clock clock, long startTimeMs) {
- super(transactionId, clock, startTimeMs);
+ long startTimeMs) {
+ super(transactionId, startTimeMs);
mRequestedNetwork = requestedNetwork;
}
@@ -2229,8 +2261,8 @@
private static class AdvertiserClientRequest extends JavaBackendClientRequest {
private AdvertiserClientRequest(int transactionId, @Nullable Network requestedNetwork,
- @NonNull Clock clock, long startTimeMs) {
- super(transactionId, requestedNetwork, clock, startTimeMs);
+ long startTimeMs) {
+ super(transactionId, requestedNetwork, startTimeMs);
}
}
@@ -2239,8 +2271,8 @@
private final MdnsListener mListener;
private DiscoveryManagerRequest(int transactionId, @NonNull MdnsListener listener,
- @Nullable Network requestedNetwork, @NonNull Clock clock, long startTimeMs) {
- super(transactionId, requestedNetwork, clock, startTimeMs);
+ @Nullable Network requestedNetwork, long startTimeMs) {
+ super(transactionId, requestedNetwork, startTimeMs);
mListener = listener;
}
}
@@ -2303,11 +2335,12 @@
mIsPreSClient = true;
}
- private void unregisterMdnsListenerFromRequest(ClientRequest request) {
+ private MdnsListener unregisterMdnsListenerFromRequest(ClientRequest request) {
final MdnsListener listener =
((DiscoveryManagerRequest) request).mListener;
mMdnsDiscoveryManager.unregisterListener(
listener.getListenedServiceType(), listener);
+ return listener;
}
// Remove any pending requests from the global map when we get rid of a client,
@@ -2327,14 +2360,21 @@
}
if (request instanceof DiscoveryManagerRequest) {
- unregisterMdnsListenerFromRequest(request);
+ final MdnsListener listener = unregisterMdnsListenerFromRequest(request);
+ if (listener instanceof DiscoveryListener) {
+ mMetrics.reportServiceDiscoveryStop(transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()),
+ request.getFoundServiceCount(),
+ request.getLostServiceCount(),
+ request.getServicesCount());
+ }
continue;
}
if (request instanceof AdvertiserClientRequest) {
mAdvertiser.removeService(transactionId);
- mMetrics.reportServiceUnregistration(
- transactionId, request.calculateRequestDurationMs());
+ mMetrics.reportServiceUnregistration(transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
continue;
}
@@ -2345,14 +2385,19 @@
switch (((LegacyClientRequest) request).mRequestCode) {
case NsdManager.DISCOVER_SERVICES:
stopServiceDiscovery(transactionId);
+ mMetrics.reportServiceDiscoveryStop(transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()),
+ request.getFoundServiceCount(),
+ request.getLostServiceCount(),
+ request.getServicesCount());
break;
case NsdManager.RESOLVE_SERVICE:
stopResolveService(transactionId);
break;
case NsdManager.REGISTER_SERVICE:
unregisterService(transactionId);
- mMetrics.reportServiceUnregistration(
- transactionId, request.calculateRequestDurationMs());
+ mMetrics.reportServiceUnregistration(transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
break;
default:
break;
@@ -2396,15 +2441,21 @@
mClientLogs.log(message);
}
- void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
+ void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info, int transactionId) {
+ mMetrics.reportServiceDiscoveryStarted(transactionId);
try {
mCb.onDiscoverServicesStarted(listenerKey, info);
} catch (RemoteException e) {
Log.e(TAG, "Error calling onDiscoverServicesStarted", e);
}
}
+ void onDiscoverServicesFailedImmediately(int listenerKey, int error) {
+ onDiscoverServicesFailed(listenerKey, error, NO_TRANSACTION, 0L /* durationMs */);
+ }
- void onDiscoverServicesFailed(int listenerKey, int error) {
+ void onDiscoverServicesFailed(int listenerKey, int error, int transactionId,
+ long durationMs) {
+ mMetrics.reportServiceDiscoveryFailed(transactionId, durationMs);
try {
mCb.onDiscoverServicesFailed(listenerKey, error);
} catch (RemoteException e) {
@@ -2412,7 +2463,8 @@
}
}
- void onServiceFound(int listenerKey, NsdServiceInfo info) {
+ void onServiceFound(int listenerKey, NsdServiceInfo info, ClientRequest request) {
+ request.onServiceFound(info.getServiceName());
try {
mCb.onServiceFound(listenerKey, info);
} catch (RemoteException e) {
@@ -2420,7 +2472,8 @@
}
}
- void onServiceLost(int listenerKey, NsdServiceInfo info) {
+ void onServiceLost(int listenerKey, NsdServiceInfo info, ClientRequest request) {
+ request.onServiceLost();
try {
mCb.onServiceLost(listenerKey, info);
} catch (RemoteException e) {
@@ -2436,7 +2489,13 @@
}
}
- void onStopDiscoverySucceeded(int listenerKey) {
+ void onStopDiscoverySucceeded(int listenerKey, ClientRequest request) {
+ mMetrics.reportServiceDiscoveryStop(
+ request.mTransactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()),
+ request.getFoundServiceCount(),
+ request.getLostServiceCount(),
+ request.getServicesCount());
try {
mCb.onStopDiscoverySucceeded(listenerKey);
} catch (RemoteException e) {
@@ -2445,7 +2504,7 @@
}
void onRegisterServiceFailedImmediately(int listenerKey, int error) {
- onRegisterServiceFailed(listenerKey, error, NO_TRANSACTION, 0 /* durationMs */);
+ onRegisterServiceFailed(listenerKey, error, NO_TRANSACTION, 0L /* durationMs */);
}
void onRegisterServiceFailed(int listenerKey, int error, int transactionId,
diff --git a/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt b/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt
index 961c422..fdc12c9 100644
--- a/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt
+++ b/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt
@@ -94,4 +94,70 @@
assertEquals(durationMs, it.eventDurationMillisec)
}
}
+
+ @Test
+ fun testReportServiceDiscoveryStarted() {
+ val clientId = 99
+ val transactionId = 100
+ val metrics = NetworkNsdReportedMetrics(true /* isLegacy */, clientId, deps)
+ metrics.reportServiceDiscoveryStarted(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_DISCOVER, it.type)
+ assertEquals(MdnsQueryResult.MQR_SERVICE_DISCOVERY_STARTED, it.queryResult)
+ }
+ }
+
+ @Test
+ fun testReportServiceDiscoveryFailed() {
+ val clientId = 99
+ val transactionId = 100
+ val durationMs = 10L
+ val metrics = NetworkNsdReportedMetrics(false /* isLegacy */, clientId, deps)
+ metrics.reportServiceDiscoveryFailed(transactionId, durationMs)
+
+ 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_DISCOVER, it.type)
+ assertEquals(MdnsQueryResult.MQR_SERVICE_DISCOVERY_FAILED, it.queryResult)
+ assertEquals(durationMs, it.eventDurationMillisec)
+ }
+ }
+
+ @Test
+ fun testReportServiceDiscoveryStop() {
+ val clientId = 99
+ val transactionId = 100
+ val durationMs = 10L
+ val foundCallbackCount = 100
+ val lostCallbackCount = 49
+ val servicesCount = 75
+ val metrics = NetworkNsdReportedMetrics(true /* isLegacy */, clientId, deps)
+ metrics.reportServiceDiscoveryStop(
+ transactionId, durationMs, foundCallbackCount, lostCallbackCount, servicesCount)
+
+ 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_DISCOVER, it.type)
+ assertEquals(MdnsQueryResult.MQR_SERVICE_DISCOVERY_STOP, it.queryResult)
+ assertEquals(durationMs, it.eventDurationMillisec)
+ assertEquals(foundCallbackCount, it.foundCallbackCount)
+ assertEquals(lostCallbackCount, it.lostCallbackCount)
+ assertEquals(servicesCount, it.foundServiceCount)
+ assertEquals(durationMs, it.eventDurationMillisec)
+ }
+ }
}
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index f778075..8ed065f 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -31,6 +31,8 @@
import static android.net.nsd.NsdManager.FAILURE_OPERATION_NOT_RUNNING;
import static com.android.server.NsdService.DEFAULT_RUNNING_APP_ACTIVE_IMPORTANCE_CUTOFF;
+import static com.android.server.NsdService.MdnsListener;
+import static com.android.server.NsdService.NO_TRANSACTION;
import static com.android.server.NsdService.parseTypeAndSubtype;
import static com.android.testutils.ContextUtils.mockService;
@@ -45,7 +47,6 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.any;
@@ -401,9 +402,11 @@
// NsdManager uses a separate HandlerThread to dispatch callbacks (on ServiceHandler), so
// this needs to use a timeout
verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStarted(SERVICE_TYPE);
+ final int discId = discIdCaptor.getValue();
+ verify(mMetrics).reportServiceDiscoveryStarted(discId);
final DiscoveryInfo discoveryInfo = new DiscoveryInfo(
- discIdCaptor.getValue(),
+ discId,
IMDnsEventListener.SERVICE_FOUND,
SERVICE_NAME,
SERVICE_TYPE,
@@ -491,9 +494,11 @@
// NsdManager uses a separate HandlerThread to dispatch callbacks (on ServiceHandler), so
// this needs to use a timeout
verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStarted(SERVICE_TYPE);
+ final int discId = discIdCaptor.getValue();
+ verify(mMetrics).reportServiceDiscoveryStarted(discId);
final DiscoveryInfo discoveryInfo = new DiscoveryInfo(
- discIdCaptor.getValue(),
+ discId,
IMDnsEventListener.SERVICE_FOUND,
SERVICE_NAME,
SERVICE_TYPE,
@@ -570,19 +575,23 @@
final ArgumentCaptor<Integer> discIdCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMockMDnsM).discover(discIdCaptor.capture(), eq(SERVICE_TYPE), eq(IFACE_IDX_ANY));
verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStarted(SERVICE_TYPE);
+ final int discId = discIdCaptor.getValue();
+ verify(mMetrics).reportServiceDiscoveryStarted(discId);
// Fail to discover service.
final DiscoveryInfo discoveryFailedInfo = new DiscoveryInfo(
- discIdCaptor.getValue(),
+ discId,
IMDnsEventListener.SERVICE_DISCOVERY_FAILED,
null /* serviceName */,
null /* registrationType */,
null /* domainName */,
IFACE_IDX_ANY,
0 /* netId */);
+ doReturn(TEST_TIME_MS + 10L).when(mClock).elapsedRealtime();
eventListener.onServiceDiscoveryStatus(discoveryFailedInfo);
verify(discListener, timeout(TIMEOUT_MS))
.onStartDiscoveryFailed(SERVICE_TYPE, FAILURE_INTERNAL_ERROR);
+ verify(mMetrics).reportServiceDiscoveryFailed(discId, 10L /* durationMs */);
}
@Test
@@ -936,8 +945,8 @@
final Network network = new Network(999);
final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
// Verify the discovery start / stop.
- final ArgumentCaptor<MdnsServiceBrowserListener> listenerCaptor =
- ArgumentCaptor.forClass(MdnsServiceBrowserListener.class);
+ final ArgumentCaptor<MdnsListener> listenerCaptor =
+ ArgumentCaptor.forClass(MdnsListener.class);
client.discoverServices(SERVICE_TYPE, PROTOCOL, network, r -> r.run(), discListener);
waitForIdle();
verify(mSocketProvider).startMonitoringSockets();
@@ -945,7 +954,10 @@
listenerCaptor.capture(), argThat(options -> network.equals(options.getNetwork())));
verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStarted(SERVICE_TYPE);
- final MdnsServiceBrowserListener listener = listenerCaptor.getValue();
+ final MdnsListener listener = listenerCaptor.getValue();
+ final int discId = listener.mTransactionId;
+ verify(mMetrics).reportServiceDiscoveryStarted(discId);
+
final MdnsServiceInfo foundInfo = new MdnsServiceInfo(
SERVICE_NAME, /* serviceInstanceName */
serviceTypeWithLocalDomain.split("\\."), /* serviceType */
@@ -987,11 +999,14 @@
&& info.getServiceType().equals(SERVICE_TYPE + ".")
&& info.getNetwork().equals(network)));
+ doReturn(TEST_TIME_MS + 10L).when(mClock).elapsedRealtime();
client.stopServiceDiscovery(discListener);
waitForIdle();
verify(mDiscoveryManager).unregisterListener(eq(serviceTypeWithLocalDomain), any());
verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStopped(SERVICE_TYPE);
verify(mSocketProvider, timeout(CLEANUP_DELAY_MS + TIMEOUT_MS)).requestStopWhenInactive();
+ verify(mMetrics).reportServiceDiscoveryStop(discId, 10L /* durationMs */,
+ 1 /* foundCallbackCount */, 1 /* lostCallbackCount */, 1 /* servicesCount */);
}
@Test
@@ -1007,6 +1022,8 @@
waitForIdle();
verify(discListener, timeout(TIMEOUT_MS))
.onStartDiscoveryFailed(invalidServiceType, FAILURE_INTERNAL_ERROR);
+ verify(mMetrics, times(1))
+ .reportServiceDiscoveryFailed(NO_TRANSACTION, 0L /* durationMs */);
final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
client.discoverServices(
@@ -1014,6 +1031,8 @@
waitForIdle();
verify(discListener, timeout(TIMEOUT_MS))
.onStartDiscoveryFailed(serviceTypeWithLocalDomain, FAILURE_INTERNAL_ERROR);
+ verify(mMetrics, times(2))
+ .reportServiceDiscoveryFailed(NO_TRANSACTION, 0L /* durationMs */);
final String serviceTypeWithoutTcpOrUdpEnding = "_test._com";
client.discoverServices(
@@ -1021,6 +1040,8 @@
waitForIdle();
verify(discListener, timeout(TIMEOUT_MS))
.onStartDiscoveryFailed(serviceTypeWithoutTcpOrUdpEnding, FAILURE_INTERNAL_ERROR);
+ verify(mMetrics, times(3))
+ .reportServiceDiscoveryFailed(NO_TRANSACTION, 0L /* durationMs */);
}
@Test
@@ -1271,7 +1292,7 @@
verify(regListener, timeout(TIMEOUT_MS)).onRegistrationFailed(
argThat(info -> matches(info, regInfo)), eq(FAILURE_INTERNAL_ERROR));
- verify(mMetrics).reportServiceRegistrationFailed(anyInt(), anyLong());
+ verify(mMetrics).reportServiceRegistrationFailed(NO_TRANSACTION, 0L /* durationMs */);
}
@Test