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 4cb88b424f..e222fcfdb8 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java @@ -140,8 +140,7 @@ public class MdnsServiceTypeClient { // before sending the query, it needs to be called just before sending it. final List servicesToResolve = makeResponsesForResolve(socketKey); final QueryTask queryTask = new QueryTask(taskArgs, servicesToResolve, - getAllDiscoverySubtypes(), - servicesToResolve.size() < listeners.size() /* sendDiscoveryQueries */); + getAllDiscoverySubtypes(), needSendDiscoveryQueries(listeners)); executor.submit(queryTask); break; } @@ -388,8 +387,7 @@ public class MdnsServiceTypeClient { final QueryTask queryTask = new QueryTask( mdnsQueryScheduler.scheduleFirstRun(taskConfig, now, minRemainingTtl, currentSessionId), servicesToResolve, - getAllDiscoverySubtypes(), - servicesToResolve.size() < listeners.size() /* sendDiscoveryQueries */); + getAllDiscoverySubtypes(), needSendDiscoveryQueries(listeners)); executor.submit(queryTask); } @@ -627,6 +625,10 @@ public class MdnsServiceTypeClient { if (resolveName == null) { continue; } + if (CollectionUtils.any(resolveResponses, + r -> MdnsUtils.equalsIgnoreDnsCase(resolveName, r.getServiceInstanceName()))) { + continue; + } MdnsResponse knownResponse = serviceCache.getCachedService(resolveName, cacheKey); if (knownResponse == null) { @@ -643,6 +645,17 @@ public class MdnsServiceTypeClient { return resolveResponses; } + private static boolean needSendDiscoveryQueries( + @NonNull ArrayMap listeners) { + // Note iterators are discouraged on ArrayMap as per its documentation + for (int i = 0; i < listeners.size(); i++) { + if (listeners.valueAt(i).searchOptions.getResolveInstanceName() == null) { + return true; + } + } + return false; + } + private void tryRemoveServiceAfterTtlExpires() { if (!shouldRemoveServiceAfterTtlExpires()) return; diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java index 58124f3dff..09236b1764 100644 --- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java +++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java @@ -43,6 +43,7 @@ import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static java.nio.charset.StandardCharsets.UTF_8; @@ -1207,10 +1208,14 @@ public class MdnsServiceTypeClientTests { final String ipV4Address = "192.0.2.0"; final String ipV6Address = "2001:db8::"; - final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder() + final MdnsSearchOptions resolveOptions1 = MdnsSearchOptions.newBuilder() + .setResolveInstanceName(instanceName).build(); + final MdnsSearchOptions resolveOptions2 = MdnsSearchOptions.newBuilder() .setResolveInstanceName(instanceName).build(); - startSendAndReceive(mockListenerOne, resolveOptions); + startSendAndReceive(mockListenerOne, resolveOptions1); + startSendAndReceive(mockListenerTwo, resolveOptions2); + // No need to verify order for both listeners; and order is not guaranteed between them InOrder inOrder = inOrder(mockListenerOne, mockSocketClient); // Verify a query for SRV/TXT was sent, but no PTR query @@ -1223,13 +1228,19 @@ public class MdnsServiceTypeClientTests { eq(socketKey), eq(false)); verify(mockDeps, times(1)).sendMessage(any(), any(Message.class)); assertNotNull(delayMessage); + inOrder.verify(mockListenerOne).onDiscoveryQuerySent(any(), anyInt()); + verify(mockListenerTwo).onDiscoveryQuerySent(any(), anyInt()); final MdnsPacket srvTxtQueryPacket = MdnsPacket.parse( new MdnsPacketReader(srvTxtQueryCaptor.getValue())); final String[] serviceName = getTestServiceName(instanceName); + assertEquals(1, srvTxtQueryPacket.questions.size()); assertFalse(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_PTR)); assertTrue(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_ANY, serviceName)); + assertEquals(0, srvTxtQueryPacket.answers.size()); + assertEquals(0, srvTxtQueryPacket.authorityRecords.size()); + assertEquals(0, srvTxtQueryPacket.additionalRecords.size()); // Process a response with SRV+TXT final MdnsPacket srvTxtResponse = new MdnsPacket( @@ -1246,6 +1257,10 @@ public class MdnsServiceTypeClientTests { Collections.emptyList() /* additionalRecords */); processResponse(srvTxtResponse, socketKey); + inOrder.verify(mockListenerOne).onServiceNameDiscovered( + matchServiceName(instanceName), eq(false) /* isServiceFromCache */); + verify(mockListenerTwo).onServiceNameDiscovered( + matchServiceName(instanceName), eq(false) /* isServiceFromCache */); // Expect a query for A/AAAA dispatchMessage(); @@ -1255,11 +1270,18 @@ public class MdnsServiceTypeClientTests { inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingMulticastResponse( addressQueryCaptor.capture(), eq(socketKey), eq(false)); + inOrder.verify(mockListenerOne).onDiscoveryQuerySent(any(), anyInt()); + // onDiscoveryQuerySent was called 2 times in total + verify(mockListenerTwo, times(2)).onDiscoveryQuerySent(any(), anyInt()); final MdnsPacket addressQueryPacket = MdnsPacket.parse( new MdnsPacketReader(addressQueryCaptor.getValue())); + assertEquals(2, addressQueryPacket.questions.size()); assertTrue(hasQuestion(addressQueryPacket, MdnsRecord.TYPE_A, hostname)); assertTrue(hasQuestion(addressQueryPacket, MdnsRecord.TYPE_AAAA, hostname)); + assertEquals(0, addressQueryPacket.answers.size()); + assertEquals(0, addressQueryPacket.authorityRecords.size()); + assertEquals(0, addressQueryPacket.additionalRecords.size()); // Process a response with address records final MdnsPacket addressResponse = new MdnsPacket( @@ -1276,10 +1298,12 @@ public class MdnsServiceTypeClientTests { Collections.emptyList() /* additionalRecords */); inOrder.verify(mockListenerOne, never()).onServiceNameDiscovered(any(), anyBoolean()); + verifyNoMoreInteractions(mockListenerTwo); processResponse(addressResponse, socketKey); inOrder.verify(mockListenerOne).onServiceFound( serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */); + verify(mockListenerTwo).onServiceFound(any(), anyBoolean()); verifyServiceInfo(serviceInfoCaptor.getValue(), instanceName, SERVICE_TYPE_LABELS,