Merge "Report resolution metrics data" into main

This commit is contained in:
Paul Hu
2023-08-17 02:57:45 +00:00
committed by Gerrit Code Review
7 changed files with 265 additions and 100 deletions

View File

@@ -173,4 +173,37 @@ public class NetworkNsdReportedMetrics {
builder.setFoundServiceCount(servicesCount); builder.setFoundServiceCount(servicesCount);
mDependencies.statsWrite(builder.build()); 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());
}
} }

View File

@@ -265,7 +265,8 @@ public class NsdService extends INsdManager.Stub {
} }
@Override @Override
public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo) { } public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo,
boolean isServiceFromCache) { }
@Override @Override
public void onServiceUpdated(@NonNull MdnsServiceInfo serviceInfo) { } public void onServiceUpdated(@NonNull MdnsServiceInfo serviceInfo) { }
@@ -274,7 +275,8 @@ public class NsdService extends INsdManager.Stub {
public void onServiceRemoved(@NonNull MdnsServiceInfo serviceInfo) { } public void onServiceRemoved(@NonNull MdnsServiceInfo serviceInfo) { }
@Override @Override
public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo) { } public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo,
boolean isServiceFromCache) { }
@Override @Override
public void onServiceNameRemoved(@NonNull MdnsServiceInfo serviceInfo) { } public void onServiceNameRemoved(@NonNull MdnsServiceInfo serviceInfo) { }
@@ -300,10 +302,11 @@ public class NsdService extends INsdManager.Stub {
} }
@Override @Override
public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo) { public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo,
boolean isServiceFromCache) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId, mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.SERVICE_FOUND, NsdManager.SERVICE_FOUND,
new MdnsEvent(mClientRequestId, serviceInfo)); new MdnsEvent(mClientRequestId, serviceInfo, isServiceFromCache));
} }
@Override @Override
@@ -322,10 +325,10 @@ public class NsdService extends INsdManager.Stub {
} }
@Override @Override
public void onServiceFound(MdnsServiceInfo serviceInfo) { public void onServiceFound(MdnsServiceInfo serviceInfo, boolean isServiceFromCache) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId, mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.RESOLVE_SERVICE_SUCCEEDED, NsdManager.RESOLVE_SERVICE_SUCCEEDED,
new MdnsEvent(mClientRequestId, serviceInfo)); new MdnsEvent(mClientRequestId, serviceInfo, isServiceFromCache));
} }
} }
@@ -337,10 +340,11 @@ public class NsdService extends INsdManager.Stub {
} }
@Override @Override
public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo) { public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo,
boolean isServiceFromCache) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId, mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.SERVICE_UPDATED, NsdManager.SERVICE_UPDATED,
new MdnsEvent(mClientRequestId, serviceInfo)); new MdnsEvent(mClientRequestId, serviceInfo, isServiceFromCache));
} }
@Override @Override
@@ -463,10 +467,17 @@ public class NsdService extends INsdManager.Stub {
final int mClientRequestId; final int mClientRequestId;
@NonNull @NonNull
final MdnsServiceInfo mMdnsServiceInfo; final MdnsServiceInfo mMdnsServiceInfo;
final boolean mIsServiceFromCache;
MdnsEvent(int clientRequestId, @NonNull MdnsServiceInfo mdnsServiceInfo) { MdnsEvent(int clientRequestId, @NonNull MdnsServiceInfo mdnsServiceInfo) {
this(clientRequestId, mdnsServiceInfo, false /* isServiceFromCache */);
}
MdnsEvent(int clientRequestId, @NonNull MdnsServiceInfo mdnsServiceInfo,
boolean isServiceFromCache) {
mClientRequestId = clientRequestId; mClientRequestId = clientRequestId;
mMdnsServiceInfo = mdnsServiceInfo; mMdnsServiceInfo = mdnsServiceInfo;
mIsServiceFromCache = isServiceFromCache;
} }
} }
@@ -615,7 +626,7 @@ public class NsdService extends INsdManager.Stub {
case NsdManager.RESOLVE_SERVICE: case NsdManager.RESOLVE_SERVICE:
cInfo = getClientInfoForReply(msg); cInfo = getClientInfoForReply(msg);
if (cInfo != null) { if (cInfo != null) {
cInfo.onResolveServiceFailed( cInfo.onResolveServiceFailedImmediately(
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR); clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
} }
break; break;
@@ -682,9 +693,9 @@ public class NsdService extends INsdManager.Stub {
} }
private void storeLegacyRequestMap(int clientRequestId, int transactionId, private void storeLegacyRequestMap(int clientRequestId, int transactionId,
ClientInfo clientInfo, int what) { ClientInfo clientInfo, int what, long startTimeMs) {
clientInfo.mClientRequests.put(clientRequestId, new LegacyClientRequest( clientInfo.mClientRequests.put(clientRequestId,
transactionId, what, mClock.elapsedRealtime())); new LegacyClientRequest(transactionId, what, startTimeMs));
mTransactionIdToClientInfoMap.put(transactionId, clientInfo); mTransactionIdToClientInfoMap.put(transactionId, clientInfo);
// Remove the cleanup event because here comes a new request. // Remove the cleanup event because here comes a new request.
cancelStop(); cancelStop();
@@ -810,8 +821,8 @@ public class NsdService extends INsdManager.Stub {
Log.d(TAG, "Discover " + msg.arg2 + " " + transactionId Log.d(TAG, "Discover " + msg.arg2 + " " + transactionId
+ info.getServiceType()); + info.getServiceType());
} }
storeLegacyRequestMap( storeLegacyRequestMap(clientRequestId, transactionId, clientInfo,
clientRequestId, transactionId, clientInfo, msg.what); msg.what, mClock.elapsedRealtime());
clientInfo.onDiscoverServicesStarted( clientInfo.onDiscoverServicesStarted(
clientRequestId, info, transactionId); clientRequestId, info, transactionId);
} else { } else {
@@ -912,8 +923,8 @@ public class NsdService extends INsdManager.Stub {
Log.d(TAG, "Register " + clientRequestId Log.d(TAG, "Register " + clientRequestId
+ " " + transactionId); + " " + transactionId);
} }
storeLegacyRequestMap( storeLegacyRequestMap(clientRequestId, transactionId, clientInfo,
clientRequestId, transactionId, clientInfo, msg.what); msg.what, mClock.elapsedRealtime());
// Return success after mDns reports success // Return success after mDns reports success
} else { } else {
unregisterService(transactionId); unregisterService(transactionId);
@@ -986,8 +997,8 @@ public class NsdService extends INsdManager.Stub {
|| mDeps.isMdnsDiscoveryManagerEnabled(mContext) || mDeps.isMdnsDiscoveryManagerEnabled(mContext)
|| useDiscoveryManagerForType(serviceType)) { || useDiscoveryManagerForType(serviceType)) {
if (serviceType == null) { if (serviceType == null) {
clientInfo.onResolveServiceFailed(clientRequestId, clientInfo.onResolveServiceFailedImmediately(
NsdManager.FAILURE_INTERNAL_ERROR); clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
break; break;
} }
final String resolveServiceType = serviceType + ".local"; final String resolveServiceType = serviceType + ".local";
@@ -1009,7 +1020,7 @@ public class NsdService extends INsdManager.Stub {
+ " for service type:" + resolveServiceType); + " for service type:" + resolveServiceType);
} else { } else {
if (clientInfo.mResolvedService != null) { if (clientInfo.mResolvedService != null) {
clientInfo.onResolveServiceFailed( clientInfo.onResolveServiceFailedImmediately(
clientRequestId, NsdManager.FAILURE_ALREADY_ACTIVE); clientRequestId, NsdManager.FAILURE_ALREADY_ACTIVE);
break; break;
} }
@@ -1017,10 +1028,10 @@ public class NsdService extends INsdManager.Stub {
maybeStartDaemon(); maybeStartDaemon();
if (resolveService(transactionId, info)) { if (resolveService(transactionId, info)) {
clientInfo.mResolvedService = new NsdServiceInfo(); clientInfo.mResolvedService = new NsdServiceInfo();
storeLegacyRequestMap( storeLegacyRequestMap(clientRequestId, transactionId, clientInfo,
clientRequestId, transactionId, clientInfo, msg.what); msg.what, mClock.elapsedRealtime());
} else { } else {
clientInfo.onResolveServiceFailed( clientInfo.onResolveServiceFailedImmediately(
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR); clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR);
} }
} }
@@ -1279,10 +1290,11 @@ public class NsdService extends INsdManager.Stub {
final int transactionId2 = getUniqueId(); final int transactionId2 = getUniqueId();
if (getAddrInfo(transactionId2, info.hostname, info.interfaceIdx)) { if (getAddrInfo(transactionId2, info.hostname, info.interfaceIdx)) {
storeLegacyRequestMap(clientRequestId, transactionId2, clientInfo, storeLegacyRequestMap(clientRequestId, transactionId2, clientInfo,
NsdManager.RESOLVE_SERVICE); NsdManager.RESOLVE_SERVICE, request.mStartTimeMs);
} else { } else {
clientInfo.onResolveServiceFailed( clientInfo.onResolveServiceFailed(clientRequestId,
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR); NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
request.calculateRequestDurationMs(mClock.elapsedRealtime()));
clientInfo.mResolvedService = null; clientInfo.mResolvedService = null;
} }
break; break;
@@ -1291,16 +1303,18 @@ public class NsdService extends INsdManager.Stub {
/* NNN resolveId errorCode */ /* NNN resolveId errorCode */
stopResolveService(transactionId); stopResolveService(transactionId);
removeRequestMap(clientRequestId, transactionId, clientInfo); removeRequestMap(clientRequestId, transactionId, clientInfo);
clientInfo.onResolveServiceFailed( clientInfo.onResolveServiceFailed(clientRequestId,
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR); NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
request.calculateRequestDurationMs(mClock.elapsedRealtime()));
clientInfo.mResolvedService = null; clientInfo.mResolvedService = null;
break; break;
case IMDnsEventListener.SERVICE_GET_ADDR_FAILED: case IMDnsEventListener.SERVICE_GET_ADDR_FAILED:
/* NNN resolveId errorCode */ /* NNN resolveId errorCode */
stopGetAddrInfo(transactionId); stopGetAddrInfo(transactionId);
removeRequestMap(clientRequestId, transactionId, clientInfo); removeRequestMap(clientRequestId, transactionId, clientInfo);
clientInfo.onResolveServiceFailed( clientInfo.onResolveServiceFailed(clientRequestId,
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR); NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
request.calculateRequestDurationMs(mClock.elapsedRealtime()));
clientInfo.mResolvedService = null; clientInfo.mResolvedService = null;
break; break;
case IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS: { case IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS: {
@@ -1323,10 +1337,11 @@ public class NsdService extends INsdManager.Stub {
setServiceNetworkForCallback(clientInfo.mResolvedService, setServiceNetworkForCallback(clientInfo.mResolvedService,
netId, info.interfaceIdx); netId, info.interfaceIdx);
clientInfo.onResolveServiceSucceeded( clientInfo.onResolveServiceSucceeded(
clientRequestId, clientInfo.mResolvedService); clientRequestId, clientInfo.mResolvedService, request);
} else { } else {
clientInfo.onResolveServiceFailed( clientInfo.onResolveServiceFailed(clientRequestId,
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR); NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
request.calculateRequestDurationMs(mClock.elapsedRealtime()));
} }
stopGetAddrInfo(transactionId); stopGetAddrInfo(transactionId);
removeRequestMap(clientRequestId, transactionId, clientInfo); removeRequestMap(clientRequestId, transactionId, clientInfo);
@@ -1429,11 +1444,13 @@ public class NsdService extends INsdManager.Stub {
final List<InetAddress> addresses = getInetAddresses(serviceInfo); final List<InetAddress> addresses = getInetAddresses(serviceInfo);
if (addresses.size() != 0) { if (addresses.size() != 0) {
info.setHostAddresses(addresses); info.setHostAddresses(addresses);
clientInfo.onResolveServiceSucceeded(clientRequestId, info); request.setServiceFromCache(event.mIsServiceFromCache);
clientInfo.onResolveServiceSucceeded(clientRequestId, info, request);
} else { } else {
// No address. Notify resolution failure. // No address. Notify resolution failure.
clientInfo.onResolveServiceFailed( clientInfo.onResolveServiceFailed(clientRequestId,
clientRequestId, NsdManager.FAILURE_INTERNAL_ERROR); NsdManager.FAILURE_INTERNAL_ERROR, transactionId,
request.calculateRequestDurationMs(mClock.elapsedRealtime()));
} }
// Unregister the listener immediately like IMDnsEventListener design // Unregister the listener immediately like IMDnsEventListener design
@@ -2200,6 +2217,7 @@ public class NsdService extends INsdManager.Stub {
private int mFoundServiceCount = 0; private int mFoundServiceCount = 0;
private int mLostServiceCount = 0; private int mLostServiceCount = 0;
private final Set<String> mServices = new ArraySet<>(); private final Set<String> mServices = new ArraySet<>();
private boolean mIsServiceFromCache = false;
private ClientRequest(int transactionId, long startTimeMs) { private ClientRequest(int transactionId, long startTimeMs) {
mTransactionId = transactionId; mTransactionId = transactionId;
@@ -2232,6 +2250,14 @@ public class NsdService extends INsdManager.Stub {
public int getServicesCount() { public int getServicesCount() {
return mServices.size(); return mServices.size();
} }
public void setServiceFromCache(boolean isServiceFromCache) {
mIsServiceFromCache = isServiceFromCache;
}
public boolean isServiceFromCache() {
return mIsServiceFromCache;
}
} }
private static class LegacyClientRequest extends ClientRequest { private static class LegacyClientRequest extends ClientRequest {
@@ -2544,7 +2570,13 @@ public class NsdService extends INsdManager.Stub {
} }
} }
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 { try {
mCb.onResolveServiceFailed(listenerKey, error); mCb.onResolveServiceFailed(listenerKey, error);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -2552,7 +2584,12 @@ public class NsdService extends INsdManager.Stub {
} }
} }
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 { try {
mCb.onResolveServiceSucceeded(listenerKey, info); mCb.onResolveServiceSucceeded(listenerKey, info);
} catch (RemoteException e) { } catch (RemoteException e) {

View File

@@ -32,8 +32,9 @@ public interface MdnsServiceBrowserListener {
* service records (PTR, SRV, TXT, A or AAAA) are received . * service records (PTR, SRV, TXT, A or AAAA) are received .
* *
* @param serviceInfo The found mDNS service instance. * @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 * Called when an mDNS service instance is updated. This method would be called only if all
@@ -84,8 +85,9 @@ public interface MdnsServiceBrowserListener {
* record has been received. * record has been received.
* *
* @param serviceInfo The discovered mDNS service instance. * @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. * Called when a discovered mDNS service instance is no longer valid and removed.

View File

@@ -297,9 +297,9 @@ public class MdnsServiceTypeClient {
if (!responseMatchesOptions(existingResponse, searchOptions)) continue; if (!responseMatchesOptions(existingResponse, searchOptions)) continue;
final MdnsServiceInfo info = final MdnsServiceInfo info =
buildMdnsServiceInfoFromResponse(existingResponse, serviceTypeLabels); buildMdnsServiceInfoFromResponse(existingResponse, serviceTypeLabels);
listener.onServiceNameDiscovered(info); listener.onServiceNameDiscovered(info, true /* isServiceFromCache */);
if (existingResponse.isComplete()) { if (existingResponse.isComplete()) {
listener.onServiceFound(info); listener.onServiceFound(info, true /* isServiceFromCache */);
hadReply = true; hadReply = true;
} }
} }
@@ -512,13 +512,13 @@ public class MdnsServiceTypeClient {
final MdnsServiceBrowserListener listener = listeners.keyAt(i); final MdnsServiceBrowserListener listener = listeners.keyAt(i);
if (newServiceFound) { if (newServiceFound) {
sharedLog.log("onServiceNameDiscovered: " + serviceInfo); sharedLog.log("onServiceNameDiscovered: " + serviceInfo);
listener.onServiceNameDiscovered(serviceInfo); listener.onServiceNameDiscovered(serviceInfo, false /* isServiceFromCache */);
} }
if (response.isComplete()) { if (response.isComplete()) {
if (newServiceFound || serviceBecomesComplete) { if (newServiceFound || serviceBecomesComplete) {
sharedLog.log("onServiceFound: " + serviceInfo); sharedLog.log("onServiceFound: " + serviceInfo);
listener.onServiceFound(serviceInfo); listener.onServiceFound(serviceInfo, false /* isServiceFromCache */);
} else { } else {
sharedLog.log("onServiceUpdated: " + serviceInfo); sharedLog.log("onServiceUpdated: " + serviceInfo);
listener.onServiceUpdated(serviceInfo); listener.onServiceUpdated(serviceInfo);

View File

@@ -160,4 +160,45 @@ class NetworkNsdReportedMetricsTest {
assertEquals(durationMs, it.eventDurationMillisec) assertEquals(durationMs, it.eventDurationMillisec)
} }
} }
@Test
fun testReportServiceResolved() {
val clientId = 99
val transactionId = 100
val durationMs = 10L
val metrics = NetworkNsdReportedMetrics(true /* isLegacy */, clientId, deps)
metrics.reportServiceResolved(transactionId, durationMs, true /* isServiceFromCache */)
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_RESOLVE, it.type)
assertEquals(MdnsQueryResult.MQR_SERVICE_RESOLVED, it.queryResult)
assertTrue(it.isKnownService)
assertEquals(durationMs, it.eventDurationMillisec)
}
}
@Test
fun testReportServiceResolutionFailed() {
val clientId = 99
val transactionId = 100
val durationMs = 10L
val metrics = NetworkNsdReportedMetrics(false /* isLegacy */, clientId, deps)
metrics.reportServiceResolutionFailed(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_RESOLVE, it.type)
assertEquals(MdnsQueryResult.MQR_SERVICE_RESOLUTION_FAILED, it.queryResult)
assertEquals(durationMs, it.eventDurationMillisec)
}
}
} }

View File

@@ -457,19 +457,24 @@ public class NsdServiceTest {
eq(interfaceIdx)); eq(interfaceIdx));
final String serviceAddress = "192.0.2.123"; final String serviceAddress = "192.0.2.123";
final int getAddrId = getAddrIdCaptor.getValue();
final GetAddressInfo addressInfo = new GetAddressInfo( final GetAddressInfo addressInfo = new GetAddressInfo(
getAddrIdCaptor.getValue(), getAddrId,
IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS, IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS,
SERVICE_FULL_NAME, SERVICE_FULL_NAME,
serviceAddress, serviceAddress,
interfaceIdx, interfaceIdx,
INetd.LOCAL_NET_ID); INetd.LOCAL_NET_ID);
doReturn(TEST_TIME_MS + 10L).when(mClock).elapsedRealtime();
eventListener.onGettingServiceAddressStatus(addressInfo); eventListener.onGettingServiceAddressStatus(addressInfo);
waitForIdle(); waitForIdle();
final ArgumentCaptor<NsdServiceInfo> resInfoCaptor = final ArgumentCaptor<NsdServiceInfo> resInfoCaptor =
ArgumentCaptor.forClass(NsdServiceInfo.class); ArgumentCaptor.forClass(NsdServiceInfo.class);
verify(resolveListener, timeout(TIMEOUT_MS)).onServiceResolved(resInfoCaptor.capture()); verify(resolveListener, timeout(TIMEOUT_MS)).onServiceResolved(resInfoCaptor.capture());
verify(mMetrics).reportServiceResolved(
getAddrId, 10L /* durationMs */, false /* isServiceFromCache */);
final NsdServiceInfo resolvedService = resInfoCaptor.getValue(); final NsdServiceInfo resolvedService = resInfoCaptor.getValue();
assertEquals(SERVICE_NAME, resolvedService.getServiceName()); assertEquals(SERVICE_NAME, resolvedService.getServiceName());
assertEquals("." + SERVICE_TYPE, resolvedService.getServiceType()); assertEquals("." + SERVICE_TYPE, resolvedService.getServiceType());
@@ -609,8 +614,9 @@ public class NsdServiceTest {
eq("local.") /* domain */, eq(IFACE_IDX_ANY)); eq("local.") /* domain */, eq(IFACE_IDX_ANY));
// Fail to resolve service. // Fail to resolve service.
final int resolvId = resolvIdCaptor.getValue();
final ResolutionInfo resolutionFailedInfo = new ResolutionInfo( final ResolutionInfo resolutionFailedInfo = new ResolutionInfo(
resolvIdCaptor.getValue(), resolvId,
IMDnsEventListener.SERVICE_RESOLUTION_FAILED, IMDnsEventListener.SERVICE_RESOLUTION_FAILED,
null /* serviceName */, null /* serviceName */,
null /* serviceType */, null /* serviceType */,
@@ -620,9 +626,11 @@ public class NsdServiceTest {
0 /* port */, 0 /* port */,
new byte[0] /* txtRecord */, new byte[0] /* txtRecord */,
IFACE_IDX_ANY); IFACE_IDX_ANY);
doReturn(TEST_TIME_MS + 10L).when(mClock).elapsedRealtime();
eventListener.onServiceResolutionStatus(resolutionFailedInfo); eventListener.onServiceResolutionStatus(resolutionFailedInfo);
verify(resolveListener, timeout(TIMEOUT_MS)) verify(resolveListener, timeout(TIMEOUT_MS))
.onResolveFailed(any(), eq(FAILURE_INTERNAL_ERROR)); .onResolveFailed(any(), eq(FAILURE_INTERNAL_ERROR));
verify(mMetrics).reportServiceResolutionFailed(resolvId, 10L /* durationMs */);
} }
@Test @Test
@@ -660,16 +668,19 @@ public class NsdServiceTest {
eq(IFACE_IDX_ANY)); eq(IFACE_IDX_ANY));
// Fail to get service address. // Fail to get service address.
final int getAddrId = getAddrIdCaptor.getValue();
final GetAddressInfo gettingAddrFailedInfo = new GetAddressInfo( final GetAddressInfo gettingAddrFailedInfo = new GetAddressInfo(
getAddrIdCaptor.getValue(), getAddrId,
IMDnsEventListener.SERVICE_GET_ADDR_FAILED, IMDnsEventListener.SERVICE_GET_ADDR_FAILED,
null /* hostname */, null /* hostname */,
null /* address */, null /* address */,
IFACE_IDX_ANY, IFACE_IDX_ANY,
0 /* netId */); 0 /* netId */);
doReturn(TEST_TIME_MS + 10L).when(mClock).elapsedRealtime();
eventListener.onGettingServiceAddressStatus(gettingAddrFailedInfo); eventListener.onGettingServiceAddressStatus(gettingAddrFailedInfo);
verify(resolveListener, timeout(TIMEOUT_MS)) verify(resolveListener, timeout(TIMEOUT_MS))
.onResolveFailed(any(), eq(FAILURE_INTERNAL_ERROR)); .onResolveFailed(any(), eq(FAILURE_INTERNAL_ERROR));
verify(mMetrics).reportServiceResolutionFailed(getAddrId, 10L /* durationMs */);
} }
@Test @Test
@@ -828,7 +839,7 @@ public class NsdServiceTest {
network); network);
// Verify onServiceFound callback // Verify onServiceFound callback
listener.onServiceFound(mdnsServiceInfo); listener.onServiceFound(mdnsServiceInfo, false /* isServiceFromCache */);
final ArgumentCaptor<NsdServiceInfo> updateInfoCaptor = final ArgumentCaptor<NsdServiceInfo> updateInfoCaptor =
ArgumentCaptor.forClass(NsdServiceInfo.class); ArgumentCaptor.forClass(NsdServiceInfo.class);
verify(serviceInfoCallback, timeout(TIMEOUT_MS).times(1)) verify(serviceInfoCallback, timeout(TIMEOUT_MS).times(1))
@@ -972,7 +983,7 @@ public class NsdServiceTest {
network); network);
// Verify onServiceNameDiscovered callback // Verify onServiceNameDiscovered callback
listener.onServiceNameDiscovered(foundInfo); listener.onServiceNameDiscovered(foundInfo, false /* isServiceFromCache */);
verify(discListener, timeout(TIMEOUT_MS)).onServiceFound(argThat(info -> verify(discListener, timeout(TIMEOUT_MS)).onServiceFound(argThat(info ->
info.getServiceName().equals(SERVICE_NAME) info.getServiceName().equals(SERVICE_NAME)
// Service type in discovery callbacks has a dot at the end // Service type in discovery callbacks has a dot at the end
@@ -1081,8 +1092,8 @@ public class NsdServiceTest {
final Network network = new Network(999); final Network network = new Network(999);
final String serviceType = "_nsd._service._tcp"; final String serviceType = "_nsd._service._tcp";
final String constructedServiceType = "_service._tcp.local"; final String constructedServiceType = "_service._tcp.local";
final ArgumentCaptor<MdnsServiceBrowserListener> listenerCaptor = final ArgumentCaptor<MdnsListener> listenerCaptor =
ArgumentCaptor.forClass(MdnsServiceBrowserListener.class); ArgumentCaptor.forClass(MdnsListener.class);
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, serviceType); final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, serviceType);
request.setNetwork(network); request.setNetwork(network);
client.resolveService(request, resolveListener); client.resolveService(request, resolveListener);
@@ -1097,7 +1108,7 @@ public class NsdServiceTest {
// Subtypes are not used for resolution, only for discovery // Subtypes are not used for resolution, only for discovery
assertEquals(Collections.emptyList(), optionsCaptor.getValue().getSubtypes()); assertEquals(Collections.emptyList(), optionsCaptor.getValue().getSubtypes());
final MdnsServiceBrowserListener listener = listenerCaptor.getValue(); final MdnsListener listener = listenerCaptor.getValue();
final MdnsServiceInfo mdnsServiceInfo = new MdnsServiceInfo( final MdnsServiceInfo mdnsServiceInfo = new MdnsServiceInfo(
SERVICE_NAME, SERVICE_NAME,
constructedServiceType.split("\\."), constructedServiceType.split("\\."),
@@ -1113,10 +1124,14 @@ public class NsdServiceTest {
network); network);
// Verify onServiceFound callback // Verify onServiceFound callback
listener.onServiceFound(mdnsServiceInfo); doReturn(TEST_TIME_MS + 10L).when(mClock).elapsedRealtime();
listener.onServiceFound(mdnsServiceInfo, true /* isServiceFromCache */);
final ArgumentCaptor<NsdServiceInfo> infoCaptor = final ArgumentCaptor<NsdServiceInfo> infoCaptor =
ArgumentCaptor.forClass(NsdServiceInfo.class); ArgumentCaptor.forClass(NsdServiceInfo.class);
verify(resolveListener, timeout(TIMEOUT_MS)).onServiceResolved(infoCaptor.capture()); verify(resolveListener, timeout(TIMEOUT_MS)).onServiceResolved(infoCaptor.capture());
verify(mMetrics).reportServiceResolved(
listener.mTransactionId, 10 /* durationMs */, true /* isServiceFromCache */);
final NsdServiceInfo info = infoCaptor.getValue(); final NsdServiceInfo info = infoCaptor.getValue();
assertEquals(SERVICE_NAME, info.getServiceName()); assertEquals(SERVICE_NAME, info.getServiceName());
assertEquals("._service._tcp", info.getServiceType()); assertEquals("._service._tcp", info.getServiceType());

View File

@@ -26,6 +26,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.argThat;
@@ -645,14 +646,14 @@ public class MdnsServiceTypeClientTests {
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
verify(mockListenerOne).onServiceNameDiscovered(any()); verify(mockListenerOne).onServiceNameDiscovered(any(), eq(false) /* isServiceFromCache */);
verify(mockListenerOne).onServiceFound(any()); verify(mockListenerOne).onServiceFound(any(), eq(false) /* isServiceFromCache */);
// File another identical query // File another identical query
startSendAndReceive(mockListenerTwo, searchOptions); startSendAndReceive(mockListenerTwo, searchOptions);
verify(mockListenerTwo).onServiceNameDiscovered(any()); verify(mockListenerTwo).onServiceNameDiscovered(any(), eq(true) /* isServiceFromCache */);
verify(mockListenerTwo).onServiceFound(any()); verify(mockListenerTwo).onServiceFound(any(), eq(true) /* isServiceFromCache */);
// This time no query is submitted, only scheduled // This time no query is submitted, only scheduled
assertNull(currentThreadExecutor.getAndClearSubmittedRunnable()); assertNull(currentThreadExecutor.getAndClearSubmittedRunnable());
@@ -686,7 +687,8 @@ public class MdnsServiceTypeClientTests {
"service-instance-1", null /* host */, 0 /* port */, "service-instance-1", null /* host */, 0 /* port */,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture()); verify(mockListenerOne).onServiceNameDiscovered(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
"service-instance-1", "service-instance-1",
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -697,7 +699,7 @@ public class MdnsServiceTypeClientTests {
Collections.emptyMap(), Collections.emptyMap(),
socketKey); socketKey);
verify(mockListenerOne, never()).onServiceFound(any(MdnsServiceInfo.class)); verify(mockListenerOne, never()).onServiceFound(any(MdnsServiceInfo.class), anyBoolean());
verify(mockListenerOne, never()).onServiceUpdated(any(MdnsServiceInfo.class)); verify(mockListenerOne, never()).onServiceUpdated(any(MdnsServiceInfo.class));
} }
@@ -718,7 +720,8 @@ public class MdnsServiceTypeClientTests {
socketKey); socketKey);
// Verify onServiceNameDiscovered was called once for the initial response. // Verify onServiceNameDiscovered was called once for the initial response.
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture()); verify(mockListenerOne).onServiceNameDiscovered(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
"service-instance-1", "service-instance-1",
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -730,7 +733,8 @@ public class MdnsServiceTypeClientTests {
socketKey); socketKey);
// Verify onServiceFound was called once for the initial response. // Verify onServiceFound was called once for the initial response.
verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture()); verify(mockListenerOne).onServiceFound(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
MdnsServiceInfo initialServiceInfo = serviceInfoCaptor.getAllValues().get(1); MdnsServiceInfo initialServiceInfo = serviceInfoCaptor.getAllValues().get(1);
assertEquals(initialServiceInfo.getServiceInstanceName(), "service-instance-1"); assertEquals(initialServiceInfo.getServiceInstanceName(), "service-instance-1");
assertEquals(initialServiceInfo.getIpv4Address(), ipV4Address); assertEquals(initialServiceInfo.getIpv4Address(), ipV4Address);
@@ -770,7 +774,8 @@ public class MdnsServiceTypeClientTests {
socketKey); socketKey);
// Verify onServiceNameDiscovered was called once for the initial response. // Verify onServiceNameDiscovered was called once for the initial response.
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture()); verify(mockListenerOne).onServiceNameDiscovered(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
"service-instance-1", "service-instance-1",
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -782,7 +787,8 @@ public class MdnsServiceTypeClientTests {
socketKey); socketKey);
// Verify onServiceFound was called once for the initial response. // Verify onServiceFound was called once for the initial response.
verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture()); verify(mockListenerOne).onServiceFound(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
MdnsServiceInfo initialServiceInfo = serviceInfoCaptor.getAllValues().get(1); MdnsServiceInfo initialServiceInfo = serviceInfoCaptor.getAllValues().get(1);
assertEquals(initialServiceInfo.getServiceInstanceName(), "service-instance-1"); assertEquals(initialServiceInfo.getServiceInstanceName(), "service-instance-1");
assertEquals(initialServiceInfo.getIpv6Address(), ipV6Address); assertEquals(initialServiceInfo.getIpv6Address(), ipV6Address);
@@ -867,7 +873,8 @@ public class MdnsServiceTypeClientTests {
startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
// Verify onServiceNameDiscovered was called once for the existing response. // Verify onServiceNameDiscovered was called once for the existing response.
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture()); verify(mockListenerOne).onServiceNameDiscovered(
serviceInfoCaptor.capture(), eq(true) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
"service-instance-1", "service-instance-1",
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -879,7 +886,8 @@ public class MdnsServiceTypeClientTests {
socketKey); socketKey);
// Verify onServiceFound was called once for the existing response. // Verify onServiceFound was called once for the existing response.
verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture()); verify(mockListenerOne).onServiceFound(
serviceInfoCaptor.capture(), eq(true) /* isServiceFromCache */);
MdnsServiceInfo existingServiceInfo = serviceInfoCaptor.getAllValues().get(1); MdnsServiceInfo existingServiceInfo = serviceInfoCaptor.getAllValues().get(1);
assertEquals(existingServiceInfo.getServiceInstanceName(), "service-instance-1"); assertEquals(existingServiceInfo.getServiceInstanceName(), "service-instance-1");
assertEquals(existingServiceInfo.getIpv4Address(), "192.168.1.1"); assertEquals(existingServiceInfo.getIpv4Address(), "192.168.1.1");
@@ -897,8 +905,9 @@ public class MdnsServiceTypeClientTests {
// Verify onServiceFound was not called on the newly registered listener after the existing // Verify onServiceFound was not called on the newly registered listener after the existing
// response is gone. // response is gone.
verify(mockListenerTwo, never()).onServiceNameDiscovered(any(MdnsServiceInfo.class)); verify(mockListenerTwo, never()).onServiceNameDiscovered(
verify(mockListenerTwo, never()).onServiceFound(any(MdnsServiceInfo.class)); any(MdnsServiceInfo.class), eq(false));
verify(mockListenerTwo, never()).onServiceFound(any(MdnsServiceInfo.class), anyBoolean());
} }
@Test @Test
@@ -1044,7 +1053,8 @@ public class MdnsServiceTypeClientTests {
socketKey); socketKey);
// Verify onServiceNameDiscovered was first called for the initial response. // Verify onServiceNameDiscovered was first called for the initial response.
inOrder.verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture()); inOrder.verify(mockListenerOne).onServiceNameDiscovered(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
serviceName, serviceName,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -1056,7 +1066,8 @@ public class MdnsServiceTypeClientTests {
socketKey); socketKey);
// Verify onServiceFound was second called for the second response. // Verify onServiceFound was second called for the second response.
inOrder.verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture()); inOrder.verify(mockListenerOne).onServiceFound(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(1), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(1),
serviceName, serviceName,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -1183,10 +1194,11 @@ public class MdnsServiceTypeClientTests {
Collections.emptyList() /* authorityRecords */, Collections.emptyList() /* authorityRecords */,
Collections.emptyList() /* additionalRecords */); Collections.emptyList() /* additionalRecords */);
inOrder.verify(mockListenerOne, never()).onServiceNameDiscovered(any()); inOrder.verify(mockListenerOne, never()).onServiceNameDiscovered(any(), anyBoolean());
processResponse(addressResponse, socketKey); processResponse(addressResponse, socketKey);
inOrder.verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture()); inOrder.verify(mockListenerOne).onServiceFound(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getValue(), verifyServiceInfo(serviceInfoCaptor.getValue(),
instanceName, instanceName,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -1253,8 +1265,10 @@ public class MdnsServiceTypeClientTests {
Collections.emptyList() /* additionalRecords */); Collections.emptyList() /* additionalRecords */);
processResponse(srvTxtResponse, socketKey); processResponse(srvTxtResponse, socketKey);
dispatchMessage(); dispatchMessage();
inOrder.verify(mockListenerOne).onServiceNameDiscovered(any()); inOrder.verify(mockListenerOne).onServiceNameDiscovered(
inOrder.verify(mockListenerOne).onServiceFound(any()); any(), eq(false) /* isServiceFromCache */);
inOrder.verify(mockListenerOne).onServiceFound(
any(), eq(false) /* isServiceFromCache */);
// Expect no query on the next run // Expect no query on the next run
currentThreadExecutor.getAndClearLastScheduledRunnable().run(); currentThreadExecutor.getAndClearLastScheduledRunnable().run();
@@ -1355,24 +1369,29 @@ public class MdnsServiceTypeClientTests {
// mockListenerOne gets notified for the requested instance // mockListenerOne gets notified for the requested instance
verify(mockListenerOne).onServiceNameDiscovered( verify(mockListenerOne).onServiceNameDiscovered(
matchServiceName(capitalizedRequestInstance)); matchServiceName(capitalizedRequestInstance), eq(false) /* isServiceFromCache */);
verify(mockListenerOne).onServiceFound(matchServiceName(capitalizedRequestInstance)); verify(mockListenerOne).onServiceFound(
matchServiceName(capitalizedRequestInstance), eq(false) /* isServiceFromCache */);
// ...but does not get any callback for the other instance // ...but does not get any callback for the other instance
verify(mockListenerOne, never()).onServiceFound(matchServiceName(otherInstance)); verify(mockListenerOne, never()).onServiceFound(
verify(mockListenerOne, never()).onServiceNameDiscovered(matchServiceName(otherInstance)); matchServiceName(otherInstance), anyBoolean());
verify(mockListenerOne, never()).onServiceNameDiscovered(
matchServiceName(otherInstance), anyBoolean());
verify(mockListenerOne, never()).onServiceUpdated(matchServiceName(otherInstance)); verify(mockListenerOne, never()).onServiceUpdated(matchServiceName(otherInstance));
verify(mockListenerOne, never()).onServiceRemoved(matchServiceName(otherInstance)); verify(mockListenerOne, never()).onServiceRemoved(matchServiceName(otherInstance));
// mockListenerTwo gets notified for both though // mockListenerTwo gets notified for both though
final InOrder inOrder = inOrder(mockListenerTwo); final InOrder inOrder = inOrder(mockListenerTwo);
inOrder.verify(mockListenerTwo).onServiceNameDiscovered( inOrder.verify(mockListenerTwo).onServiceNameDiscovered(
matchServiceName(capitalizedRequestInstance)); matchServiceName(capitalizedRequestInstance), eq(false) /* isServiceFromCache */);
inOrder.verify(mockListenerTwo).onServiceFound( inOrder.verify(mockListenerTwo).onServiceFound(
matchServiceName(capitalizedRequestInstance)); matchServiceName(capitalizedRequestInstance), eq(false) /* isServiceFromCache */);
inOrder.verify(mockListenerTwo).onServiceNameDiscovered(matchServiceName(otherInstance)); inOrder.verify(mockListenerTwo).onServiceNameDiscovered(
inOrder.verify(mockListenerTwo).onServiceFound(matchServiceName(otherInstance)); matchServiceName(otherInstance), eq(false) /* isServiceFromCache */);
inOrder.verify(mockListenerTwo).onServiceFound(
matchServiceName(otherInstance), eq(false) /* isServiceFromCache */);
inOrder.verify(mockListenerTwo).onServiceUpdated(matchServiceName(otherInstance)); inOrder.verify(mockListenerTwo).onServiceUpdated(matchServiceName(otherInstance));
inOrder.verify(mockListenerTwo).onServiceRemoved(matchServiceName(otherInstance)); inOrder.verify(mockListenerTwo).onServiceRemoved(matchServiceName(otherInstance));
} }
@@ -1439,22 +1458,30 @@ public class MdnsServiceTypeClientTests {
final ArgumentMatcher<MdnsServiceInfo> subtypeInstanceMatcher = info -> final ArgumentMatcher<MdnsServiceInfo> subtypeInstanceMatcher = info ->
info.getServiceInstanceName().equals(matchingInstance) info.getServiceInstanceName().equals(matchingInstance)
&& info.getSubtypes().equals(Collections.singletonList(subtype)); && info.getSubtypes().equals(Collections.singletonList(subtype));
verify(mockListenerOne).onServiceNameDiscovered(argThat(subtypeInstanceMatcher)); verify(mockListenerOne).onServiceNameDiscovered(
verify(mockListenerOne).onServiceFound(argThat(subtypeInstanceMatcher)); argThat(subtypeInstanceMatcher), eq(false) /* isServiceFromCache */);
verify(mockListenerOne).onServiceFound(
argThat(subtypeInstanceMatcher), eq(false) /* isServiceFromCache */);
// ...but does not get any callback for the other instance // ...but does not get any callback for the other instance
verify(mockListenerOne, never()).onServiceFound(matchServiceName(otherInstance)); verify(mockListenerOne, never()).onServiceFound(
verify(mockListenerOne, never()).onServiceNameDiscovered(matchServiceName(otherInstance)); matchServiceName(otherInstance), anyBoolean());
verify(mockListenerOne, never()).onServiceNameDiscovered(
matchServiceName(otherInstance), anyBoolean());
verify(mockListenerOne, never()).onServiceUpdated(matchServiceName(otherInstance)); verify(mockListenerOne, never()).onServiceUpdated(matchServiceName(otherInstance));
verify(mockListenerOne, never()).onServiceRemoved(matchServiceName(otherInstance)); verify(mockListenerOne, never()).onServiceRemoved(matchServiceName(otherInstance));
// mockListenerTwo gets notified for both though // mockListenerTwo gets notified for both though
final InOrder inOrder = inOrder(mockListenerTwo); final InOrder inOrder = inOrder(mockListenerTwo);
inOrder.verify(mockListenerTwo).onServiceNameDiscovered(argThat(subtypeInstanceMatcher)); inOrder.verify(mockListenerTwo).onServiceNameDiscovered(
inOrder.verify(mockListenerTwo).onServiceFound(argThat(subtypeInstanceMatcher)); argThat(subtypeInstanceMatcher), eq(false) /* isServiceFromCache */);
inOrder.verify(mockListenerTwo).onServiceFound(
argThat(subtypeInstanceMatcher), eq(false) /* isServiceFromCache */);
inOrder.verify(mockListenerTwo).onServiceNameDiscovered(matchServiceName(otherInstance)); inOrder.verify(mockListenerTwo).onServiceNameDiscovered(
inOrder.verify(mockListenerTwo).onServiceFound(matchServiceName(otherInstance)); matchServiceName(otherInstance), eq(false) /* isServiceFromCache */);
inOrder.verify(mockListenerTwo).onServiceFound(
matchServiceName(otherInstance), eq(false) /* isServiceFromCache */);
inOrder.verify(mockListenerTwo).onServiceUpdated(matchServiceName(otherInstance)); inOrder.verify(mockListenerTwo).onServiceUpdated(matchServiceName(otherInstance));
inOrder.verify(mockListenerTwo).onServiceRemoved(matchServiceName(otherInstance)); inOrder.verify(mockListenerTwo).onServiceRemoved(matchServiceName(otherInstance));
} }
@@ -1508,24 +1535,30 @@ public class MdnsServiceTypeClientTests {
// mockListenerOne gets notified for the requested instance // mockListenerOne gets notified for the requested instance
final InOrder inOrder1 = inOrder(mockListenerOne); final InOrder inOrder1 = inOrder(mockListenerOne);
inOrder1.verify(mockListenerOne).onServiceNameDiscovered( inOrder1.verify(mockListenerOne).onServiceNameDiscovered(
matchServiceName(requestedInstance)); matchServiceName(requestedInstance), eq(false) /* isServiceFromCache */);
inOrder1.verify(mockListenerOne).onServiceFound(matchServiceName(requestedInstance)); inOrder1.verify(mockListenerOne).onServiceFound(
matchServiceName(requestedInstance), eq(false) /* isServiceFromCache */);
inOrder1.verify(mockListenerOne).onServiceRemoved(matchServiceName(requestedInstance)); inOrder1.verify(mockListenerOne).onServiceRemoved(matchServiceName(requestedInstance));
inOrder1.verify(mockListenerOne).onServiceNameRemoved(matchServiceName(requestedInstance)); inOrder1.verify(mockListenerOne).onServiceNameRemoved(matchServiceName(requestedInstance));
verify(mockListenerOne, never()).onServiceFound(matchServiceName(otherInstance)); verify(mockListenerOne, never()).onServiceFound(
verify(mockListenerOne, never()).onServiceNameDiscovered(matchServiceName(otherInstance)); matchServiceName(otherInstance), anyBoolean());
verify(mockListenerOne, never()).onServiceNameDiscovered(
matchServiceName(otherInstance), anyBoolean());
verify(mockListenerOne, never()).onServiceRemoved(matchServiceName(otherInstance)); verify(mockListenerOne, never()).onServiceRemoved(matchServiceName(otherInstance));
verify(mockListenerOne, never()).onServiceNameRemoved(matchServiceName(otherInstance)); verify(mockListenerOne, never()).onServiceNameRemoved(matchServiceName(otherInstance));
// mockListenerTwo gets notified for both though // mockListenerTwo gets notified for both though
final InOrder inOrder2 = inOrder(mockListenerTwo); final InOrder inOrder2 = inOrder(mockListenerTwo);
inOrder2.verify(mockListenerTwo).onServiceNameDiscovered( inOrder2.verify(mockListenerTwo).onServiceNameDiscovered(
matchServiceName(requestedInstance)); matchServiceName(requestedInstance), eq(false) /* isServiceFromCache */);
inOrder2.verify(mockListenerTwo).onServiceFound(matchServiceName(requestedInstance)); inOrder2.verify(mockListenerTwo).onServiceFound(
matchServiceName(requestedInstance), eq(false) /* isServiceFromCache */);
inOrder2.verify(mockListenerTwo).onServiceRemoved(matchServiceName(requestedInstance)); inOrder2.verify(mockListenerTwo).onServiceRemoved(matchServiceName(requestedInstance));
inOrder2.verify(mockListenerTwo).onServiceNameRemoved(matchServiceName(requestedInstance)); inOrder2.verify(mockListenerTwo).onServiceNameRemoved(matchServiceName(requestedInstance));
verify(mockListenerTwo).onServiceNameDiscovered(matchServiceName(otherInstance)); verify(mockListenerTwo).onServiceNameDiscovered(
verify(mockListenerTwo).onServiceFound(matchServiceName(otherInstance)); matchServiceName(otherInstance), eq(false) /* isServiceFromCache */);
verify(mockListenerTwo).onServiceFound(
matchServiceName(otherInstance), eq(false) /* isServiceFromCache */);
verify(mockListenerTwo).onServiceRemoved(matchServiceName(otherInstance)); verify(mockListenerTwo).onServiceRemoved(matchServiceName(otherInstance));
verify(mockListenerTwo).onServiceNameRemoved(matchServiceName(otherInstance)); verify(mockListenerTwo).onServiceNameRemoved(matchServiceName(otherInstance));
} }
@@ -1547,7 +1580,8 @@ public class MdnsServiceTypeClientTests {
socketKey); socketKey);
// Verify that onServiceNameDiscovered is called. // Verify that onServiceNameDiscovered is called.
inOrder.verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture()); inOrder.verify(mockListenerOne).onServiceNameDiscovered(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
serviceName, serviceName,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -1559,7 +1593,8 @@ public class MdnsServiceTypeClientTests {
socketKey); socketKey);
// Verify that onServiceFound is called. // Verify that onServiceFound is called.
inOrder.verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture()); inOrder.verify(mockListenerOne).onServiceFound(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(1), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(1),
serviceName, serviceName,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -1581,7 +1616,8 @@ public class MdnsServiceTypeClientTests {
// The services are cached in MdnsServiceCache, verify that onServiceNameDiscovered is // The services are cached in MdnsServiceCache, verify that onServiceNameDiscovered is
// called immediately. // called immediately.
inOrder2.verify(mockListenerTwo).onServiceNameDiscovered(serviceInfoCaptor.capture()); inOrder2.verify(mockListenerTwo).onServiceNameDiscovered(
serviceInfoCaptor.capture(), eq(true) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(2), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(2),
serviceName, serviceName,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
@@ -1594,7 +1630,8 @@ public class MdnsServiceTypeClientTests {
// The services are cached in MdnsServiceCache, verify that onServiceFound is // The services are cached in MdnsServiceCache, verify that onServiceFound is
// called immediately. // called immediately.
inOrder2.verify(mockListenerTwo).onServiceFound(serviceInfoCaptor.capture()); inOrder2.verify(mockListenerTwo).onServiceFound(
serviceInfoCaptor.capture(), eq(true) /* isServiceFromCache */);
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(3), verifyServiceInfo(serviceInfoCaptor.getAllValues().get(3),
serviceName, serviceName,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,