Merge "Adjust query frequency based on remaining TTL"
This commit is contained in:
@@ -50,7 +50,8 @@ public class MdnsSearchOptions implements Parcelable {
|
|||||||
source.readBoolean(),
|
source.readBoolean(),
|
||||||
source.readParcelable(null),
|
source.readParcelable(null),
|
||||||
source.readString(),
|
source.readString(),
|
||||||
(source.dataAvail() > 0) ? source.readBoolean() : false);
|
source.readBoolean(),
|
||||||
|
source.readInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -62,9 +63,9 @@ public class MdnsSearchOptions implements Parcelable {
|
|||||||
private final List<String> subtypes;
|
private final List<String> subtypes;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String resolveInstanceName;
|
private final String resolveInstanceName;
|
||||||
|
|
||||||
private final boolean isPassiveMode;
|
private final boolean isPassiveMode;
|
||||||
private final boolean onlyUseIpv6OnIpv6OnlyNetworks;
|
private final boolean onlyUseIpv6OnIpv6OnlyNetworks;
|
||||||
|
private final int numOfQueriesBeforeBackoff;
|
||||||
private final boolean removeExpiredService;
|
private final boolean removeExpiredService;
|
||||||
// The target network for searching. Null network means search on all possible interfaces.
|
// The target network for searching. Null network means search on all possible interfaces.
|
||||||
@Nullable private final Network mNetwork;
|
@Nullable private final Network mNetwork;
|
||||||
@@ -76,13 +77,15 @@ public class MdnsSearchOptions implements Parcelable {
|
|||||||
boolean removeExpiredService,
|
boolean removeExpiredService,
|
||||||
@Nullable Network network,
|
@Nullable Network network,
|
||||||
@Nullable String resolveInstanceName,
|
@Nullable String resolveInstanceName,
|
||||||
boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
boolean onlyUseIpv6OnIpv6OnlyNetworks,
|
||||||
|
int numOfQueriesBeforeBackoff) {
|
||||||
this.subtypes = new ArrayList<>();
|
this.subtypes = new ArrayList<>();
|
||||||
if (subtypes != null) {
|
if (subtypes != null) {
|
||||||
this.subtypes.addAll(subtypes);
|
this.subtypes.addAll(subtypes);
|
||||||
}
|
}
|
||||||
this.isPassiveMode = isPassiveMode;
|
this.isPassiveMode = isPassiveMode;
|
||||||
this.onlyUseIpv6OnIpv6OnlyNetworks = onlyUseIpv6OnIpv6OnlyNetworks;
|
this.onlyUseIpv6OnIpv6OnlyNetworks = onlyUseIpv6OnIpv6OnlyNetworks;
|
||||||
|
this.numOfQueriesBeforeBackoff = numOfQueriesBeforeBackoff;
|
||||||
this.removeExpiredService = removeExpiredService;
|
this.removeExpiredService = removeExpiredService;
|
||||||
mNetwork = network;
|
mNetwork = network;
|
||||||
this.resolveInstanceName = resolveInstanceName;
|
this.resolveInstanceName = resolveInstanceName;
|
||||||
@@ -122,6 +125,14 @@ public class MdnsSearchOptions implements Parcelable {
|
|||||||
return onlyUseIpv6OnIpv6OnlyNetworks;
|
return onlyUseIpv6OnIpv6OnlyNetworks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of queries should be executed before backoff mode is enabled.
|
||||||
|
* The default number is 3 if it is not set.
|
||||||
|
*/
|
||||||
|
public int numOfQueriesBeforeBackoff() {
|
||||||
|
return numOfQueriesBeforeBackoff;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns {@code true} if service will be removed after its TTL expires. */
|
/** Returns {@code true} if service will be removed after its TTL expires. */
|
||||||
public boolean removeExpiredService() {
|
public boolean removeExpiredService() {
|
||||||
return removeExpiredService;
|
return removeExpiredService;
|
||||||
@@ -159,6 +170,7 @@ public class MdnsSearchOptions implements Parcelable {
|
|||||||
out.writeParcelable(mNetwork, 0);
|
out.writeParcelable(mNetwork, 0);
|
||||||
out.writeString(resolveInstanceName);
|
out.writeString(resolveInstanceName);
|
||||||
out.writeBoolean(onlyUseIpv6OnIpv6OnlyNetworks);
|
out.writeBoolean(onlyUseIpv6OnIpv6OnlyNetworks);
|
||||||
|
out.writeInt(numOfQueriesBeforeBackoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A builder to create {@link MdnsSearchOptions}. */
|
/** A builder to create {@link MdnsSearchOptions}. */
|
||||||
@@ -166,6 +178,7 @@ public class MdnsSearchOptions implements Parcelable {
|
|||||||
private final Set<String> subtypes;
|
private final Set<String> subtypes;
|
||||||
private boolean isPassiveMode = true;
|
private boolean isPassiveMode = true;
|
||||||
private boolean onlyUseIpv6OnIpv6OnlyNetworks = false;
|
private boolean onlyUseIpv6OnIpv6OnlyNetworks = false;
|
||||||
|
private int numOfQueriesBeforeBackoff = 3;
|
||||||
private boolean removeExpiredService;
|
private boolean removeExpiredService;
|
||||||
private Network mNetwork;
|
private Network mNetwork;
|
||||||
private String resolveInstanceName;
|
private String resolveInstanceName;
|
||||||
@@ -218,6 +231,14 @@ public class MdnsSearchOptions implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets if the query backoff mode should be turned on.
|
||||||
|
*/
|
||||||
|
public Builder setNumOfQueriesBeforeBackoff(int numOfQueriesBeforeBackoff) {
|
||||||
|
this.numOfQueriesBeforeBackoff = numOfQueriesBeforeBackoff;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets if the service should be removed after TTL.
|
* Sets if the service should be removed after TTL.
|
||||||
*
|
*
|
||||||
@@ -258,7 +279,8 @@ public class MdnsSearchOptions implements Parcelable {
|
|||||||
removeExpiredService,
|
removeExpiredService,
|
||||||
mNetwork,
|
mNetwork,
|
||||||
resolveInstanceName,
|
resolveInstanceName,
|
||||||
onlyUseIpv6OnIpv6OnlyNetworks);
|
onlyUseIpv6OnIpv6OnlyNetworks,
|
||||||
|
numOfQueriesBeforeBackoff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,6 +50,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||||||
*/
|
*/
|
||||||
public class MdnsServiceTypeClient {
|
public class MdnsServiceTypeClient {
|
||||||
|
|
||||||
|
private static final String TAG = MdnsServiceTypeClient.class.getSimpleName();
|
||||||
private static final int DEFAULT_MTU = 1500;
|
private static final int DEFAULT_MTU = 1500;
|
||||||
|
|
||||||
private final String serviceType;
|
private final String serviceType;
|
||||||
@@ -63,6 +64,7 @@ public class MdnsServiceTypeClient {
|
|||||||
private final ArrayMap<MdnsServiceBrowserListener, MdnsSearchOptions> listeners =
|
private final ArrayMap<MdnsServiceBrowserListener, MdnsSearchOptions> listeners =
|
||||||
new ArrayMap<>();
|
new ArrayMap<>();
|
||||||
// TODO: change instanceNameToResponse to TreeMap with case insensitive comparator.
|
// TODO: change instanceNameToResponse to TreeMap with case insensitive comparator.
|
||||||
|
@GuardedBy("lock")
|
||||||
private final Map<String, MdnsResponse> instanceNameToResponse = new HashMap<>();
|
private final Map<String, MdnsResponse> instanceNameToResponse = new HashMap<>();
|
||||||
private final boolean removeServiceAfterTtlExpires =
|
private final boolean removeServiceAfterTtlExpires =
|
||||||
MdnsConfigs.removeServiceAfterTtlExpires();
|
MdnsConfigs.removeServiceAfterTtlExpires();
|
||||||
@@ -77,7 +79,14 @@ public class MdnsServiceTypeClient {
|
|||||||
|
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
@Nullable
|
@Nullable
|
||||||
private Future<?> requestTaskFuture;
|
private Future<?> nextQueryTaskFuture;
|
||||||
|
|
||||||
|
@GuardedBy("lock")
|
||||||
|
@Nullable
|
||||||
|
private QueryTask lastScheduledTask;
|
||||||
|
|
||||||
|
@GuardedBy("lock")
|
||||||
|
private long lastSentTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor of {@link MdnsServiceTypeClient}.
|
* Constructor of {@link MdnsServiceTypeClient}.
|
||||||
@@ -189,7 +198,7 @@ public class MdnsServiceTypeClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cancel the next scheduled periodical task.
|
// Cancel the next scheduled periodical task.
|
||||||
if (requestTaskFuture != null) {
|
if (nextQueryTaskFuture != null) {
|
||||||
cancelRequestTaskLocked();
|
cancelRequestTaskLocked();
|
||||||
}
|
}
|
||||||
// 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
|
||||||
@@ -198,21 +207,40 @@ public class MdnsServiceTypeClient {
|
|||||||
searchOptions.getSubtypes(),
|
searchOptions.getSubtypes(),
|
||||||
searchOptions.isPassiveMode(),
|
searchOptions.isPassiveMode(),
|
||||||
searchOptions.onlyUseIpv6OnIpv6OnlyNetworks(),
|
searchOptions.onlyUseIpv6OnIpv6OnlyNetworks(),
|
||||||
currentSessionId,
|
searchOptions.numOfQueriesBeforeBackoff(),
|
||||||
socketKey);
|
socketKey);
|
||||||
|
final long now = clock.elapsedRealtime();
|
||||||
|
if (lastSentTime == 0) {
|
||||||
|
lastSentTime = now;
|
||||||
|
}
|
||||||
if (hadReply) {
|
if (hadReply) {
|
||||||
requestTaskFuture = scheduleNextRunLocked(taskConfig);
|
final QueryTaskConfig queryTaskConfig = taskConfig.getConfigForNextRun();
|
||||||
|
final long minRemainingTtl = getMinRemainingTtlLocked(now);
|
||||||
|
final long timeToRun = now + queryTaskConfig.delayUntilNextTaskWithoutBackoffMs;
|
||||||
|
nextQueryTaskFuture = scheduleNextRunLocked(queryTaskConfig,
|
||||||
|
minRemainingTtl, now, timeToRun, currentSessionId);
|
||||||
} else {
|
} else {
|
||||||
requestTaskFuture = executor.submit(new QueryTask(taskConfig));
|
lastScheduledTask = new QueryTask(taskConfig,
|
||||||
|
now /* timeToRun */,
|
||||||
|
now + getMinRemainingTtlLocked(now)/* minTtlExpirationTimeWhenScheduled */,
|
||||||
|
currentSessionId);
|
||||||
|
nextQueryTaskFuture = executor.submit(lastScheduledTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private void cancelRequestTaskLocked() {
|
private void cancelRequestTaskLocked() {
|
||||||
requestTaskFuture.cancel(true);
|
final boolean canceled = nextQueryTaskFuture.cancel(true);
|
||||||
|
sharedLog.log("task canceled:" + canceled + ", current session: " + currentSessionId
|
||||||
|
+ " task hashcode: " + getHexString(nextQueryTaskFuture));
|
||||||
++currentSessionId;
|
++currentSessionId;
|
||||||
requestTaskFuture = null;
|
nextQueryTaskFuture = null;
|
||||||
|
lastScheduledTask = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getHexString(Object o) {
|
||||||
|
return Integer.toHexString(System.identityHashCode(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean responseMatchesOptions(@NonNull MdnsResponse response,
|
private boolean responseMatchesOptions(@NonNull MdnsResponse response,
|
||||||
@@ -247,7 +275,7 @@ public class MdnsServiceTypeClient {
|
|||||||
if (listeners.remove(listener) == null) {
|
if (listeners.remove(listener) == null) {
|
||||||
return listeners.isEmpty();
|
return listeners.isEmpty();
|
||||||
}
|
}
|
||||||
if (listeners.isEmpty() && requestTaskFuture != null) {
|
if (listeners.isEmpty() && nextQueryTaskFuture != null) {
|
||||||
cancelRequestTaskLocked();
|
cancelRequestTaskLocked();
|
||||||
}
|
}
|
||||||
return listeners.isEmpty();
|
return listeners.isEmpty();
|
||||||
@@ -284,9 +312,9 @@ public class MdnsServiceTypeClient {
|
|||||||
for (MdnsResponse response : allResponses) {
|
for (MdnsResponse response : allResponses) {
|
||||||
if (modifiedResponse.contains(response)) {
|
if (modifiedResponse.contains(response)) {
|
||||||
if (response.isGoodbye()) {
|
if (response.isGoodbye()) {
|
||||||
onGoodbyeReceived(response.getServiceInstanceName());
|
onGoodbyeReceivedLocked(response.getServiceInstanceName());
|
||||||
} else {
|
} else {
|
||||||
onResponseModified(response);
|
onResponseModifiedLocked(response);
|
||||||
}
|
}
|
||||||
} else if (instanceNameToResponse.containsKey(response.getServiceInstanceName())) {
|
} else if (instanceNameToResponse.containsKey(response.getServiceInstanceName())) {
|
||||||
// If the response is not modified and already in the cache. The cache will
|
// If the response is not modified and already in the cache. The cache will
|
||||||
@@ -294,6 +322,20 @@ public class MdnsServiceTypeClient {
|
|||||||
instanceNameToResponse.put(response.getServiceInstanceName(), response);
|
instanceNameToResponse.put(response.getServiceInstanceName(), response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (nextQueryTaskFuture != null && lastScheduledTask != null
|
||||||
|
&& lastScheduledTask.config.shouldUseQueryBackoff()) {
|
||||||
|
final long now = clock.elapsedRealtime();
|
||||||
|
final long minRemainingTtl = getMinRemainingTtlLocked(now);
|
||||||
|
final long timeToRun = calculateTimeToRun(lastScheduledTask,
|
||||||
|
lastScheduledTask.config, now,
|
||||||
|
minRemainingTtl, lastSentTime);
|
||||||
|
if (timeToRun > lastScheduledTask.timeToRun) {
|
||||||
|
QueryTaskConfig lastTaskConfig = lastScheduledTask.config;
|
||||||
|
cancelRequestTaskLocked();
|
||||||
|
nextQueryTaskFuture = scheduleNextRunLocked(lastTaskConfig, minRemainingTtl,
|
||||||
|
now, timeToRun, currentSessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,13 +365,14 @@ public class MdnsServiceTypeClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestTaskFuture != null) {
|
if (nextQueryTaskFuture != null) {
|
||||||
cancelRequestTaskLocked();
|
cancelRequestTaskLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onResponseModified(@NonNull MdnsResponse response) {
|
@GuardedBy("lock")
|
||||||
|
private void onResponseModifiedLocked(@NonNull MdnsResponse response) {
|
||||||
final String serviceInstanceName = response.getServiceInstanceName();
|
final String serviceInstanceName = response.getServiceInstanceName();
|
||||||
final MdnsResponse currentResponse =
|
final MdnsResponse currentResponse =
|
||||||
instanceNameToResponse.get(serviceInstanceName);
|
instanceNameToResponse.get(serviceInstanceName);
|
||||||
@@ -375,7 +418,8 @@ public class MdnsServiceTypeClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onGoodbyeReceived(@Nullable String serviceInstanceName) {
|
@GuardedBy("lock")
|
||||||
|
private void onGoodbyeReceivedLocked(@Nullable String serviceInstanceName) {
|
||||||
final MdnsResponse response = instanceNameToResponse.remove(serviceInstanceName);
|
final MdnsResponse response = instanceNameToResponse.remove(serviceInstanceName);
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
return;
|
return;
|
||||||
@@ -427,32 +471,52 @@ public class MdnsServiceTypeClient {
|
|||||||
MdnsConfigs.alwaysAskForUnicastResponseInEachBurst();
|
MdnsConfigs.alwaysAskForUnicastResponseInEachBurst();
|
||||||
private final boolean usePassiveMode;
|
private final boolean usePassiveMode;
|
||||||
private final boolean onlyUseIpv6OnIpv6OnlyNetworks;
|
private final boolean onlyUseIpv6OnIpv6OnlyNetworks;
|
||||||
private final long sessionId;
|
private final int numOfQueriesBeforeBackoff;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
int transactionId;
|
final int transactionId;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean expectUnicastResponse;
|
final boolean expectUnicastResponse;
|
||||||
private int queriesPerBurst;
|
private final int queriesPerBurst;
|
||||||
private int timeBetweenBurstsInMs;
|
private final int timeBetweenBurstsInMs;
|
||||||
private int burstCounter;
|
private final int burstCounter;
|
||||||
private int timeToRunNextTaskInMs;
|
private final long delayUntilNextTaskWithoutBackoffMs;
|
||||||
private boolean isFirstBurst;
|
private final boolean isFirstBurst;
|
||||||
|
private final long queryCount;
|
||||||
@NonNull private final SocketKey socketKey;
|
@NonNull private final SocketKey socketKey;
|
||||||
|
|
||||||
|
|
||||||
|
QueryTaskConfig(@NonNull QueryTaskConfig other, long queryCount, int transactionId,
|
||||||
|
boolean expectUnicastResponse, boolean isFirstBurst, int burstCounter,
|
||||||
|
int queriesPerBurst, int timeBetweenBurstsInMs,
|
||||||
|
long delayUntilNextTaskWithoutBackoffMs) {
|
||||||
|
this.subtypes = new ArrayList<>(other.subtypes);
|
||||||
|
this.usePassiveMode = other.usePassiveMode;
|
||||||
|
this.onlyUseIpv6OnIpv6OnlyNetworks = other.onlyUseIpv6OnIpv6OnlyNetworks;
|
||||||
|
this.numOfQueriesBeforeBackoff = other.numOfQueriesBeforeBackoff;
|
||||||
|
this.transactionId = transactionId;
|
||||||
|
this.expectUnicastResponse = expectUnicastResponse;
|
||||||
|
this.queriesPerBurst = queriesPerBurst;
|
||||||
|
this.timeBetweenBurstsInMs = timeBetweenBurstsInMs;
|
||||||
|
this.burstCounter = burstCounter;
|
||||||
|
this.delayUntilNextTaskWithoutBackoffMs = delayUntilNextTaskWithoutBackoffMs;
|
||||||
|
this.isFirstBurst = isFirstBurst;
|
||||||
|
this.queryCount = queryCount;
|
||||||
|
this.socketKey = other.socketKey;
|
||||||
|
}
|
||||||
QueryTaskConfig(@NonNull Collection<String> subtypes,
|
QueryTaskConfig(@NonNull Collection<String> subtypes,
|
||||||
boolean usePassiveMode,
|
boolean usePassiveMode,
|
||||||
boolean onlyUseIpv6OnIpv6OnlyNetworks,
|
boolean onlyUseIpv6OnIpv6OnlyNetworks,
|
||||||
long sessionId,
|
int numOfQueriesBeforeBackoff,
|
||||||
@Nullable SocketKey socketKey) {
|
@Nullable SocketKey socketKey) {
|
||||||
this.usePassiveMode = usePassiveMode;
|
this.usePassiveMode = usePassiveMode;
|
||||||
this.onlyUseIpv6OnIpv6OnlyNetworks = onlyUseIpv6OnIpv6OnlyNetworks;
|
this.onlyUseIpv6OnIpv6OnlyNetworks = onlyUseIpv6OnIpv6OnlyNetworks;
|
||||||
|
this.numOfQueriesBeforeBackoff = numOfQueriesBeforeBackoff;
|
||||||
this.subtypes = new ArrayList<>(subtypes);
|
this.subtypes = new ArrayList<>(subtypes);
|
||||||
this.queriesPerBurst = QUERIES_PER_BURST;
|
this.queriesPerBurst = QUERIES_PER_BURST;
|
||||||
this.burstCounter = 0;
|
this.burstCounter = 0;
|
||||||
this.transactionId = 1;
|
this.transactionId = 1;
|
||||||
this.expectUnicastResponse = true;
|
this.expectUnicastResponse = true;
|
||||||
this.isFirstBurst = true;
|
this.isFirstBurst = true;
|
||||||
this.sessionId = sessionId;
|
|
||||||
// Config the scan frequency based on the scan mode.
|
// Config the scan frequency based on the scan mode.
|
||||||
if (this.usePassiveMode) {
|
if (this.usePassiveMode) {
|
||||||
// In passive scan mode, sends a single burst of QUERIES_PER_BURST queries, and then
|
// In passive scan mode, sends a single burst of QUERIES_PER_BURST queries, and then
|
||||||
@@ -467,42 +531,61 @@ public class MdnsServiceTypeClient {
|
|||||||
this.timeBetweenBurstsInMs = INITIAL_TIME_BETWEEN_BURSTS_MS;
|
this.timeBetweenBurstsInMs = INITIAL_TIME_BETWEEN_BURSTS_MS;
|
||||||
}
|
}
|
||||||
this.socketKey = socketKey;
|
this.socketKey = socketKey;
|
||||||
|
this.queryCount = 0;
|
||||||
|
this.delayUntilNextTaskWithoutBackoffMs = TIME_BETWEEN_QUERIES_IN_BURST_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryTaskConfig getConfigForNextRun() {
|
QueryTaskConfig getConfigForNextRun() {
|
||||||
if (++transactionId > UNSIGNED_SHORT_MAX_VALUE) {
|
long newQueryCount = queryCount + 1;
|
||||||
transactionId = 1;
|
int newTransactionId = transactionId + 1;
|
||||||
|
if (newTransactionId > UNSIGNED_SHORT_MAX_VALUE) {
|
||||||
|
newTransactionId = 1;
|
||||||
}
|
}
|
||||||
|
boolean newExpectUnicastResponse = false;
|
||||||
|
boolean newIsFirstBurst = isFirstBurst;
|
||||||
|
int newQueriesPerBurst = queriesPerBurst;
|
||||||
|
int newBurstCounter = burstCounter + 1;
|
||||||
|
long newDelayUntilNextTaskWithoutBackoffMs = delayUntilNextTaskWithoutBackoffMs;
|
||||||
|
int newTimeBetweenBurstsInMs = timeBetweenBurstsInMs;
|
||||||
// Only the first query expects uni-cast response.
|
// Only the first query expects uni-cast response.
|
||||||
expectUnicastResponse = false;
|
if (newBurstCounter == queriesPerBurst) {
|
||||||
if (++burstCounter == queriesPerBurst) {
|
newBurstCounter = 0;
|
||||||
burstCounter = 0;
|
|
||||||
|
|
||||||
if (alwaysAskForUnicastResponse) {
|
if (alwaysAskForUnicastResponse) {
|
||||||
expectUnicastResponse = true;
|
newExpectUnicastResponse = true;
|
||||||
}
|
}
|
||||||
// In passive scan mode, sends a single burst of QUERIES_PER_BURST queries, and
|
// In passive scan mode, sends a single burst of QUERIES_PER_BURST queries, and
|
||||||
// then in each TIME_BETWEEN_BURSTS interval, sends QUERIES_PER_BURST_PASSIVE_MODE
|
// then in each TIME_BETWEEN_BURSTS interval, sends QUERIES_PER_BURST_PASSIVE_MODE
|
||||||
// queries.
|
// queries.
|
||||||
if (isFirstBurst) {
|
if (isFirstBurst) {
|
||||||
isFirstBurst = false;
|
newIsFirstBurst = false;
|
||||||
if (usePassiveMode) {
|
if (usePassiveMode) {
|
||||||
queriesPerBurst = QUERIES_PER_BURST_PASSIVE_MODE;
|
newQueriesPerBurst = QUERIES_PER_BURST_PASSIVE_MODE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// In active scan mode, sends a burst of QUERIES_PER_BURST queries,
|
// In active scan mode, sends a burst of QUERIES_PER_BURST queries,
|
||||||
// TIME_BETWEEN_QUERIES_IN_BURST_MS apart, then waits for the scan interval, and
|
// TIME_BETWEEN_QUERIES_IN_BURST_MS apart, then waits for the scan interval, and
|
||||||
// then repeats. The scan interval starts as INITIAL_TIME_BETWEEN_BURSTS_MS and
|
// then repeats. The scan interval starts as INITIAL_TIME_BETWEEN_BURSTS_MS and
|
||||||
// doubles until it maxes out at TIME_BETWEEN_BURSTS_MS.
|
// doubles until it maxes out at TIME_BETWEEN_BURSTS_MS.
|
||||||
timeToRunNextTaskInMs = timeBetweenBurstsInMs;
|
newDelayUntilNextTaskWithoutBackoffMs = timeBetweenBurstsInMs;
|
||||||
if (timeBetweenBurstsInMs < TIME_BETWEEN_BURSTS_MS) {
|
if (timeBetweenBurstsInMs < TIME_BETWEEN_BURSTS_MS) {
|
||||||
timeBetweenBurstsInMs = Math.min(timeBetweenBurstsInMs * 2,
|
newTimeBetweenBurstsInMs = Math.min(timeBetweenBurstsInMs * 2,
|
||||||
TIME_BETWEEN_BURSTS_MS);
|
TIME_BETWEEN_BURSTS_MS);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
timeToRunNextTaskInMs = TIME_BETWEEN_QUERIES_IN_BURST_MS;
|
newDelayUntilNextTaskWithoutBackoffMs = TIME_BETWEEN_QUERIES_IN_BURST_MS;
|
||||||
}
|
}
|
||||||
return this;
|
return new QueryTaskConfig(this, newQueryCount, newTransactionId,
|
||||||
|
newExpectUnicastResponse, newIsFirstBurst, newBurstCounter, newQueriesPerBurst,
|
||||||
|
newTimeBetweenBurstsInMs, newDelayUntilNextTaskWithoutBackoffMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldUseQueryBackoff() {
|
||||||
|
// Don't enable backoff mode during the burst or in the first burst
|
||||||
|
if (burstCounter != 0 || isFirstBurst) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return queryCount > numOfQueriesBeforeBackoff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,9 +615,17 @@ public class MdnsServiceTypeClient {
|
|||||||
private class QueryTask implements Runnable {
|
private class QueryTask implements Runnable {
|
||||||
|
|
||||||
private final QueryTaskConfig config;
|
private final QueryTaskConfig config;
|
||||||
|
private final long timeToRun;
|
||||||
|
private final long minTtlExpirationTimeWhenScheduled;
|
||||||
|
private final long sessionId;
|
||||||
|
|
||||||
QueryTask(@NonNull QueryTaskConfig config) {
|
QueryTask(@NonNull QueryTaskConfig config, long timeToRun,
|
||||||
|
long minTtlExpirationTimeWhenScheduled,
|
||||||
|
long sessionId) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.timeToRun = timeToRun;
|
||||||
|
this.minTtlExpirationTimeWhenScheduled = minTtlExpirationTimeWhenScheduled;
|
||||||
|
this.sessionId = sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -573,13 +664,13 @@ public class MdnsServiceTypeClient {
|
|||||||
if (MdnsConfigs.useSessionIdToScheduleMdnsTask()) {
|
if (MdnsConfigs.useSessionIdToScheduleMdnsTask()) {
|
||||||
// In case that the task is not canceled successfully, use session ID to check
|
// In case that the task is not canceled successfully, use session ID to check
|
||||||
// if this task should continue to schedule more.
|
// if this task should continue to schedule more.
|
||||||
if (config.sessionId != currentSessionId) {
|
if (sessionId != currentSessionId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MdnsConfigs.shouldCancelScanTaskWhenFutureIsNull()) {
|
if (MdnsConfigs.shouldCancelScanTaskWhenFutureIsNull()) {
|
||||||
if (requestTaskFuture == null) {
|
if (nextQueryTaskFuture == null) {
|
||||||
// If requestTaskFuture is set to null, the task is cancelled. We can't use
|
// If requestTaskFuture is set to null, the task is cancelled. We can't use
|
||||||
// isCancelled() here because this QueryTask is different from the future
|
// isCancelled() here because this QueryTask is different from the future
|
||||||
// that is returned from executor.schedule(). See b/71646910.
|
// that is returned from executor.schedule(). See b/71646910.
|
||||||
@@ -624,14 +715,72 @@ public class MdnsServiceTypeClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
requestTaskFuture = scheduleNextRunLocked(this.config);
|
QueryTaskConfig nextRunConfig = this.config.getConfigForNextRun();
|
||||||
|
final long now = clock.elapsedRealtime();
|
||||||
|
lastSentTime = now;
|
||||||
|
final long minRemainingTtl = getMinRemainingTtlLocked(now);
|
||||||
|
final long timeToRun = calculateTimeToRun(this, nextRunConfig, now,
|
||||||
|
minRemainingTtl, lastSentTime);
|
||||||
|
nextQueryTaskFuture = scheduleNextRunLocked(nextRunConfig,
|
||||||
|
minRemainingTtl, now, timeToRun, lastScheduledTask.sessionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static long calculateTimeToRun(@NonNull QueryTask lastScheduledTask,
|
||||||
|
QueryTaskConfig queryTaskConfig, long now, long minRemainingTtl, long lastSentTime) {
|
||||||
|
final long baseDelayInMs = queryTaskConfig.delayUntilNextTaskWithoutBackoffMs;
|
||||||
|
if (!queryTaskConfig.shouldUseQueryBackoff()) {
|
||||||
|
return lastSentTime + baseDelayInMs;
|
||||||
|
}
|
||||||
|
if (minRemainingTtl <= 0) {
|
||||||
|
// There's no service, or there is an expired service. In any case, schedule for the
|
||||||
|
// minimum time, which is the base delay.
|
||||||
|
return lastSentTime + baseDelayInMs;
|
||||||
|
}
|
||||||
|
// If the next TTL expiration time hasn't changed, then use previous calculated timeToRun.
|
||||||
|
if (lastSentTime < now
|
||||||
|
&& lastScheduledTask.minTtlExpirationTimeWhenScheduled == now + minRemainingTtl) {
|
||||||
|
// Use the original scheduling time if the TTL has not changed, to avoid continuously
|
||||||
|
// rescheduling to 80% of the remaining TTL as time passes
|
||||||
|
return lastScheduledTask.timeToRun;
|
||||||
|
}
|
||||||
|
return Math.max(now + (long) (0.8 * minRemainingTtl), lastSentTime + baseDelayInMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuardedBy("lock")
|
||||||
|
private long getMinRemainingTtlLocked(long now) {
|
||||||
|
long minRemainingTtl = Long.MAX_VALUE;
|
||||||
|
for (MdnsResponse response : instanceNameToResponse.values()) {
|
||||||
|
if (!response.isComplete()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
long remainingTtl =
|
||||||
|
response.getServiceRecord().getRemainingTTL(now);
|
||||||
|
// remainingTtl is <= 0 means the service expired.
|
||||||
|
if (remainingTtl <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (remainingTtl < minRemainingTtl) {
|
||||||
|
minRemainingTtl = remainingTtl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minRemainingTtl == Long.MAX_VALUE ? 0 : minRemainingTtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuardedBy("lock")
|
||||||
@NonNull
|
@NonNull
|
||||||
private Future<?> scheduleNextRunLocked(@NonNull QueryTaskConfig lastRunConfig) {
|
private Future<?> scheduleNextRunLocked(@NonNull QueryTaskConfig nextRunConfig,
|
||||||
QueryTaskConfig config = lastRunConfig.getConfigForNextRun();
|
long minRemainingTtl,
|
||||||
return executor.schedule(new QueryTask(config), config.timeToRunNextTaskInMs, MILLISECONDS);
|
long timeWhenScheduled, long timeToRun, long sessionId) {
|
||||||
|
lastScheduledTask = new QueryTask(nextRunConfig, timeToRun,
|
||||||
|
minRemainingTtl + timeWhenScheduled, sessionId);
|
||||||
|
// The timeWhenScheduled could be greater than the timeToRun if the Runnable is delayed.
|
||||||
|
long timeToNextTasksWithBackoffInMs = Math.max(timeToRun - timeWhenScheduled, 0);
|
||||||
|
sharedLog.log(
|
||||||
|
String.format("Next run: sessionId: %d, in %d ms", lastScheduledTask.sessionId,
|
||||||
|
timeToNextTasksWithBackoffInMs));
|
||||||
|
return executor.schedule(lastScheduledTask, timeToNextTasksWithBackoffInMs,
|
||||||
|
MILLISECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,6 +288,110 @@ public class MdnsServiceTypeClientTests {
|
|||||||
verify(expectedSendFutures[5]).cancel(true);
|
verify(expectedSendFutures[5]).cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendQueries_activeScanWithQueryBackoff() {
|
||||||
|
MdnsSearchOptions searchOptions =
|
||||||
|
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(
|
||||||
|
false).setNumOfQueriesBeforeBackoff(11).build();
|
||||||
|
client.startSendAndReceive(mockListenerOne, searchOptions);
|
||||||
|
|
||||||
|
// First burst, 3 queries.
|
||||||
|
verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
1, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
2, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
// Second burst will be sent after initialTimeBetweenBurstsMs, 3 queries.
|
||||||
|
verifyAndSendQuery(
|
||||||
|
3, MdnsConfigs.initialTimeBetweenBurstsMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
4, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
5, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
// Third burst will be sent after initialTimeBetweenBurstsMs * 2, 3 queries.
|
||||||
|
verifyAndSendQuery(
|
||||||
|
6, MdnsConfigs.initialTimeBetweenBurstsMs() * 2, /* expectsUnicastResponse= */
|
||||||
|
false);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
7, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
8, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
// Forth burst will be sent after initialTimeBetweenBurstsMs * 4, 3 queries.
|
||||||
|
verifyAndSendQuery(
|
||||||
|
9, MdnsConfigs.initialTimeBetweenBurstsMs() * 4, /* expectsUnicastResponse= */
|
||||||
|
false);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
10, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
11, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
// In backoff mode, the current scheduled task will be canceled and reschedule if the
|
||||||
|
// 0.8 * smallestRemainingTtl is larger than time to next run.
|
||||||
|
long currentTime = TEST_TTL / 2 + TEST_ELAPSED_REALTIME;
|
||||||
|
doReturn(currentTime).when(mockDecoderClock).elapsedRealtime();
|
||||||
|
client.processResponse(createResponse(
|
||||||
|
"service-instance-1", "192.0.2.123", 5353,
|
||||||
|
SERVICE_TYPE_LABELS,
|
||||||
|
Collections.emptyMap(), TEST_TTL), socketKey);
|
||||||
|
verifyAndSendQuery(12, (long) (TEST_TTL / 2 * 0.8), /* expectsUnicastResponse= */
|
||||||
|
false);
|
||||||
|
currentTime += (long) (TEST_TTL / 2 * 0.8);
|
||||||
|
doReturn(currentTime).when(mockDecoderClock).elapsedRealtime();
|
||||||
|
verifyAndSendQuery(
|
||||||
|
13, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendQueries_passiveScanWithQueryBackoff() {
|
||||||
|
MdnsSearchOptions searchOptions =
|
||||||
|
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(
|
||||||
|
true).setNumOfQueriesBeforeBackoff(3).build();
|
||||||
|
client.startSendAndReceive(mockListenerOne, searchOptions);
|
||||||
|
verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
1, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
verifyAndSendQuery(
|
||||||
|
2, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
|
||||||
|
verifyAndSendQuery(3, MdnsConfigs.timeBetweenBurstsMs(), /* expectsUnicastResponse= */
|
||||||
|
false);
|
||||||
|
assertEquals(4, currentThreadExecutor.getNumOfScheduledFuture());
|
||||||
|
|
||||||
|
// In backoff mode, the current scheduled task will be canceled and reschedule if the
|
||||||
|
// 0.8 * smallestRemainingTtl is larger than time to next run.
|
||||||
|
doReturn(TEST_ELAPSED_REALTIME + 20000).when(mockDecoderClock).elapsedRealtime();
|
||||||
|
client.processResponse(createResponse(
|
||||||
|
"service-instance-1", "192.0.2.123", 5353,
|
||||||
|
SERVICE_TYPE_LABELS,
|
||||||
|
Collections.emptyMap(), TEST_TTL), socketKey);
|
||||||
|
verify(expectedSendFutures[4]).cancel(true);
|
||||||
|
assertEquals(5, currentThreadExecutor.getNumOfScheduledFuture());
|
||||||
|
verifyAndSendQuery(4, 80000 /* timeInMs */, false /* expectsUnicastResponse */);
|
||||||
|
assertEquals(6, currentThreadExecutor.getNumOfScheduledFuture());
|
||||||
|
// Next run should also be scheduled in 0.8 * smallestRemainingTtl
|
||||||
|
verifyAndSendQuery(5, 80000 /* timeInMs */, false /* expectsUnicastResponse */);
|
||||||
|
assertEquals(7, currentThreadExecutor.getNumOfScheduledFuture());
|
||||||
|
|
||||||
|
// If the records is not refreshed, the current scheduled task will not be canceled.
|
||||||
|
doReturn(TEST_ELAPSED_REALTIME + 20001).when(mockDecoderClock).elapsedRealtime();
|
||||||
|
client.processResponse(createResponse(
|
||||||
|
"service-instance-1", "192.0.2.123", 5353,
|
||||||
|
SERVICE_TYPE_LABELS,
|
||||||
|
Collections.emptyMap(), TEST_TTL,
|
||||||
|
TEST_ELAPSED_REALTIME - 1), socketKey);
|
||||||
|
verify(expectedSendFutures[7], never()).cancel(true);
|
||||||
|
|
||||||
|
// In backoff mode, the current scheduled task will not be canceled if the
|
||||||
|
// 0.8 * smallestRemainingTtl is smaller than time to next run.
|
||||||
|
doReturn(TEST_ELAPSED_REALTIME).when(mockDecoderClock).elapsedRealtime();
|
||||||
|
client.processResponse(createResponse(
|
||||||
|
"service-instance-1", "192.0.2.123", 5353,
|
||||||
|
SERVICE_TYPE_LABELS,
|
||||||
|
Collections.emptyMap(), TEST_TTL), socketKey);
|
||||||
|
verify(expectedSendFutures[7], never()).cancel(true);
|
||||||
|
|
||||||
|
client.stopSendAndReceive(mockListenerOne);
|
||||||
|
verify(expectedSendFutures[7]).cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendQueries_reentry_passiveScanMode() {
|
public void sendQueries_reentry_passiveScanMode() {
|
||||||
MdnsSearchOptions searchOptions =
|
MdnsSearchOptions searchOptions =
|
||||||
@@ -328,7 +432,8 @@ public class MdnsServiceTypeClientTests {
|
|||||||
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
|
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
|
||||||
QueryTaskConfig config = new QueryTaskConfig(
|
QueryTaskConfig config = new QueryTaskConfig(
|
||||||
searchOptions.getSubtypes(), searchOptions.isPassiveMode(),
|
searchOptions.getSubtypes(), searchOptions.isPassiveMode(),
|
||||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */, 1, socketKey);
|
false /* onlyUseIpv6OnIpv6OnlyNetworks */, 3 /* numOfQueriesBeforeBackoff */,
|
||||||
|
socketKey);
|
||||||
|
|
||||||
// This is the first query. We will ask for unicast response.
|
// This is the first query. We will ask for unicast response.
|
||||||
assertTrue(config.expectUnicastResponse);
|
assertTrue(config.expectUnicastResponse);
|
||||||
@@ -358,7 +463,8 @@ public class MdnsServiceTypeClientTests {
|
|||||||
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
|
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
|
||||||
QueryTaskConfig config = new QueryTaskConfig(
|
QueryTaskConfig config = new QueryTaskConfig(
|
||||||
searchOptions.getSubtypes(), searchOptions.isPassiveMode(),
|
searchOptions.getSubtypes(), searchOptions.isPassiveMode(),
|
||||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */, 1, socketKey);
|
false /* onlyUseIpv6OnIpv6OnlyNetworks */, 3 /* numOfQueriesBeforeBackoff */,
|
||||||
|
socketKey);
|
||||||
|
|
||||||
// This is the first query. We will ask for unicast response.
|
// This is the first query. We will ask for unicast response.
|
||||||
assertTrue(config.expectUnicastResponse);
|
assertTrue(config.expectUnicastResponse);
|
||||||
@@ -714,8 +820,10 @@ public class MdnsServiceTypeClientTests {
|
|||||||
return mockPacketWriter;
|
return mockPacketWriter;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
MdnsSearchOptions searchOptions = MdnsSearchOptions.newBuilder().setRemoveExpiredService(
|
MdnsSearchOptions searchOptions = MdnsSearchOptions.newBuilder()
|
||||||
true).build();
|
.setRemoveExpiredService(true)
|
||||||
|
.setNumOfQueriesBeforeBackoff(Integer.MAX_VALUE)
|
||||||
|
.build();
|
||||||
client.startSendAndReceive(mockListenerOne, searchOptions);
|
client.startSendAndReceive(mockListenerOne, searchOptions);
|
||||||
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
|
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
|
||||||
|
|
||||||
@@ -1248,13 +1356,16 @@ public class MdnsServiceTypeClientTests {
|
|||||||
final String ipV4Address = "192.0.2.0";
|
final String ipV4Address = "192.0.2.0";
|
||||||
|
|
||||||
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
|
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
|
||||||
|
.setNumOfQueriesBeforeBackoff(Integer.MAX_VALUE)
|
||||||
.setResolveInstanceName("instance1").build();
|
.setResolveInstanceName("instance1").build();
|
||||||
|
|
||||||
client.startSendAndReceive(mockListenerOne, resolveOptions);
|
client.startSendAndReceive(mockListenerOne, resolveOptions);
|
||||||
// Ensure the first task is executed so it schedules a future task
|
// Ensure the first task is executed so it schedules a future task
|
||||||
currentThreadExecutor.getAndClearSubmittedFuture().get(
|
currentThreadExecutor.getAndClearSubmittedFuture().get(
|
||||||
TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||||
client.startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
|
client.startSendAndReceive(mockListenerTwo,
|
||||||
|
MdnsSearchOptions.newBuilder().setNumOfQueriesBeforeBackoff(
|
||||||
|
Integer.MAX_VALUE).build());
|
||||||
|
|
||||||
// Filing the second request cancels the first future
|
// Filing the second request cancels the first future
|
||||||
verify(expectedSendFutures[0]).cancel(true);
|
verify(expectedSendFutures[0]).cancel(true);
|
||||||
@@ -1317,7 +1428,7 @@ public class MdnsServiceTypeClientTests {
|
|||||||
|
|
||||||
private void verifyAndSendQuery(int index, long timeInMs, boolean expectsUnicastResponse,
|
private void verifyAndSendQuery(int index, long timeInMs, boolean expectsUnicastResponse,
|
||||||
boolean multipleSocketDiscovery) {
|
boolean multipleSocketDiscovery) {
|
||||||
assertEquals(currentThreadExecutor.getAndClearLastScheduledDelayInMs(), timeInMs);
|
assertEquals(timeInMs, currentThreadExecutor.getAndClearLastScheduledDelayInMs());
|
||||||
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
|
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
|
||||||
if (expectsUnicastResponse) {
|
if (expectsUnicastResponse) {
|
||||||
verify(mockSocketClient).sendPacketRequestingUnicastResponse(
|
verify(mockSocketClient).sendPacketRequestingUnicastResponse(
|
||||||
@@ -1406,6 +1517,10 @@ public class MdnsServiceTypeClientTests {
|
|||||||
lastSubmittedFuture = null;
|
lastSubmittedFuture = null;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getNumOfScheduledFuture() {
|
||||||
|
return futureIndex - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MdnsPacket createResponse(
|
private MdnsPacket createResponse(
|
||||||
@@ -1424,7 +1539,7 @@ public class MdnsServiceTypeClientTests {
|
|||||||
textAttributes, ptrTtlMillis);
|
textAttributes, ptrTtlMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a mDNS response.
|
|
||||||
private MdnsPacket createResponse(
|
private MdnsPacket createResponse(
|
||||||
@NonNull String serviceInstanceName,
|
@NonNull String serviceInstanceName,
|
||||||
@Nullable String host,
|
@Nullable String host,
|
||||||
@@ -1432,6 +1547,19 @@ public class MdnsServiceTypeClientTests {
|
|||||||
@NonNull String[] type,
|
@NonNull String[] type,
|
||||||
@NonNull Map<String, String> textAttributes,
|
@NonNull Map<String, String> textAttributes,
|
||||||
long ptrTtlMillis) {
|
long ptrTtlMillis) {
|
||||||
|
return createResponse(serviceInstanceName, host, port, type, textAttributes, ptrTtlMillis,
|
||||||
|
TEST_ELAPSED_REALTIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a mDNS response.
|
||||||
|
private MdnsPacket createResponse(
|
||||||
|
@NonNull String serviceInstanceName,
|
||||||
|
@Nullable String host,
|
||||||
|
int port,
|
||||||
|
@NonNull String[] type,
|
||||||
|
@NonNull Map<String, String> textAttributes,
|
||||||
|
long ptrTtlMillis,
|
||||||
|
long receiptTimeMillis) {
|
||||||
|
|
||||||
final ArrayList<MdnsRecord> answerRecords = new ArrayList<>();
|
final ArrayList<MdnsRecord> answerRecords = new ArrayList<>();
|
||||||
|
|
||||||
@@ -1442,7 +1570,7 @@ public class MdnsServiceTypeClientTests {
|
|||||||
final String[] serviceName = serviceNameList.toArray(new String[0]);
|
final String[] serviceName = serviceNameList.toArray(new String[0]);
|
||||||
final MdnsPointerRecord pointerRecord = new MdnsPointerRecord(
|
final MdnsPointerRecord pointerRecord = new MdnsPointerRecord(
|
||||||
type,
|
type,
|
||||||
TEST_ELAPSED_REALTIME /* receiptTimeMillis */,
|
receiptTimeMillis,
|
||||||
false /* cacheFlush */,
|
false /* cacheFlush */,
|
||||||
ptrTtlMillis,
|
ptrTtlMillis,
|
||||||
serviceName);
|
serviceName);
|
||||||
@@ -1451,7 +1579,7 @@ public class MdnsServiceTypeClientTests {
|
|||||||
// Set SRV record.
|
// Set SRV record.
|
||||||
final MdnsServiceRecord serviceRecord = new MdnsServiceRecord(
|
final MdnsServiceRecord serviceRecord = new MdnsServiceRecord(
|
||||||
serviceName,
|
serviceName,
|
||||||
TEST_ELAPSED_REALTIME /* receiptTimeMillis */,
|
receiptTimeMillis,
|
||||||
false /* cacheFlush */,
|
false /* cacheFlush */,
|
||||||
TEST_TTL,
|
TEST_TTL,
|
||||||
0 /* servicePriority */,
|
0 /* servicePriority */,
|
||||||
@@ -1465,7 +1593,7 @@ public class MdnsServiceTypeClientTests {
|
|||||||
final InetAddress addr = InetAddresses.parseNumericAddress(host);
|
final InetAddress addr = InetAddresses.parseNumericAddress(host);
|
||||||
final MdnsInetAddressRecord inetAddressRecord = new MdnsInetAddressRecord(
|
final MdnsInetAddressRecord inetAddressRecord = new MdnsInetAddressRecord(
|
||||||
new String[] {"hostname"} /* name */,
|
new String[] {"hostname"} /* name */,
|
||||||
TEST_ELAPSED_REALTIME /* receiptTimeMillis */,
|
receiptTimeMillis,
|
||||||
false /* cacheFlush */,
|
false /* cacheFlush */,
|
||||||
TEST_TTL,
|
TEST_TTL,
|
||||||
addr);
|
addr);
|
||||||
@@ -1479,7 +1607,7 @@ public class MdnsServiceTypeClientTests {
|
|||||||
}
|
}
|
||||||
final MdnsTextRecord textRecord = new MdnsTextRecord(
|
final MdnsTextRecord textRecord = new MdnsTextRecord(
|
||||||
serviceName,
|
serviceName,
|
||||||
TEST_ELAPSED_REALTIME /* receiptTimeMillis */,
|
receiptTimeMillis,
|
||||||
false /* cacheFlush */,
|
false /* cacheFlush */,
|
||||||
TEST_TTL,
|
TEST_TTL,
|
||||||
textEntries);
|
textEntries);
|
||||||
|
|||||||
Reference in New Issue
Block a user