Do not immediately send new queries on cache hit

If a listener request is fulfilled immediately from cache, do not
restart queries immediately, but just schedule the next run.

This avoids doubling the number of queries when discovery, then resolve
is requested.

Bug: 281793453
Test: atest
(cherry picked from https://android-review.googlesource.com/q/commit:58bb0a129a4eb1f19904265104af2a14db248cb3)
Merged-In: Ibe41ee20427068a1ccdbc1f04525988a89a58899
Change-Id: Ibe41ee20427068a1ccdbc1f04525988a89a58899
This commit is contained in:
Remi NGUYEN VAN
2023-05-12 16:10:25 +09:00
committed by Cherrypicker Worker
parent 20e768a2f3
commit ededb1337e
2 changed files with 48 additions and 12 deletions

View File

@@ -175,6 +175,7 @@ public class MdnsServiceTypeClient {
@NonNull MdnsSearchOptions searchOptions) { @NonNull MdnsSearchOptions searchOptions) {
synchronized (lock) { synchronized (lock) {
this.searchOptions = searchOptions; this.searchOptions = searchOptions;
boolean hadReply = false;
if (listeners.put(listener, searchOptions) == null) { if (listeners.put(listener, searchOptions) == null) {
for (MdnsResponse existingResponse : instanceNameToResponse.values()) { for (MdnsResponse existingResponse : instanceNameToResponse.values()) {
if (!responseMatchesOptions(existingResponse, searchOptions)) continue; if (!responseMatchesOptions(existingResponse, searchOptions)) continue;
@@ -183,6 +184,7 @@ public class MdnsServiceTypeClient {
listener.onServiceNameDiscovered(info); listener.onServiceNameDiscovered(info);
if (existingResponse.isComplete()) { if (existingResponse.isComplete()) {
listener.onServiceFound(info); listener.onServiceFound(info);
hadReply = true;
} }
} }
} }
@@ -192,14 +194,16 @@ public class MdnsServiceTypeClient {
} }
// Keep tracking the ScheduledFuture for the task so we can cancel it if caller is not // Keep tracking the ScheduledFuture for the task so we can cancel it if caller is not
// interested anymore. // interested anymore.
requestTaskFuture = final QueryTaskConfig taskConfig = new QueryTaskConfig(
executor.submit(
new QueryTask(
new QueryTaskConfig(
searchOptions.getSubtypes(), searchOptions.getSubtypes(),
searchOptions.isPassiveMode(), searchOptions.isPassiveMode(),
++currentSessionId, ++currentSessionId,
searchOptions.getNetwork()))); searchOptions.getNetwork());
if (hadReply) {
requestTaskFuture = scheduleNextRunLocked(taskConfig);
} else {
requestTaskFuture = executor.submit(new QueryTask(taskConfig));
}
} }
} }
@@ -552,11 +556,14 @@ public class MdnsServiceTypeClient {
} }
} }
} }
QueryTaskConfig config = this.config.getConfigForNextRun(); requestTaskFuture = scheduleNextRunLocked(this.config);
requestTaskFuture =
executor.schedule(
new QueryTask(config), config.timeToRunNextTaskInMs, MILLISECONDS);
} }
} }
} }
@NonNull
private Future<?> scheduleNextRunLocked(@NonNull QueryTaskConfig lastRunConfig) {
QueryTaskConfig config = lastRunConfig.getConfigForNextRun();
return executor.schedule(new QueryTask(config), config.timeToRunNextTaskInMs, MILLISECONDS);
}
} }

View File

@@ -21,6 +21,7 @@ import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
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;
@@ -422,6 +423,34 @@ public class MdnsServiceTypeClientTests {
assertNull(currentThreadExecutor.getAndClearLastScheduledRunnable()); assertNull(currentThreadExecutor.getAndClearLastScheduledRunnable());
} }
@Test
public void testQueryScheduledWhenAnsweredFromCache() {
final MdnsSearchOptions searchOptions = MdnsSearchOptions.getDefaultOptions();
client.startSendAndReceive(mockListenerOne, searchOptions);
assertNotNull(currentThreadExecutor.getAndClearSubmittedRunnable());
client.processResponse(createResponse(
"service-instance-1", "192.0.2.123", 5353,
SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), /* interfaceIndex= */ 20, mockNetwork);
verify(mockListenerOne).onServiceNameDiscovered(any());
verify(mockListenerOne).onServiceFound(any());
// File another identical query
client.startSendAndReceive(mockListenerTwo, searchOptions);
verify(mockListenerTwo).onServiceNameDiscovered(any());
verify(mockListenerTwo).onServiceFound(any());
// This time no query is submitted, only scheduled
assertNull(currentThreadExecutor.getAndClearSubmittedRunnable());
assertNotNull(currentThreadExecutor.getAndClearLastScheduledRunnable());
// This just skips the first query of the first burst
assertEquals(MdnsConfigs.timeBetweenQueriesInBurstMs(),
currentThreadExecutor.getAndClearLastScheduledDelayInMs());
}
private static void verifyServiceInfo(MdnsServiceInfo serviceInfo, String serviceName, private static void verifyServiceInfo(MdnsServiceInfo serviceInfo, String serviceName,
String[] serviceType, List<String> ipv4Addresses, List<String> ipv6Addresses, int port, String[] serviceType, List<String> ipv4Addresses, List<String> ipv6Addresses, int port,
List<String> subTypes, Map<String, String> attributes, int interfaceIndex, List<String> subTypes, Map<String, String> attributes, int interfaceIndex,