Report resolution metrics data
Collect information on resolution success and failure events,
then use this data to build metrics and report them.
Bug: 287546772
Test: atest FrameworksNetTestCases NsdManagerTest
Change-Id: I373ce91fea9d5a278f53fc0c505be90dd39b2d5b
diff --git a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
index 71788d2..c3b5086 100644
--- a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
+++ b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
@@ -173,4 +173,37 @@
builder.setFoundServiceCount(servicesCount);
mDependencies.statsWrite(builder.build());
}
+
+ /**
+ * Report service resolution success metric data.
+ *
+ * @param transactionId The transaction id of service resolution.
+ * @param durationMs The duration of resolving services.
+ * @param isServiceFromCache Whether the resolved service is from cache.
+ */
+ public void reportServiceResolved(int transactionId, long durationMs,
+ boolean isServiceFromCache) {
+ final Builder builder = makeReportedBuilder();
+ builder.setTransactionId(transactionId);
+ builder.setType(NsdEventType.NET_RESOLVE);
+ builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_RESOLVED);
+ builder.setEventDurationMillisec(durationMs);
+ builder.setIsKnownService(isServiceFromCache);
+ mDependencies.statsWrite(builder.build());
+ }
+
+ /**
+ * Report service resolution failed metric data.
+ *
+ * @param transactionId The transaction id of service resolution.
+ * @param durationMs The duration of service resolution failed.
+ */
+ public void reportServiceResolutionFailed(int transactionId, long durationMs) {
+ final Builder builder = makeReportedBuilder();
+ builder.setTransactionId(transactionId);
+ builder.setType(NsdEventType.NET_RESOLVE);
+ builder.setQueryResult(MdnsQueryResult.MQR_SERVICE_RESOLUTION_FAILED);
+ builder.setEventDurationMillisec(durationMs);
+ 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 786a181..b975a1b 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -265,7 +265,8 @@
}
@Override
- public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo) { }
+ public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo,
+ boolean isServiceFromCache) { }
@Override
public void onServiceUpdated(@NonNull MdnsServiceInfo serviceInfo) { }
@@ -274,7 +275,8 @@
public void onServiceRemoved(@NonNull MdnsServiceInfo serviceInfo) { }
@Override
- public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo) { }
+ public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo,
+ boolean isServiceFromCache) { }
@Override
public void onServiceNameRemoved(@NonNull MdnsServiceInfo serviceInfo) { }
@@ -300,10 +302,11 @@
}
@Override
- public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo) {
+ public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo,
+ boolean isServiceFromCache) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.SERVICE_FOUND,
- new MdnsEvent(mClientRequestId, serviceInfo));
+ new MdnsEvent(mClientRequestId, serviceInfo, isServiceFromCache));
}
@Override
@@ -322,10 +325,10 @@
}
@Override
- public void onServiceFound(MdnsServiceInfo serviceInfo) {
+ public void onServiceFound(MdnsServiceInfo serviceInfo, boolean isServiceFromCache) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.RESOLVE_SERVICE_SUCCEEDED,
- new MdnsEvent(mClientRequestId, serviceInfo));
+ new MdnsEvent(mClientRequestId, serviceInfo, isServiceFromCache));
}
}
@@ -337,10 +340,11 @@
}
@Override
- public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo) {
+ public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo,
+ boolean isServiceFromCache) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.SERVICE_UPDATED,
- new MdnsEvent(mClientRequestId, serviceInfo));
+ new MdnsEvent(mClientRequestId, serviceInfo, isServiceFromCache));
}
@Override
@@ -463,10 +467,17 @@
final int mClientRequestId;
@NonNull
final MdnsServiceInfo mMdnsServiceInfo;
+ final boolean mIsServiceFromCache;
MdnsEvent(int clientRequestId, @NonNull MdnsServiceInfo mdnsServiceInfo) {
+ this(clientRequestId, mdnsServiceInfo, false /* isServiceFromCache */);
+ }
+
+ MdnsEvent(int clientRequestId, @NonNull MdnsServiceInfo mdnsServiceInfo,
+ boolean isServiceFromCache) {
mClientRequestId = clientRequestId;
mMdnsServiceInfo = mdnsServiceInfo;
+ mIsServiceFromCache = isServiceFromCache;
}
}
@@ -615,7 +626,7 @@
case NsdManager.RESOLVE_SERVICE:
cInfo = getClientInfoForReply(msg);
if (cInfo != null) {
- cInfo.onResolveServiceFailed(
+ cInfo.onResolveServiceFailedImmediately(
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
}
break;
@@ -682,9 +693,9 @@
}
private void storeLegacyRequestMap(int clientRequestId, int transactionId,
- ClientInfo clientInfo, int what) {
- clientInfo.mClientRequests.put(clientRequestId, new LegacyClientRequest(
- transactionId, what, mClock.elapsedRealtime()));
+ ClientInfo clientInfo, int what, long startTimeMs) {
+ clientInfo.mClientRequests.put(clientRequestId,
+ new LegacyClientRequest(transactionId, what, startTimeMs));
mTransactionIdToClientInfoMap.put(transactionId, clientInfo);
// Remove the cleanup event because here comes a new request.
cancelStop();
@@ -810,8 +821,8 @@
Log.d(TAG, "Discover " + msg.arg2 + " " + transactionId
+ info.getServiceType());
}
- storeLegacyRequestMap(
- clientRequestId, transactionId, clientInfo, msg.what);
+ storeLegacyRequestMap(clientRequestId, transactionId, clientInfo,
+ msg.what, mClock.elapsedRealtime());
clientInfo.onDiscoverServicesStarted(
clientRequestId, info, transactionId);
} else {
@@ -912,8 +923,8 @@
Log.d(TAG, "Register " + clientRequestId
+ " " + transactionId);
}
- storeLegacyRequestMap(
- clientRequestId, transactionId, clientInfo, msg.what);
+ storeLegacyRequestMap(clientRequestId, transactionId, clientInfo,
+ msg.what, mClock.elapsedRealtime());
// Return success after mDns reports success
} else {
unregisterService(transactionId);
@@ -986,8 +997,8 @@
|| mDeps.isMdnsDiscoveryManagerEnabled(mContext)
|| useDiscoveryManagerForType(serviceType)) {
if (serviceType == null) {
- clientInfo.onResolveServiceFailed(clientRequestId,
- NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onResolveServiceFailedImmediately(
+ clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
break;
}
final String resolveServiceType = serviceType + ".local";
@@ -1009,7 +1020,7 @@
+ " for service type:" + resolveServiceType);
} else {
if (clientInfo.mResolvedService != null) {
- clientInfo.onResolveServiceFailed(
+ clientInfo.onResolveServiceFailedImmediately(
clientRequestId, NsdManager.FAILURE_ALREADY_ACTIVE);
break;
}
@@ -1017,10 +1028,10 @@
maybeStartDaemon();
if (resolveService(transactionId, info)) {
clientInfo.mResolvedService = new NsdServiceInfo();
- storeLegacyRequestMap(
- clientRequestId, transactionId, clientInfo, msg.what);
+ storeLegacyRequestMap(clientRequestId, transactionId, clientInfo,
+ msg.what, mClock.elapsedRealtime());
} else {
- clientInfo.onResolveServiceFailed(
+ clientInfo.onResolveServiceFailedImmediately(
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
}
}
@@ -1279,10 +1290,11 @@
final int transactionId2 = getUniqueId();
if (getAddrInfo(transactionId2, info.hostname, info.interfaceIdx)) {
storeLegacyRequestMap(clientRequestId, transactionId2, clientInfo,
- NsdManager.RESOLVE_SERVICE);
+ NsdManager.RESOLVE_SERVICE, request.mStartTimeMs);
} else {
- clientInfo.onResolveServiceFailed(
- clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onResolveServiceFailed(clientRequestId,
+ NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
clientInfo.mResolvedService = null;
}
break;
@@ -1291,16 +1303,18 @@
/* NNN resolveId errorCode */
stopResolveService(transactionId);
removeRequestMap(clientRequestId, transactionId, clientInfo);
- clientInfo.onResolveServiceFailed(
- clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onResolveServiceFailed(clientRequestId,
+ NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
clientInfo.mResolvedService = null;
break;
case IMDnsEventListener.SERVICE_GET_ADDR_FAILED:
/* NNN resolveId errorCode */
stopGetAddrInfo(transactionId);
removeRequestMap(clientRequestId, transactionId, clientInfo);
- clientInfo.onResolveServiceFailed(
- clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onResolveServiceFailed(clientRequestId,
+ NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
clientInfo.mResolvedService = null;
break;
case IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS: {
@@ -1323,10 +1337,11 @@
setServiceNetworkForCallback(clientInfo.mResolvedService,
netId, info.interfaceIdx);
clientInfo.onResolveServiceSucceeded(
- clientRequestId, clientInfo.mResolvedService);
+ clientRequestId, clientInfo.mResolvedService, request);
} else {
- clientInfo.onResolveServiceFailed(
- clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onResolveServiceFailed(clientRequestId,
+ NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
}
stopGetAddrInfo(transactionId);
removeRequestMap(clientRequestId, transactionId, clientInfo);
@@ -1429,11 +1444,13 @@
final List<InetAddress> addresses = getInetAddresses(serviceInfo);
if (addresses.size() != 0) {
info.setHostAddresses(addresses);
- clientInfo.onResolveServiceSucceeded(clientRequestId, info);
+ request.setServiceFromCache(event.mIsServiceFromCache);
+ clientInfo.onResolveServiceSucceeded(clientRequestId, info, request);
} else {
// No address. Notify resolution failure.
- clientInfo.onResolveServiceFailed(
- clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.onResolveServiceFailed(clientRequestId,
+ NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()));
}
// Unregister the listener immediately like IMDnsEventListener design
@@ -2200,6 +2217,7 @@
private int mFoundServiceCount = 0;
private int mLostServiceCount = 0;
private final Set<String> mServices = new ArraySet<>();
+ private boolean mIsServiceFromCache = false;
private ClientRequest(int transactionId, long startTimeMs) {
mTransactionId = transactionId;
@@ -2232,6 +2250,14 @@
public int getServicesCount() {
return mServices.size();
}
+
+ public void setServiceFromCache(boolean isServiceFromCache) {
+ mIsServiceFromCache = isServiceFromCache;
+ }
+
+ public boolean isServiceFromCache() {
+ return mIsServiceFromCache;
+ }
}
private static class LegacyClientRequest extends ClientRequest {
@@ -2544,7 +2570,13 @@
}
}
- void onResolveServiceFailed(int listenerKey, int error) {
+ void onResolveServiceFailedImmediately(int listenerKey, int error) {
+ onResolveServiceFailed(listenerKey, error, NO_TRANSACTION, 0L /* durationMs */);
+ }
+
+ void onResolveServiceFailed(int listenerKey, int error, int transactionId,
+ long durationMs) {
+ mMetrics.reportServiceResolutionFailed(transactionId, durationMs);
try {
mCb.onResolveServiceFailed(listenerKey, error);
} catch (RemoteException e) {
@@ -2552,7 +2584,12 @@
}
}
- void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) {
+ void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info,
+ ClientRequest request) {
+ mMetrics.reportServiceResolved(
+ request.mTransactionId,
+ request.calculateRequestDurationMs(mClock.elapsedRealtime()),
+ request.isServiceFromCache());
try {
mCb.onResolveServiceSucceeded(listenerKey, info);
} catch (RemoteException e) {
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceBrowserListener.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceBrowserListener.java
index 7c19359..4c3cbc0 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceBrowserListener.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceBrowserListener.java
@@ -32,8 +32,9 @@
* service records (PTR, SRV, TXT, A or AAAA) are received .
*
* @param serviceInfo The found mDNS service instance.
+ * @param isServiceFromCache Whether the found mDNS service is from cache.
*/
- void onServiceFound(@NonNull MdnsServiceInfo serviceInfo);
+ void onServiceFound(@NonNull MdnsServiceInfo serviceInfo, boolean isServiceFromCache);
/**
* Called when an mDNS service instance is updated. This method would be called only if all
@@ -84,8 +85,9 @@
* record has been received.
*
* @param serviceInfo The discovered mDNS service instance.
+ * @param isServiceFromCache Whether the discovered mDNS service is from cache.
*/
- void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo);
+ void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo, boolean isServiceFromCache);
/**
* Called when a discovered mDNS service instance is no longer valid and removed.
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
index 53a7ab9..861d8d1 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
@@ -297,9 +297,9 @@
if (!responseMatchesOptions(existingResponse, searchOptions)) continue;
final MdnsServiceInfo info =
buildMdnsServiceInfoFromResponse(existingResponse, serviceTypeLabels);
- listener.onServiceNameDiscovered(info);
+ listener.onServiceNameDiscovered(info, true /* isServiceFromCache */);
if (existingResponse.isComplete()) {
- listener.onServiceFound(info);
+ listener.onServiceFound(info, true /* isServiceFromCache */);
hadReply = true;
}
}
@@ -512,13 +512,13 @@
final MdnsServiceBrowserListener listener = listeners.keyAt(i);
if (newServiceFound) {
sharedLog.log("onServiceNameDiscovered: " + serviceInfo);
- listener.onServiceNameDiscovered(serviceInfo);
+ listener.onServiceNameDiscovered(serviceInfo, false /* isServiceFromCache */);
}
if (response.isComplete()) {
if (newServiceFound || serviceBecomesComplete) {
sharedLog.log("onServiceFound: " + serviceInfo);
- listener.onServiceFound(serviceInfo);
+ listener.onServiceFound(serviceInfo, false /* isServiceFromCache */);
} else {
sharedLog.log("onServiceUpdated: " + serviceInfo);
listener.onServiceUpdated(serviceInfo);