diff --git a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java index 4594f71cf0..71788d2d06 100644 --- a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java +++ b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java @@ -123,4 +123,54 @@ public class NetworkNsdReportedMetrics { // 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 f7edbe4ecf..786a1810bc 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.HashMap; 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 class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } } - 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 @@ public class NsdService extends INsdManager.Stub { case NsdManager.DISCOVER_SERVICES: cInfo = getClientInfoForReply(msg); if (cInfo != null) { - cInfo.onDiscoverServicesFailed( + cInfo.onDiscoverServicesFailedImmediately( clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR); } break; @@ -680,7 +684,7 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } if (requestLimitReached(clientInfo)) { - clientInfo.onDiscoverServicesFailed( + clientInfo.onDiscoverServicesFailedImmediately( clientRequestId, NsdManager.FAILURE_MAX_LIMIT); break; } @@ -773,8 +776,8 @@ public class NsdService extends INsdManager.Stub { || 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { // 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { // 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { // 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } } - 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 @@ public class NsdService extends INsdManager.Stub { } } - 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 @@ public class NsdService extends INsdManager.Stub { } } - 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 @@ public class NsdService extends INsdManager.Stub { } 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 961c4222b4..fdc12c908d 100644 --- a/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt +++ b/tests/unit/java/com/android/metrics/NetworkNsdReportedMetricsTest.kt @@ -94,4 +94,70 @@ class NetworkNsdReportedMetricsTest { 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 f77807528b..8ed065fc84 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_INTERNAL_ERROR; 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.assertThrows; 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 @@ public class NsdServiceTest { // 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 @@ public class NsdServiceTest { // 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 @@ public class NsdServiceTest { final ArgumentCaptor 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 @@ public class NsdServiceTest { final Network network = new Network(999); final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local"; // Verify the discovery start / stop. - final ArgumentCaptor listenerCaptor = - ArgumentCaptor.forClass(MdnsServiceBrowserListener.class); + final ArgumentCaptor listenerCaptor = + ArgumentCaptor.forClass(MdnsListener.class); client.discoverServices(SERVICE_TYPE, PROTOCOL, network, r -> r.run(), discListener); waitForIdle(); verify(mSocketProvider).startMonitoringSockets(); @@ -945,7 +954,10 @@ public class NsdServiceTest { 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 @@ public class NsdServiceTest { && 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 @@ public class NsdServiceTest { 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 @@ public class NsdServiceTest { 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 @@ public class NsdServiceTest { 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 @@ public class NsdServiceTest { 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