Add a handler thread check to all public methods

To ensure that all access to the MdnsServiceTypeClient is done on
the handler thread, a handler thread check must be added to all
public methods in the MdnsServiceTypeClient. This will allow the
synchronized lock to be removed in future changes, and it will
also ensure that MdnsServiceTypeClient can access MdsServiceCache
properly.

Bug: 265787401
Test: atest FrameworksNetTests
Change-Id: I0206874eb0acdf0272b8ad23d29f3e764bfdec38
This commit is contained in:
Paul Hu
2023-05-16 17:42:24 +08:00
parent 775840e1b4
commit d5b24b4855
3 changed files with 144 additions and 96 deletions

View File

@@ -289,6 +289,6 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
return new MdnsServiceTypeClient( return new MdnsServiceTypeClient(
serviceType, socketClient, serviceType, socketClient,
executorProvider.newServiceTypeClientSchedulerExecutor(), socketKey, executorProvider.newServiceTypeClientSchedulerExecutor(), socketKey,
sharedLog.forSubComponent(tag)); sharedLog.forSubComponent(tag), handler.getLooper());
} }
} }

View File

@@ -16,10 +16,14 @@
package com.android.server.connectivity.mdns; package com.android.server.connectivity.mdns;
import static com.android.server.connectivity.mdns.util.MdnsUtils.ensureRunningOnHandlerThread;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
@@ -60,6 +64,7 @@ public class MdnsServiceTypeClient {
private final ScheduledExecutorService executor; private final ScheduledExecutorService executor;
@NonNull private final SocketKey socketKey; @NonNull private final SocketKey socketKey;
@NonNull private final SharedLog sharedLog; @NonNull private final SharedLog sharedLog;
@NonNull private final Handler handler;
private final Object lock = new Object(); private final Object lock = new Object();
private final ArrayMap<MdnsServiceBrowserListener, MdnsSearchOptions> listeners = private final ArrayMap<MdnsServiceBrowserListener, MdnsSearchOptions> listeners =
new ArrayMap<>(); new ArrayMap<>();
@@ -99,9 +104,10 @@ public class MdnsServiceTypeClient {
@NonNull MdnsSocketClientBase socketClient, @NonNull MdnsSocketClientBase socketClient,
@NonNull ScheduledExecutorService executor, @NonNull ScheduledExecutorService executor,
@NonNull SocketKey socketKey, @NonNull SocketKey socketKey,
@NonNull SharedLog sharedLog) { @NonNull SharedLog sharedLog,
@NonNull Looper looper) {
this(serviceType, socketClient, executor, new MdnsResponseDecoder.Clock(), socketKey, this(serviceType, socketClient, executor, new MdnsResponseDecoder.Clock(), socketKey,
sharedLog); sharedLog, looper);
} }
@VisibleForTesting @VisibleForTesting
@@ -111,7 +117,8 @@ public class MdnsServiceTypeClient {
@NonNull ScheduledExecutorService executor, @NonNull ScheduledExecutorService executor,
@NonNull MdnsResponseDecoder.Clock clock, @NonNull MdnsResponseDecoder.Clock clock,
@NonNull SocketKey socketKey, @NonNull SocketKey socketKey,
@NonNull SharedLog sharedLog) { @NonNull SharedLog sharedLog,
@NonNull Looper looper) {
this.serviceType = serviceType; this.serviceType = serviceType;
this.socketClient = socketClient; this.socketClient = socketClient;
this.executor = executor; this.executor = executor;
@@ -120,6 +127,7 @@ public class MdnsServiceTypeClient {
this.clock = clock; this.clock = clock;
this.socketKey = socketKey; this.socketKey = socketKey;
this.sharedLog = sharedLog; this.sharedLog = sharedLog;
this.handler = new Handler(looper);
} }
private static MdnsServiceInfo buildMdnsServiceInfoFromResponse( private static MdnsServiceInfo buildMdnsServiceInfoFromResponse(
@@ -182,6 +190,7 @@ public class MdnsServiceTypeClient {
public void startSendAndReceive( public void startSendAndReceive(
@NonNull MdnsServiceBrowserListener listener, @NonNull MdnsServiceBrowserListener listener,
@NonNull MdnsSearchOptions searchOptions) { @NonNull MdnsSearchOptions searchOptions) {
ensureRunningOnHandlerThread(handler);
synchronized (lock) { synchronized (lock) {
this.searchOptions = searchOptions; this.searchOptions = searchOptions;
boolean hadReply = false; boolean hadReply = false;
@@ -271,6 +280,7 @@ public class MdnsServiceTypeClient {
* listener}. Otherwise returns {@code false}. * listener}. Otherwise returns {@code false}.
*/ */
public boolean stopSendAndReceive(@NonNull MdnsServiceBrowserListener listener) { public boolean stopSendAndReceive(@NonNull MdnsServiceBrowserListener listener) {
ensureRunningOnHandlerThread(handler);
synchronized (lock) { synchronized (lock) {
if (listeners.remove(listener) == null) { if (listeners.remove(listener) == null) {
return listeners.isEmpty(); return listeners.isEmpty();
@@ -282,15 +292,12 @@ public class MdnsServiceTypeClient {
} }
} }
public String[] getServiceTypeLabels() {
return serviceTypeLabels;
}
/** /**
* Process an incoming response packet. * Process an incoming response packet.
*/ */
public synchronized void processResponse(@NonNull MdnsPacket packet, public synchronized void processResponse(@NonNull MdnsPacket packet,
@NonNull SocketKey socketKey) { @NonNull SocketKey socketKey) {
ensureRunningOnHandlerThread(handler);
synchronized (lock) { synchronized (lock) {
// Augment the list of current known responses, and generated responses for resolve // Augment the list of current known responses, and generated responses for resolve
// requests if there is no known response // requests if there is no known response
@@ -340,6 +347,7 @@ public class MdnsServiceTypeClient {
} }
public synchronized void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode) { public synchronized void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode) {
ensureRunningOnHandlerThread(handler);
for (int i = 0; i < listeners.size(); i++) { for (int i = 0; i < listeners.size(); i++) {
listeners.keyAt(i).onFailedToParseMdnsResponse(receivedPacketNumber, errorCode); listeners.keyAt(i).onFailedToParseMdnsResponse(receivedPacketNumber, errorCode);
} }
@@ -347,6 +355,7 @@ public class MdnsServiceTypeClient {
/** Notify all services are removed because the socket is destroyed. */ /** Notify all services are removed because the socket is destroyed. */
public void notifySocketDestroyed() { public void notifySocketDestroyed() {
ensureRunningOnHandlerThread(handler);
synchronized (lock) { synchronized (lock) {
for (MdnsResponse response : instanceNameToResponse.values()) { for (MdnsResponse response : instanceNameToResponse.values()) {
final String name = response.getServiceInstanceName(); final String name = response.getServiceInstanceName();

View File

@@ -41,6 +41,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.net.InetAddresses; import android.net.InetAddresses;
import android.net.Network; import android.net.Network;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.CollectionUtils;
@@ -49,7 +51,9 @@ import com.android.server.connectivity.mdns.MdnsServiceInfo.TextEntry;
import com.android.server.connectivity.mdns.MdnsServiceTypeClient.QueryTaskConfig; import com.android.server.connectivity.mdns.MdnsServiceTypeClient.QueryTaskConfig;
import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner; import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@@ -82,6 +86,7 @@ import java.util.stream.Stream;
@DevSdkIgnoreRule.IgnoreUpTo(SC_V2) @DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
public class MdnsServiceTypeClientTests { public class MdnsServiceTypeClientTests {
private static final int INTERFACE_INDEX = 999; private static final int INTERFACE_INDEX = 999;
private static final long DEFAULT_TIMEOUT = 2000L;
private static final String SERVICE_TYPE = "_googlecast._tcp.local"; private static final String SERVICE_TYPE = "_googlecast._tcp.local";
private static final String[] SERVICE_TYPE_LABELS = TextUtils.split(SERVICE_TYPE, "\\."); private static final String[] SERVICE_TYPE_LABELS = TextUtils.split(SERVICE_TYPE, "\\.");
private static final InetSocketAddress IPV4_ADDRESS = new InetSocketAddress( private static final InetSocketAddress IPV4_ADDRESS = new InetSocketAddress(
@@ -119,6 +124,8 @@ public class MdnsServiceTypeClientTests {
private MdnsServiceTypeClient client; private MdnsServiceTypeClient client;
private SocketKey socketKey; private SocketKey socketKey;
private HandlerThread thread;
private Handler handler;
@Before @Before
@SuppressWarnings("DoNotMock") @SuppressWarnings("DoNotMock")
@@ -174,9 +181,12 @@ public class MdnsServiceTypeClientTests {
.thenReturn(expectedIPv6Packets[14]) .thenReturn(expectedIPv6Packets[14])
.thenReturn(expectedIPv6Packets[15]); .thenReturn(expectedIPv6Packets[15]);
thread = new HandlerThread("MdnsServiceTypeClientTests");
thread.start();
handler = new Handler(thread.getLooper());
client = client =
new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor, new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
mockDecoderClock, socketKey, mockSharedLog) { mockDecoderClock, socketKey, mockSharedLog, thread.getLooper()) {
@Override @Override
MdnsPacketWriter createMdnsPacketWriter() { MdnsPacketWriter createMdnsPacketWriter() {
return mockPacketWriter; return mockPacketWriter;
@@ -184,11 +194,40 @@ public class MdnsServiceTypeClientTests {
}; };
} }
@After
public void tearDown() {
if (thread != null) {
thread.quitSafely();
}
}
private void runOnHandler(Runnable r) {
handler.post(r);
HandlerUtils.waitForIdle(handler, DEFAULT_TIMEOUT);
}
private void startSendAndReceive(MdnsServiceBrowserListener listener,
MdnsSearchOptions searchOptions) {
runOnHandler(() -> client.startSendAndReceive(listener, searchOptions));
}
private void processResponse(MdnsPacket packet, SocketKey socketKey) {
runOnHandler(() -> client.processResponse(packet, socketKey));
}
private void stopSendAndReceive(MdnsServiceBrowserListener listener) {
runOnHandler(() -> client.stopSendAndReceive(listener));
}
private void notifySocketDestroyed() {
runOnHandler(() -> client.notifySocketDestroyed());
}
@Test @Test
public void sendQueries_activeScanMode() { public void sendQueries_activeScanMode() {
MdnsSearchOptions searchOptions = MdnsSearchOptions searchOptions =
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build(); MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
// First burst, 3 queries. // First burst, 3 queries.
verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true); verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true);
@@ -228,7 +267,7 @@ public class MdnsServiceTypeClientTests {
14, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false); 14, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
// Stop sending packets. // Stop sending packets.
client.stopSendAndReceive(mockListenerOne); stopSendAndReceive(mockListenerOne);
verify(expectedSendFutures[15]).cancel(true); verify(expectedSendFutures[15]).cancel(true);
} }
@@ -236,7 +275,7 @@ public class MdnsServiceTypeClientTests {
public void sendQueries_reentry_activeScanMode() { public void sendQueries_reentry_activeScanMode() {
MdnsSearchOptions searchOptions = MdnsSearchOptions searchOptions =
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build(); MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
// First burst, first query is sent. // First burst, first query is sent.
verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true); verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true);
@@ -248,7 +287,7 @@ public class MdnsServiceTypeClientTests {
.addSubtype("abcde") .addSubtype("abcde")
.setIsPassiveMode(false) .setIsPassiveMode(false)
.build(); .build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
// The previous scheduled task should be canceled. // The previous scheduled task should be canceled.
verify(expectedSendFutures[1]).cancel(true); verify(expectedSendFutures[1]).cancel(true);
@@ -260,7 +299,7 @@ public class MdnsServiceTypeClientTests {
3, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false); 3, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
// Stop sending packets. // Stop sending packets.
client.stopSendAndReceive(mockListenerOne); stopSendAndReceive(mockListenerOne);
verify(expectedSendFutures[5]).cancel(true); verify(expectedSendFutures[5]).cancel(true);
} }
@@ -268,7 +307,7 @@ public class MdnsServiceTypeClientTests {
public void sendQueries_passiveScanMode() { public void sendQueries_passiveScanMode() {
MdnsSearchOptions searchOptions = MdnsSearchOptions searchOptions =
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(true).build(); MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(true).build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
// First burst, 3 query. // First burst, 3 query.
verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true); verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true);
@@ -284,7 +323,7 @@ public class MdnsServiceTypeClientTests {
false); false);
// Stop sending packets. // Stop sending packets.
client.stopSendAndReceive(mockListenerOne); stopSendAndReceive(mockListenerOne);
verify(expectedSendFutures[5]).cancel(true); verify(expectedSendFutures[5]).cancel(true);
} }
@@ -293,7 +332,7 @@ public class MdnsServiceTypeClientTests {
MdnsSearchOptions searchOptions = MdnsSearchOptions searchOptions =
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode( MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(
false).setNumOfQueriesBeforeBackoff(11).build(); false).setNumOfQueriesBeforeBackoff(11).build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
// First burst, 3 queries. // First burst, 3 queries.
verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true); verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true);
@@ -328,7 +367,7 @@ public class MdnsServiceTypeClientTests {
// 0.8 * smallestRemainingTtl is larger than time to next run. // 0.8 * smallestRemainingTtl is larger than time to next run.
long currentTime = TEST_TTL / 2 + TEST_ELAPSED_REALTIME; long currentTime = TEST_TTL / 2 + TEST_ELAPSED_REALTIME;
doReturn(currentTime).when(mockDecoderClock).elapsedRealtime(); doReturn(currentTime).when(mockDecoderClock).elapsedRealtime();
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", "192.0.2.123", 5353, "service-instance-1", "192.0.2.123", 5353,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
@@ -345,7 +384,7 @@ public class MdnsServiceTypeClientTests {
MdnsSearchOptions searchOptions = MdnsSearchOptions searchOptions =
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode( MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(
true).setNumOfQueriesBeforeBackoff(3).build(); true).setNumOfQueriesBeforeBackoff(3).build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true); verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true);
verifyAndSendQuery( verifyAndSendQuery(
1, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false); 1, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
@@ -358,7 +397,7 @@ public class MdnsServiceTypeClientTests {
// In backoff mode, the current scheduled task will be canceled and reschedule if the // In backoff mode, the current scheduled task will be canceled and reschedule if the
// 0.8 * smallestRemainingTtl is larger than time to next run. // 0.8 * smallestRemainingTtl is larger than time to next run.
doReturn(TEST_ELAPSED_REALTIME + 20000).when(mockDecoderClock).elapsedRealtime(); doReturn(TEST_ELAPSED_REALTIME + 20000).when(mockDecoderClock).elapsedRealtime();
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", "192.0.2.123", 5353, "service-instance-1", "192.0.2.123", 5353,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
@@ -372,7 +411,7 @@ public class MdnsServiceTypeClientTests {
// If the records is not refreshed, the current scheduled task will not be canceled. // If the records is not refreshed, the current scheduled task will not be canceled.
doReturn(TEST_ELAPSED_REALTIME + 20001).when(mockDecoderClock).elapsedRealtime(); doReturn(TEST_ELAPSED_REALTIME + 20001).when(mockDecoderClock).elapsedRealtime();
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", "192.0.2.123", 5353, "service-instance-1", "192.0.2.123", 5353,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL, Collections.emptyMap(), TEST_TTL,
@@ -382,13 +421,13 @@ public class MdnsServiceTypeClientTests {
// In backoff mode, the current scheduled task will not be canceled if the // In backoff mode, the current scheduled task will not be canceled if the
// 0.8 * smallestRemainingTtl is smaller than time to next run. // 0.8 * smallestRemainingTtl is smaller than time to next run.
doReturn(TEST_ELAPSED_REALTIME).when(mockDecoderClock).elapsedRealtime(); doReturn(TEST_ELAPSED_REALTIME).when(mockDecoderClock).elapsedRealtime();
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", "192.0.2.123", 5353, "service-instance-1", "192.0.2.123", 5353,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
verify(expectedSendFutures[7], never()).cancel(true); verify(expectedSendFutures[7], never()).cancel(true);
client.stopSendAndReceive(mockListenerOne); stopSendAndReceive(mockListenerOne);
verify(expectedSendFutures[7]).cancel(true); verify(expectedSendFutures[7]).cancel(true);
} }
@@ -396,7 +435,7 @@ public class MdnsServiceTypeClientTests {
public void sendQueries_reentry_passiveScanMode() { public void sendQueries_reentry_passiveScanMode() {
MdnsSearchOptions searchOptions = MdnsSearchOptions searchOptions =
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(true).build(); MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(true).build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
// First burst, first query is sent. // First burst, first query is sent.
verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true); verifyAndSendQuery(0, 0, /* expectsUnicastResponse= */ true);
@@ -408,7 +447,7 @@ public class MdnsServiceTypeClientTests {
.addSubtype("abcde") .addSubtype("abcde")
.setIsPassiveMode(true) .setIsPassiveMode(true)
.build(); .build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
// The previous scheduled task should be canceled. // The previous scheduled task should be canceled.
verify(expectedSendFutures[1]).cancel(true); verify(expectedSendFutures[1]).cancel(true);
@@ -420,7 +459,7 @@ public class MdnsServiceTypeClientTests {
3, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false); 3, MdnsConfigs.timeBetweenQueriesInBurstMs(), /* expectsUnicastResponse= */ false);
// Stop sending packets. // Stop sending packets.
client.stopSendAndReceive(mockListenerOne); stopSendAndReceive(mockListenerOne);
verify(expectedSendFutures[5]).cancel(true); verify(expectedSendFutures[5]).cancel(true);
} }
@@ -492,7 +531,7 @@ public class MdnsServiceTypeClientTests {
public void testIfPreviousTaskIsCanceledWhenNewSessionStarts() { public void testIfPreviousTaskIsCanceledWhenNewSessionStarts() {
MdnsSearchOptions searchOptions = MdnsSearchOptions searchOptions =
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(true).build(); MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(true).build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable(); Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
// Change the sutypes and start a new session. // Change the sutypes and start a new session.
@@ -502,7 +541,7 @@ public class MdnsServiceTypeClientTests {
.addSubtype("abcde") .addSubtype("abcde")
.setIsPassiveMode(true) .setIsPassiveMode(true)
.build(); .build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
// Clear the scheduled runnable. // Clear the scheduled runnable.
currentThreadExecutor.getAndClearLastScheduledRunnable(); currentThreadExecutor.getAndClearLastScheduledRunnable();
@@ -521,9 +560,9 @@ public class MdnsServiceTypeClientTests {
//MdnsConfigsFlagsImpl.shouldCancelScanTaskWhenFutureIsNull.override(true); //MdnsConfigsFlagsImpl.shouldCancelScanTaskWhenFutureIsNull.override(true);
MdnsSearchOptions searchOptions = MdnsSearchOptions searchOptions =
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(true).build(); MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(true).build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
// Change the sutypes and start a new session. // Change the sutypes and start a new session.
client.stopSendAndReceive(mockListenerOne); stopSendAndReceive(mockListenerOne);
// Clear the scheduled runnable. // Clear the scheduled runnable.
currentThreadExecutor.getAndClearLastScheduledRunnable(); currentThreadExecutor.getAndClearLastScheduledRunnable();
@@ -538,10 +577,10 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void testQueryScheduledWhenAnsweredFromCache() { public void testQueryScheduledWhenAnsweredFromCache() {
final MdnsSearchOptions searchOptions = MdnsSearchOptions.getDefaultOptions(); final MdnsSearchOptions searchOptions = MdnsSearchOptions.getDefaultOptions();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
assertNotNull(currentThreadExecutor.getAndClearSubmittedRunnable()); assertNotNull(currentThreadExecutor.getAndClearSubmittedRunnable());
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", "192.0.2.123", 5353, "service-instance-1", "192.0.2.123", 5353,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
@@ -550,7 +589,7 @@ public class MdnsServiceTypeClientTests {
verify(mockListenerOne).onServiceFound(any()); verify(mockListenerOne).onServiceFound(any());
// File another identical query // File another identical query
client.startSendAndReceive(mockListenerTwo, searchOptions); startSendAndReceive(mockListenerTwo, searchOptions);
verify(mockListenerTwo).onServiceNameDiscovered(any()); verify(mockListenerTwo).onServiceNameDiscovered(any());
verify(mockListenerTwo).onServiceFound(any()); verify(mockListenerTwo).onServiceFound(any());
@@ -582,9 +621,9 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void processResponse_incompleteResponse() { public void processResponse_incompleteResponse() {
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
client.processResponse(createResponse( processResponse(createResponse(
"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);
@@ -606,16 +645,16 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void processIPv4Response_completeResponseForNewServiceInstance() throws Exception { public void processIPv4Response_completeResponseForNewServiceInstance() throws Exception {
final String ipV4Address = "192.168.1.1"; final String ipV4Address = "192.168.1.1";
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
// Process the initial response. // Process the initial response.
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", ipV4Address, 5353, "service-instance-1", ipV4Address, 5353,
/* subtype= */ "ABCDE", /* subtype= */ "ABCDE",
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
// Process a second response with a different port and updated text attributes. // Process a second response with a different port and updated text attributes.
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", ipV4Address, 5354, "service-instance-1", ipV4Address, 5354,
/* subtype= */ "ABCDE", /* subtype= */ "ABCDE",
Collections.singletonMap("key", "value"), TEST_TTL), Collections.singletonMap("key", "value"), TEST_TTL),
@@ -660,16 +699,16 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void processIPv6Response_getCorrectServiceInfo() throws Exception { public void processIPv6Response_getCorrectServiceInfo() throws Exception {
final String ipV6Address = "2000:3333::da6c:63ff:fe7c:7483"; final String ipV6Address = "2000:3333::da6c:63ff:fe7c:7483";
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
// Process the initial response. // Process the initial response.
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", ipV6Address, 5353, "service-instance-1", ipV6Address, 5353,
/* subtype= */ "ABCDE", /* subtype= */ "ABCDE",
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
// Process a second response with a different port and updated text attributes. // Process a second response with a different port and updated text attributes.
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", ipV6Address, 5354, "service-instance-1", ipV6Address, 5354,
/* subtype= */ "ABCDE", /* subtype= */ "ABCDE",
Collections.singletonMap("key", "value"), TEST_TTL), Collections.singletonMap("key", "value"), TEST_TTL),
@@ -732,18 +771,18 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void processResponse_goodBye() throws Exception { public void processResponse_goodBye() throws Exception {
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
client.startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
final String serviceName = "service-instance-1"; final String serviceName = "service-instance-1";
final String ipV6Address = "2000:3333::da6c:63ff:fe7c:7483"; final String ipV6Address = "2000:3333::da6c:63ff:fe7c:7483";
// Process the initial response. // Process the initial response.
client.processResponse(createResponse( processResponse(createResponse(
serviceName, ipV6Address, 5353, serviceName, ipV6Address, 5353,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
client.processResponse(createResponse( processResponse(createResponse(
"goodbye-service", ipV6Address, 5353, "goodbye-service", ipV6Address, 5353,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), /* ptrTtlMillis= */ 0L), socketKey); Collections.emptyMap(), /* ptrTtlMillis= */ 0L), socketKey);
@@ -753,7 +792,7 @@ public class MdnsServiceTypeClientTests {
verifyServiceRemovedNoCallback(mockListenerTwo); verifyServiceRemovedNoCallback(mockListenerTwo);
// Verify removed callback would be called. // Verify removed callback would be called.
client.processResponse(createResponse( processResponse(createResponse(
serviceName, ipV6Address, 5353, serviceName, ipV6Address, 5353,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), 0L), socketKey); Collections.emptyMap(), 0L), socketKey);
@@ -766,12 +805,12 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void reportExistingServiceToNewlyRegisteredListeners() throws Exception { public void reportExistingServiceToNewlyRegisteredListeners() throws Exception {
// Process the initial response. // Process the initial response.
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", "192.168.1.1", 5353, "service-instance-1", "192.168.1.1", 5353,
/* subtype= */ "ABCDE", /* subtype= */ "ABCDE",
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
client.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());
@@ -795,12 +834,12 @@ public class MdnsServiceTypeClientTests {
assertNull(existingServiceInfo.getAttributeByKey("key")); assertNull(existingServiceInfo.getAttributeByKey("key"));
// Process a goodbye message for the existing response. // Process a goodbye message for the existing response.
client.processResponse(createResponse( processResponse(createResponse(
"service-instance-1", "192.168.1.1", 5353, "service-instance-1", "192.168.1.1", 5353,
SERVICE_TYPE_LABELS, SERVICE_TYPE_LABELS,
Collections.emptyMap(), /* ptrTtlMillis= */ 0L), socketKey); Collections.emptyMap(), /* ptrTtlMillis= */ 0L), socketKey);
client.startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
// 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.
@@ -814,7 +853,7 @@ public class MdnsServiceTypeClientTests {
final String serviceInstanceName = "service-instance-1"; final String serviceInstanceName = "service-instance-1";
client = client =
new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor, new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
mockDecoderClock, socketKey, mockSharedLog) { mockDecoderClock, socketKey, mockSharedLog, thread.getLooper()) {
@Override @Override
MdnsPacketWriter createMdnsPacketWriter() { MdnsPacketWriter createMdnsPacketWriter() {
return mockPacketWriter; return mockPacketWriter;
@@ -824,11 +863,11 @@ public class MdnsServiceTypeClientTests {
.setRemoveExpiredService(true) .setRemoveExpiredService(true)
.setNumOfQueriesBeforeBackoff(Integer.MAX_VALUE) .setNumOfQueriesBeforeBackoff(Integer.MAX_VALUE)
.build(); .build();
client.startSendAndReceive(mockListenerOne, searchOptions); startSendAndReceive(mockListenerOne, searchOptions);
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable(); Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
// Process the initial response. // Process the initial response.
client.processResponse(createResponse( processResponse(createResponse(
serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE", serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE",
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
@@ -857,17 +896,17 @@ public class MdnsServiceTypeClientTests {
final String serviceInstanceName = "service-instance-1"; final String serviceInstanceName = "service-instance-1";
client = client =
new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor, new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
mockDecoderClock, socketKey, mockSharedLog) { mockDecoderClock, socketKey, mockSharedLog, thread.getLooper()) {
@Override @Override
MdnsPacketWriter createMdnsPacketWriter() { MdnsPacketWriter createMdnsPacketWriter() {
return mockPacketWriter; return mockPacketWriter;
} }
}; };
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable(); Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
// Process the initial response. // Process the initial response.
client.processResponse(createResponse( processResponse(createResponse(
serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE", serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE",
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
@@ -890,17 +929,17 @@ public class MdnsServiceTypeClientTests {
final String serviceInstanceName = "service-instance-1"; final String serviceInstanceName = "service-instance-1";
client = client =
new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor, new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
mockDecoderClock, socketKey, mockSharedLog) { mockDecoderClock, socketKey, mockSharedLog, thread.getLooper()) {
@Override @Override
MdnsPacketWriter createMdnsPacketWriter() { MdnsPacketWriter createMdnsPacketWriter() {
return mockPacketWriter; return mockPacketWriter;
} }
}; };
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable(); Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
// Process the initial response. // Process the initial response.
client.processResponse(createResponse( processResponse(createResponse(
serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE", serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE",
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
@@ -921,27 +960,27 @@ public class MdnsServiceTypeClientTests {
final String serviceName = "service-instance"; final String serviceName = "service-instance";
final String ipV4Address = "192.0.2.0"; final String ipV4Address = "192.0.2.0";
final String ipV6Address = "2001:db8::"; final String ipV6Address = "2001:db8::";
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
InOrder inOrder = inOrder(mockListenerOne); InOrder inOrder = inOrder(mockListenerOne);
// Process the initial response which is incomplete. // Process the initial response which is incomplete.
final String subtype = "ABCDE"; final String subtype = "ABCDE";
client.processResponse(createResponse( processResponse(createResponse(
serviceName, null, 5353, subtype, serviceName, null, 5353, subtype,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
// Process a second response which has ip address to make response become complete. // Process a second response which has ip address to make response become complete.
client.processResponse(createResponse( processResponse(createResponse(
serviceName, ipV4Address, 5353, subtype, serviceName, ipV4Address, 5353, subtype,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
// Process a third response with a different ip address, port and updated text attributes. // Process a third response with a different ip address, port and updated text attributes.
client.processResponse(createResponse( processResponse(createResponse(
serviceName, ipV6Address, 5354, subtype, serviceName, ipV6Address, 5354, subtype,
Collections.singletonMap("key", "value"), TEST_TTL), socketKey); Collections.singletonMap("key", "value"), TEST_TTL), socketKey);
// Process the last response which is goodbye message (with the main type, not subtype). // Process the last response which is goodbye message (with the main type, not subtype).
client.processResponse(createResponse( processResponse(createResponse(
serviceName, ipV6Address, 5354, SERVICE_TYPE_LABELS, serviceName, ipV6Address, 5354, SERVICE_TYPE_LABELS,
Collections.singletonMap("key", "value"), /* ptrTtlMillis= */ 0L), Collections.singletonMap("key", "value"), /* ptrTtlMillis= */ 0L),
socketKey); socketKey);
@@ -1009,8 +1048,8 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void testProcessResponse_Resolve() throws Exception { public void testProcessResponse_Resolve() throws Exception {
client = new MdnsServiceTypeClient( client = new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
SERVICE_TYPE, mockSocketClient, currentThreadExecutor, socketKey, mockSharedLog); socketKey, mockSharedLog, thread.getLooper());
final String instanceName = "service-instance"; final String instanceName = "service-instance";
final String[] hostname = new String[] { "testhost "}; final String[] hostname = new String[] { "testhost "};
@@ -1020,7 +1059,7 @@ public class MdnsServiceTypeClientTests {
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder() final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
.setResolveInstanceName(instanceName).build(); .setResolveInstanceName(instanceName).build();
client.startSendAndReceive(mockListenerOne, resolveOptions); startSendAndReceive(mockListenerOne, resolveOptions);
InOrder inOrder = inOrder(mockListenerOne, mockSocketClient); InOrder inOrder = inOrder(mockListenerOne, mockSocketClient);
// Verify a query for SRV/TXT was sent, but no PTR query // Verify a query for SRV/TXT was sent, but no PTR query
@@ -1053,7 +1092,7 @@ public class MdnsServiceTypeClientTests {
Collections.emptyList() /* authorityRecords */, Collections.emptyList() /* authorityRecords */,
Collections.emptyList() /* additionalRecords */); Collections.emptyList() /* additionalRecords */);
client.processResponse(srvTxtResponse, socketKey); processResponse(srvTxtResponse, socketKey);
// Expect a query for A/AAAA // Expect a query for A/AAAA
final ArgumentCaptor<DatagramPacket> addressQueryCaptor = final ArgumentCaptor<DatagramPacket> addressQueryCaptor =
@@ -1083,7 +1122,7 @@ public class MdnsServiceTypeClientTests {
Collections.emptyList() /* additionalRecords */); Collections.emptyList() /* additionalRecords */);
inOrder.verify(mockListenerOne, never()).onServiceNameDiscovered(any()); inOrder.verify(mockListenerOne, never()).onServiceNameDiscovered(any());
client.processResponse(addressResponse, socketKey); processResponse(addressResponse, socketKey);
inOrder.verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture()); inOrder.verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
verifyServiceInfo(serviceInfoCaptor.getValue(), verifyServiceInfo(serviceInfoCaptor.getValue(),
@@ -1100,7 +1139,7 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void testRenewTxtSrvInResolve() throws Exception { public void testRenewTxtSrvInResolve() throws Exception {
client = new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor, client = new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
mockDecoderClock, socketKey, mockSharedLog); mockDecoderClock, socketKey, mockSharedLog, thread.getLooper());
final String instanceName = "service-instance"; final String instanceName = "service-instance";
final String[] hostname = new String[] { "testhost "}; final String[] hostname = new String[] { "testhost "};
@@ -1110,7 +1149,7 @@ public class MdnsServiceTypeClientTests {
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder() final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
.setResolveInstanceName(instanceName).build(); .setResolveInstanceName(instanceName).build();
client.startSendAndReceive(mockListenerOne, resolveOptions); startSendAndReceive(mockListenerOne, resolveOptions);
InOrder inOrder = inOrder(mockListenerOne, mockSocketClient); InOrder inOrder = inOrder(mockListenerOne, mockSocketClient);
// Get the query for SRV/TXT // Get the query for SRV/TXT
@@ -1147,7 +1186,7 @@ public class MdnsServiceTypeClientTests {
InetAddresses.parseNumericAddress(ipV6Address))), InetAddresses.parseNumericAddress(ipV6Address))),
Collections.emptyList() /* authorityRecords */, Collections.emptyList() /* authorityRecords */,
Collections.emptyList() /* additionalRecords */); Collections.emptyList() /* additionalRecords */);
client.processResponse(srvTxtResponse, socketKey); processResponse(srvTxtResponse, socketKey);
inOrder.verify(mockListenerOne).onServiceNameDiscovered(any()); inOrder.verify(mockListenerOne).onServiceNameDiscovered(any());
inOrder.verify(mockListenerOne).onServiceFound(any()); inOrder.verify(mockListenerOne).onServiceFound(any());
@@ -1192,7 +1231,7 @@ public class MdnsServiceTypeClientTests {
InetAddresses.parseNumericAddress(ipV6Address))), InetAddresses.parseNumericAddress(ipV6Address))),
Collections.emptyList() /* authorityRecords */, Collections.emptyList() /* authorityRecords */,
Collections.emptyList() /* additionalRecords */); Collections.emptyList() /* additionalRecords */);
client.processResponse(refreshedSrvTxtResponse, socketKey); processResponse(refreshedSrvTxtResponse, socketKey);
// Advance time to updatedReceiptTime + 1, expected no refresh query because the cache // Advance time to updatedReceiptTime + 1, expected no refresh query because the cache
// should contain the record that have update last receipt time. // should contain the record that have update last receipt time.
@@ -1203,8 +1242,8 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void testProcessResponse_ResolveExcludesOtherServices() { public void testProcessResponse_ResolveExcludesOtherServices() {
client = new MdnsServiceTypeClient( client = new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
SERVICE_TYPE, mockSocketClient, currentThreadExecutor, socketKey, mockSharedLog); socketKey, mockSharedLog, thread.getLooper());
final String requestedInstance = "instance1"; final String requestedInstance = "instance1";
final String otherInstance = "instance2"; final String otherInstance = "instance2";
@@ -1216,28 +1255,28 @@ public class MdnsServiceTypeClientTests {
// Use different case in the options // Use different case in the options
.setResolveInstanceName(capitalizedRequestInstance).build(); .setResolveInstanceName(capitalizedRequestInstance).build();
client.startSendAndReceive(mockListenerOne, resolveOptions); startSendAndReceive(mockListenerOne, resolveOptions);
client.startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
// Complete response from instanceName // Complete response from instanceName
client.processResponse(createResponse( processResponse(createResponse(
requestedInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS, requestedInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS,
Collections.emptyMap() /* textAttributes */, TEST_TTL), Collections.emptyMap() /* textAttributes */, TEST_TTL),
socketKey); socketKey);
// Complete response from otherInstanceName // Complete response from otherInstanceName
client.processResponse(createResponse( processResponse(createResponse(
otherInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS, otherInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS,
Collections.emptyMap() /* textAttributes */, TEST_TTL), Collections.emptyMap() /* textAttributes */, TEST_TTL),
socketKey); socketKey);
// Address update from otherInstanceName // Address update from otherInstanceName
client.processResponse(createResponse( processResponse(createResponse(
otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS, otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
// Goodbye from otherInstanceName // Goodbye from otherInstanceName
client.processResponse(createResponse( processResponse(createResponse(
otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS, otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS,
Collections.emptyMap(), 0L /* ttl */), socketKey); Collections.emptyMap(), 0L /* ttl */), socketKey);
@@ -1267,8 +1306,8 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void testProcessResponse_SubtypeDiscoveryLimitedToSubtype() { public void testProcessResponse_SubtypeDiscoveryLimitedToSubtype() {
client = new MdnsServiceTypeClient( client = new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
SERVICE_TYPE, mockSocketClient, currentThreadExecutor, socketKey, mockSharedLog); socketKey, mockSharedLog, thread.getLooper());
final String matchingInstance = "instance1"; final String matchingInstance = "instance1";
final String subtype = "_subtype"; final String subtype = "_subtype";
@@ -1280,8 +1319,8 @@ public class MdnsServiceTypeClientTests {
// Search with different case. Note MdnsSearchOptions subtype doesn't start with "_" // Search with different case. Note MdnsSearchOptions subtype doesn't start with "_"
.addSubtype("Subtype").build(); .addSubtype("Subtype").build();
client.startSendAndReceive(mockListenerOne, options); startSendAndReceive(mockListenerOne, options);
client.startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions()); startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
// Complete response from instanceName // Complete response from instanceName
final MdnsPacket packetWithoutSubtype = createResponse( final MdnsPacket packetWithoutSubtype = createResponse(
@@ -1304,21 +1343,21 @@ public class MdnsServiceTypeClientTests {
newAnswers, newAnswers,
packetWithoutSubtype.authorityRecords, packetWithoutSubtype.authorityRecords,
packetWithoutSubtype.additionalRecords); packetWithoutSubtype.additionalRecords);
client.processResponse(packetWithSubtype, socketKey); processResponse(packetWithSubtype, socketKey);
// Complete response from otherInstanceName, without subtype // Complete response from otherInstanceName, without subtype
client.processResponse(createResponse( processResponse(createResponse(
otherInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS, otherInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS,
Collections.emptyMap() /* textAttributes */, TEST_TTL), Collections.emptyMap() /* textAttributes */, TEST_TTL),
socketKey); socketKey);
// Address update from otherInstanceName // Address update from otherInstanceName
client.processResponse(createResponse( processResponse(createResponse(
otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS, otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS,
Collections.emptyMap(), TEST_TTL), socketKey); Collections.emptyMap(), TEST_TTL), socketKey);
// Goodbye from otherInstanceName // Goodbye from otherInstanceName
client.processResponse(createResponse( processResponse(createResponse(
otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS, otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS,
Collections.emptyMap(), 0L /* ttl */), socketKey); Collections.emptyMap(), 0L /* ttl */), socketKey);
@@ -1348,8 +1387,8 @@ public class MdnsServiceTypeClientTests {
@Test @Test
public void testNotifySocketDestroyed() throws Exception { public void testNotifySocketDestroyed() throws Exception {
client = new MdnsServiceTypeClient( client = new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
SERVICE_TYPE, mockSocketClient, currentThreadExecutor, socketKey, mockSharedLog); socketKey, mockSharedLog, thread.getLooper());
final String requestedInstance = "instance1"; final String requestedInstance = "instance1";
final String otherInstance = "instance2"; final String otherInstance = "instance2";
@@ -1359,11 +1398,11 @@ public class MdnsServiceTypeClientTests {
.setNumOfQueriesBeforeBackoff(Integer.MAX_VALUE) .setNumOfQueriesBeforeBackoff(Integer.MAX_VALUE)
.setResolveInstanceName("instance1").build(); .setResolveInstanceName("instance1").build();
client.startSendAndReceive(mockListenerOne, resolveOptions); 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, startSendAndReceive(mockListenerTwo,
MdnsSearchOptions.newBuilder().setNumOfQueriesBeforeBackoff( MdnsSearchOptions.newBuilder().setNumOfQueriesBeforeBackoff(
Integer.MAX_VALUE).build()); Integer.MAX_VALUE).build());
@@ -1375,19 +1414,19 @@ public class MdnsServiceTypeClientTests {
TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS); TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
// Complete response from instanceName // Complete response from instanceName
client.processResponse(createResponse( processResponse(createResponse(
requestedInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS, requestedInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS,
Collections.emptyMap() /* textAttributes */, TEST_TTL), Collections.emptyMap() /* textAttributes */, TEST_TTL),
socketKey); socketKey);
// Complete response from otherInstanceName // Complete response from otherInstanceName
client.processResponse(createResponse( processResponse(createResponse(
otherInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS, otherInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS,
Collections.emptyMap() /* textAttributes */, TEST_TTL), Collections.emptyMap() /* textAttributes */, TEST_TTL),
socketKey); socketKey);
verify(expectedSendFutures[1], never()).cancel(true); verify(expectedSendFutures[1], never()).cancel(true);
client.notifySocketDestroyed(); notifySocketDestroyed();
verify(expectedSendFutures[1]).cancel(true); verify(expectedSendFutures[1]).cancel(true);
// mockListenerOne gets notified for the requested instance // mockListenerOne gets notified for the requested instance