diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java index b4f889786d..36808cfc21 100644 --- a/framework-t/src/android/net/nsd/NsdManager.java +++ b/framework-t/src/android/net/nsd/NsdManager.java @@ -1312,7 +1312,7 @@ public final class NsdManager { * before registering other callbacks. Upon failure to register a callback for example if * it's a duplicated registration, the application is notified through * {@link ServiceInfoCallback#onServiceInfoCallbackRegistrationFailed} with - * {@link #FAILURE_BAD_PARAMETERS} or {@link #FAILURE_ALREADY_ACTIVE}. + * {@link #FAILURE_BAD_PARAMETERS}. * * @param serviceInfo the service to receive updates for * @param executor Executor to run callbacks with diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java index 619b64d851..8b70a94c96 100644 --- a/service-t/src/com/android/server/NsdService.java +++ b/service-t/src/com/android/server/NsdService.java @@ -84,7 +84,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -265,6 +264,35 @@ public class NsdService extends INsdManager.Stub { } } + private class ServiceInfoListener extends MdnsListener { + + ServiceInfoListener(int clientId, int transactionId, @NonNull NsdServiceInfo reqServiceInfo, + @NonNull String listenServiceType) { + super(clientId, transactionId, reqServiceInfo, listenServiceType); + } + + @Override + public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo) { + mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId, + NsdManager.SERVICE_UPDATED, + new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo)); + } + + @Override + public void onServiceUpdated(@NonNull MdnsServiceInfo serviceInfo) { + mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId, + NsdManager.SERVICE_UPDATED, + new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo)); + } + + @Override + public void onServiceRemoved(@NonNull MdnsServiceInfo serviceInfo) { + mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId, + NsdManager.SERVICE_UPDATED_LOST, + new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo)); + } + } + /** * Data class of mdns service callback information. */ @@ -521,12 +549,6 @@ public class NsdService extends INsdManager.Stub { mIdToClientInfoMap.put(globalId, clientInfo); } - private void clearRegisteredServiceInfo(ClientInfo clientInfo) { - clientInfo.mRegisteredService = null; - clientInfo.mClientIdForServiceUpdates = 0; - } - - /** * Truncate a service name to up to 63 UTF-8 bytes. * @@ -832,7 +854,7 @@ public class NsdService extends INsdManager.Stub { } break; } - case NsdManager.REGISTER_SERVICE_CALLBACK: + case NsdManager.REGISTER_SERVICE_CALLBACK: { if (DBG) Log.d(TAG, "Register a service callback"); args = (ListenerArgs) msg.obj; clientInfo = mClients.get(args.connector); @@ -844,23 +866,29 @@ public class NsdService extends INsdManager.Stub { break; } - if (clientInfo.mRegisteredService != null) { - clientInfo.onServiceInfoCallbackRegistrationFailed( - clientId, NsdManager.FAILURE_ALREADY_ACTIVE); + final NsdServiceInfo info = args.serviceInfo; + id = getUniqueId(); + final String serviceType = constructServiceType(info.getServiceType()); + if (serviceType == null) { + clientInfo.onServiceInfoCallbackRegistrationFailed(clientId, + NsdManager.FAILURE_BAD_PARAMETERS); break; } + final String resolveServiceType = serviceType + ".local"; - maybeStartDaemon(); - id = getUniqueId(); - if (resolveService(id, args.serviceInfo)) { - clientInfo.mRegisteredService = new NsdServiceInfo(); - clientInfo.mClientIdForServiceUpdates = clientId; - storeLegacyRequestMap(clientId, id, clientInfo, msg.what); - } else { - clientInfo.onServiceInfoCallbackRegistrationFailed( - clientId, NsdManager.FAILURE_BAD_PARAMETERS); - } + maybeStartMonitoringSockets(); + final MdnsListener listener = + new ServiceInfoListener(clientId, id, info, resolveServiceType); + final MdnsSearchOptions options = MdnsSearchOptions.newBuilder() + .setNetwork(info.getNetwork()) + .setIsPassiveMode(true) + .setResolveInstanceName(info.getServiceName()) + .build(); + mMdnsDiscoveryManager.registerListener( + resolveServiceType, listener, options); + storeDiscoveryManagerRequestMap(clientId, id, listener, clientInfo); break; + } case NsdManager.UNREGISTER_SERVICE_CALLBACK: { if (DBG) Log.d(TAG, "Unregister a service callback"); args = (ListenerArgs) msg.obj; @@ -875,17 +903,16 @@ public class NsdService extends INsdManager.Stub { final ClientRequest request = clientInfo.mClientRequests.get(clientId); if (request == null) { - Log.e(TAG, "Unknown client request in STOP_RESOLUTION"); + Log.e(TAG, "Unknown client request in UNREGISTER_SERVICE_CALLBACK"); break; } id = request.mGlobalId; - removeRequestMap(clientId, id, clientInfo); - if (stopResolveService(id)) { + if (request instanceof DiscoveryManagerRequest) { + stopDiscoveryManagerRequest(request, clientId, id, clientInfo); clientInfo.onServiceInfoCallbackUnregistered(clientId); } else { - Log.e(TAG, "Failed to unregister service info callback"); + loge("Unregister failed with non-DiscoveryManagerRequest."); } - clearRegisteredServiceInfo(clientInfo); break; } case MDNS_SERVICE_EVENT: @@ -904,19 +931,6 @@ public class NsdService extends INsdManager.Stub { return HANDLED; } - private void notifyResolveFailedResult(boolean isListenedToUpdates, int clientId, - ClientInfo clientInfo, int error) { - if (isListenedToUpdates) { - clientInfo.onServiceInfoCallbackRegistrationFailed(clientId, error); - clearRegisteredServiceInfo(clientInfo); - } else { - // The resolve API always returned FAILURE_INTERNAL_ERROR on error; keep it - // for backwards compatibility. - clientInfo.onResolveServiceFailed(clientId, NsdManager.FAILURE_INTERNAL_ERROR); - clientInfo.mResolvedService = null; - } - } - private boolean handleMDnsServiceEvent(int code, int id, Object obj) { NsdServiceInfo servInfo; ClientInfo clientInfo = mIdToClientInfoMap.get(id); @@ -973,8 +987,6 @@ public class NsdService extends INsdManager.Stub { // found services on the same interface index and their network at the time setServiceNetworkForCallback(servInfo, lostNetId, info.interfaceIdx); clientInfo.onServiceLost(clientId, servInfo); - // TODO: also support registered service lost when not discovering - clientInfo.maybeNotifyRegisteredServiceLost(servInfo); break; } case IMDnsEventListener.SERVICE_DISCOVERY_FAILED: @@ -1011,11 +1023,7 @@ public class NsdService extends INsdManager.Stub { String rest = fullName.substring(index); String type = rest.replace(".local.", ""); - final boolean isListenedToUpdates = - clientId == clientInfo.mClientIdForServiceUpdates; - final NsdServiceInfo serviceInfo = isListenedToUpdates - ? clientInfo.mRegisteredService : clientInfo.mResolvedService; - + final NsdServiceInfo serviceInfo = clientInfo.mResolvedService; serviceInfo.setServiceName(name); serviceInfo.setServiceType(type); serviceInfo.setPort(info.port); @@ -1030,8 +1038,9 @@ public class NsdService extends INsdManager.Stub { storeLegacyRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE); } else { - notifyResolveFailedResult(isListenedToUpdates, clientId, clientInfo, - NsdManager.FAILURE_BAD_PARAMETERS); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.mResolvedService = null; } break; } @@ -1039,17 +1048,17 @@ public class NsdService extends INsdManager.Stub { /* NNN resolveId errorCode */ stopResolveService(id); removeRequestMap(clientId, id, clientInfo); - notifyResolveFailedResult( - clientId == clientInfo.mClientIdForServiceUpdates, - clientId, clientInfo, NsdManager.FAILURE_BAD_PARAMETERS); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.mResolvedService = null; break; case IMDnsEventListener.SERVICE_GET_ADDR_FAILED: /* NNN resolveId errorCode */ stopGetAddrInfo(id); removeRequestMap(clientId, id, clientInfo); - notifyResolveFailedResult( - clientId == clientInfo.mClientIdForServiceUpdates, - clientId, clientInfo, NsdManager.FAILURE_BAD_PARAMETERS); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.mResolvedService = null; break; case IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS: { /* NNN resolveId hostname ttl addr interfaceIdx netId */ @@ -1066,38 +1075,19 @@ public class NsdService extends INsdManager.Stub { // If the resolved service is on an interface without a network, consider it // as a failure: it would not be usable by apps as they would need // privileged permissions. - if (clientId == clientInfo.mClientIdForServiceUpdates) { - if (netId != NETID_UNSET && serviceHost != null) { - setServiceNetworkForCallback(clientInfo.mRegisteredService, - netId, info.interfaceIdx); - final List addresses = - clientInfo.mRegisteredService.getHostAddresses(); - addresses.add(serviceHost); - clientInfo.mRegisteredService.setHostAddresses(addresses); - clientInfo.onServiceUpdated( - clientId, clientInfo.mRegisteredService); - } else { - stopGetAddrInfo(id); - removeRequestMap(clientId, id, clientInfo); - clearRegisteredServiceInfo(clientInfo); - clientInfo.onServiceInfoCallbackRegistrationFailed( - clientId, NsdManager.FAILURE_BAD_PARAMETERS); - } + if (netId != NETID_UNSET && serviceHost != null) { + clientInfo.mResolvedService.setHost(serviceHost); + setServiceNetworkForCallback(clientInfo.mResolvedService, + netId, info.interfaceIdx); + clientInfo.onResolveServiceSucceeded( + clientId, clientInfo.mResolvedService); } else { - if (netId != NETID_UNSET && serviceHost != null) { - clientInfo.mResolvedService.setHost(serviceHost); - setServiceNetworkForCallback(clientInfo.mResolvedService, - netId, info.interfaceIdx); - clientInfo.onResolveServiceSucceeded( - clientId, clientInfo.mResolvedService); - } else { - clientInfo.onResolveServiceFailed( - clientId, NsdManager.FAILURE_INTERNAL_ERROR); - } - stopGetAddrInfo(id); - removeRequestMap(clientId, id, clientInfo); - clientInfo.mResolvedService = null; + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } + stopGetAddrInfo(id); + removeRequestMap(clientId, id, clientInfo); + clientInfo.mResolvedService = null; break; } default: @@ -1195,6 +1185,42 @@ public class NsdService extends INsdManager.Stub { stopDiscoveryManagerRequest(request, clientId, transactionId, clientInfo); break; } + case NsdManager.SERVICE_UPDATED: { + final MdnsServiceInfo serviceInfo = event.mMdnsServiceInfo; + info.setPort(serviceInfo.getPort()); + + Map attrs = serviceInfo.getAttributes(); + for (Map.Entry kv : attrs.entrySet()) { + final String key = kv.getKey(); + try { + info.setAttribute(key, serviceInfo.getAttributeAsBytes(key)); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Invalid attribute", e); + } + } + + final List addresses = new ArrayList<>(); + for (String ipv4Address : serviceInfo.getIpv4Addresses()) { + try { + addresses.add(InetAddresses.parseNumericAddress(ipv4Address)); + } catch (IllegalArgumentException e) { + Log.wtf(TAG, "Invalid ipv4 address", e); + } + } + for (String ipv6Address : serviceInfo.getIpv6Addresses()) { + try { + addresses.add(InetAddresses.parseNumericAddress(ipv6Address)); + } catch (IllegalArgumentException e) { + Log.wtf(TAG, "Invalid ipv6 address", e); + } + } + info.setHostAddresses(addresses); + clientInfo.onServiceUpdated(clientId, info); + break; + } + case NsdManager.SERVICE_UPDATED_LOST: + clientInfo.onServiceUpdatedLost(clientId); + break; default: return false; } @@ -1765,11 +1791,6 @@ public class NsdService extends INsdManager.Stub { // The target SDK of this client < Build.VERSION_CODES.S private boolean mIsPreSClient = false; - /*** The service that is registered to listen to its updates */ - private NsdServiceInfo mRegisteredService; - /*** The client id that listen to updates */ - private int mClientIdForServiceUpdates; - private ClientInfo(INsdManagerCallback cb) { mCb = cb; if (DBG) Log.d(TAG, "New client"); @@ -1864,18 +1885,6 @@ public class NsdService extends INsdManager.Stub { return -1; } - private void maybeNotifyRegisteredServiceLost(@NonNull NsdServiceInfo info) { - if (mRegisteredService == null) return; - if (!Objects.equals(mRegisteredService.getServiceName(), info.getServiceName())) return; - // Resolved services have a leading dot appended at the beginning of their type, but in - // discovered info it's at the end - if (!Objects.equals( - mRegisteredService.getServiceType() + ".", "." + info.getServiceType())) { - return; - } - onServiceUpdatedLost(mClientIdForServiceUpdates); - } - void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) { try { mCb.onDiscoverServicesStarted(listenerKey, info); diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt index de5e46f319..408c54647b 100644 --- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt +++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt @@ -879,7 +879,7 @@ class NsdManagerTest { @Test fun testRegisterServiceInfoCallback() { - // This test requires shims supporting U+ APIs (NsdManager.subscribeService) + // This test requires shims supporting U+ APIs (NsdManager.registerServiceInfoCallback) assumeTrue(TestUtils.shouldTestUApis()) // Ensure Wi-Fi network connected and get addresses @@ -909,16 +909,14 @@ class NsdManagerTest { val foundInfo = discoveryRecord.waitForServiceDiscovered( serviceName, wifiNetwork) - // Subscribe to service and check the addresses are the same as Wi-Fi addresses + // Register service callback and check the addresses are the same as Wi-Fi addresses nsdShim.registerServiceInfoCallback(nsdManager, foundInfo, { it.run() }, cbRecord) - for (i in addresses.indices) { - val subscribeCb = cbRecord.expectCallback() - assertEquals(foundInfo.serviceName, subscribeCb.serviceInfo.serviceName) - val hostAddresses = subscribeCb.serviceInfo.hostAddresses - assertEquals(i + 1, hostAddresses.size) - for (hostAddress in hostAddresses) { - assertTrue(addresses.contains(hostAddress)) - } + val serviceInfoCb = cbRecord.expectCallback() + assertEquals(foundInfo.serviceName, serviceInfoCb.serviceInfo.serviceName) + val hostAddresses = serviceInfoCb.serviceInfo.hostAddresses + assertEquals(addresses.size, hostAddresses.size) + for (hostAddress in hostAddresses) { + assertTrue(addresses.contains(hostAddress)) } } cleanupStep { nsdManager.unregisterService(registrationRecord) diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java index 3dc5647cc9..0b48e08dc2 100644 --- a/tests/unit/java/com/android/server/NsdServiceTest.java +++ b/tests/unit/java/com/android/server/NsdServiceTest.java @@ -101,6 +101,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.net.InetAddress; import java.net.UnknownHostException; import java.util.LinkedList; import java.util.List; @@ -704,119 +705,102 @@ public class NsdServiceTest { } private void verifyUpdatedServiceInfo(NsdServiceInfo info, String serviceName, - String serviceType, String address, int port, int interfaceIndex, Network network) { + String serviceType, List address, int port, int interfaceIndex, + Network network) { assertEquals(serviceName, info.getServiceName()); assertEquals(serviceType, info.getServiceType()); - assertTrue(info.getHostAddresses().contains(parseNumericAddress(address))); + assertEquals(address, info.getHostAddresses()); assertEquals(port, info.getPort()); assertEquals(network, info.getNetwork()); assertEquals(interfaceIndex, info.getInterfaceIndex()); } @Test - public void testRegisterAndUnregisterServiceInfoCallback() throws RemoteException { + public void testRegisterAndUnregisterServiceInfoCallback() { final NsdManager client = connectClient(mService); final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE); final NsdManager.ServiceInfoCallback serviceInfoCallback = mock( NsdManager.ServiceInfoCallback.class); + final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local"; + final Network network = new Network(999); + request.setNetwork(network); client.registerServiceInfoCallback(request, Runnable::run, serviceInfoCallback); waitForIdle(); + // Verify the registration callback start. + final ArgumentCaptor listenerCaptor = + ArgumentCaptor.forClass(MdnsServiceBrowserListener.class); + verify(mSocketProvider).startMonitoringSockets(); + verify(mDiscoveryManager).registerListener(eq(serviceTypeWithLocalDomain), + listenerCaptor.capture(), argThat(options -> network.equals(options.getNetwork()))); - final IMDnsEventListener eventListener = getEventListener(); - final ArgumentCaptor resolvIdCaptor = ArgumentCaptor.forClass(Integer.class); - verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE), - eq("local.") /* domain */, eq(IFACE_IDX_ANY)); - - // Resolve service successfully. - final ResolutionInfo resolutionInfo = new ResolutionInfo( - resolvIdCaptor.getValue(), - IMDnsEventListener.SERVICE_RESOLVED, - null /* serviceName */, - null /* serviceType */, - null /* domain */, - SERVICE_FULL_NAME, - DOMAIN_NAME, + final MdnsServiceBrowserListener listener = listenerCaptor.getValue(); + final MdnsServiceInfo mdnsServiceInfo = new MdnsServiceInfo( + SERVICE_NAME, + serviceTypeWithLocalDomain.split("\\."), + List.of(), /* subtypes */ + new String[]{"android", "local"}, /* hostName */ PORT, - new byte[0] /* txtRecord */, - IFACE_IDX_ANY); - doReturn(true).when(mMockMDnsM).getServiceAddress(anyInt(), any(), anyInt()); - eventListener.onServiceResolutionStatus(resolutionInfo); - waitForIdle(); - - final ArgumentCaptor getAddrIdCaptor = ArgumentCaptor.forClass(Integer.class); - verify(mMockMDnsM).getServiceAddress(getAddrIdCaptor.capture(), eq(DOMAIN_NAME), - eq(IFACE_IDX_ANY)); - - // First address info - final String v4Address = "192.0.2.1"; - final String v6Address = "2001:db8::"; - final GetAddressInfo addressInfo1 = new GetAddressInfo( - getAddrIdCaptor.getValue(), - IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS, - SERVICE_FULL_NAME, - v4Address, - IFACE_IDX_ANY, - 999 /* netId */); - eventListener.onGettingServiceAddressStatus(addressInfo1); - waitForIdle(); + List.of(IPV4_ADDRESS), + List.of(IPV6_ADDRESS), + List.of() /* textStrings */, + List.of() /* textEntries */, + 1234, + network); + // Verify onServiceFound callback + listener.onServiceFound(mdnsServiceInfo); final ArgumentCaptor updateInfoCaptor = ArgumentCaptor.forClass(NsdServiceInfo.class); verify(serviceInfoCallback, timeout(TIMEOUT_MS).times(1)) .onServiceUpdated(updateInfoCaptor.capture()); verifyUpdatedServiceInfo(updateInfoCaptor.getAllValues().get(0) /* info */, SERVICE_NAME, - "." + SERVICE_TYPE, v4Address, PORT, IFACE_IDX_ANY, new Network(999)); + SERVICE_TYPE, + List.of(parseNumericAddress(IPV4_ADDRESS), parseNumericAddress(IPV6_ADDRESS)), + PORT, IFACE_IDX_ANY, new Network(999)); - // Second address info - final GetAddressInfo addressInfo2 = new GetAddressInfo( - getAddrIdCaptor.getValue(), - IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS, - SERVICE_FULL_NAME, - v6Address, - IFACE_IDX_ANY, - 999 /* netId */); - eventListener.onGettingServiceAddressStatus(addressInfo2); - waitForIdle(); + // Service addresses changed. + final String v4Address = "192.0.2.1"; + final String v6Address = "2001:db8::1"; + final MdnsServiceInfo updatedServiceInfo = new MdnsServiceInfo( + SERVICE_NAME, + serviceTypeWithLocalDomain.split("\\."), + List.of(), /* subtypes */ + new String[]{"android", "local"}, /* hostName */ + PORT, + List.of(v4Address), + List.of(v6Address), + List.of() /* textStrings */, + List.of() /* textEntries */, + 1234, + network); + // Verify onServiceUpdated callback. + listener.onServiceUpdated(updatedServiceInfo); verify(serviceInfoCallback, timeout(TIMEOUT_MS).times(2)) .onServiceUpdated(updateInfoCaptor.capture()); - verifyUpdatedServiceInfo(updateInfoCaptor.getAllValues().get(1) /* info */, SERVICE_NAME, - "." + SERVICE_TYPE, v6Address, PORT, IFACE_IDX_ANY, new Network(999)); + verifyUpdatedServiceInfo(updateInfoCaptor.getAllValues().get(2) /* info */, SERVICE_NAME, + SERVICE_TYPE, + List.of(parseNumericAddress(v4Address), parseNumericAddress(v6Address)), + PORT, IFACE_IDX_ANY, new Network(999)); + // Verify service callback unregistration. client.unregisterServiceInfoCallback(serviceInfoCallback); waitForIdle(); - verify(serviceInfoCallback, timeout(TIMEOUT_MS)).onServiceInfoCallbackUnregistered(); } @Test - public void testRegisterServiceCallbackFailed() throws Exception { + public void testRegisterServiceCallbackFailed() { final NsdManager client = connectClient(mService); - final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE); - final NsdManager.ServiceInfoCallback subscribeListener = mock( + final String invalidServiceType = "a_service"; + final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, invalidServiceType); + final NsdManager.ServiceInfoCallback serviceInfoCallback = mock( NsdManager.ServiceInfoCallback.class); - client.registerServiceInfoCallback(request, Runnable::run, subscribeListener); + client.registerServiceInfoCallback(request, Runnable::run, serviceInfoCallback); waitForIdle(); - final IMDnsEventListener eventListener = getEventListener(); - final ArgumentCaptor resolvIdCaptor = ArgumentCaptor.forClass(Integer.class); - verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE), - eq("local.") /* domain */, eq(IFACE_IDX_ANY)); - - // Fail to resolve service. - final ResolutionInfo resolutionFailedInfo = new ResolutionInfo( - resolvIdCaptor.getValue(), - IMDnsEventListener.SERVICE_RESOLUTION_FAILED, - null /* serviceName */, - null /* serviceType */, - null /* domain */, - null /* serviceFullName */, - null /* domainName */, - 0 /* port */, - new byte[0] /* txtRecord */, - IFACE_IDX_ANY); - eventListener.onServiceResolutionStatus(resolutionFailedInfo); - verify(subscribeListener, timeout(TIMEOUT_MS)) + // Fail to register service callback. + verify(serviceInfoCallback, timeout(TIMEOUT_MS)) .onServiceInfoCallbackRegistrationFailed(eq(FAILURE_BAD_PARAMETERS)); }