Update NSD tests without AsyncChannel
Update the tests to use the newer NsdManager based on Binder interfaces
instead of AsyncChannel.
Bug: 190249673
Test: atest NsdManagerTest NsdServiceTest
Change-Id: I0991b598331e335a0bc211f010da7f034fb2441b
diff --git a/tests/unit/java/android/net/nsd/NsdManagerTest.java b/tests/unit/java/android/net/nsd/NsdManagerTest.java
index de77d23..30b8fcd 100644
--- a/tests/unit/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/unit/java/android/net/nsd/NsdManagerTest.java
@@ -20,38 +20,32 @@
import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.os.Build;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
import androidx.test.filters.SmallTest;
-import com.android.internal.util.AsyncChannel;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
-import com.android.testutils.HandlerUtils;
+import com.android.testutils.ExceptionUtils;
-import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -67,9 +61,10 @@
@Mock Context mContext;
@Mock INsdManager mService;
- MockServiceHandler mServiceHandler;
+ @Mock INsdServiceConnector mServiceConn;
NsdManager mManager;
+ INsdManagerCallback mCallback;
long mTimeoutMs = 200; // non-final so that tests can adjust the value.
@@ -77,91 +72,85 @@
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mServiceHandler = spy(MockServiceHandler.create(mContext));
- doReturn(new Messenger(mServiceHandler)).when(mService).getMessenger();
- }
-
- @After
- public void tearDown() throws Exception {
- HandlerUtils.waitForIdle(mServiceHandler, mTimeoutMs);
- mServiceHandler.chan.disconnect();
- mServiceHandler.stop();
- if (mManager != null) {
- mManager.disconnect();
- }
+ doReturn(mServiceConn).when(mService).connect(any());
+ mManager = new NsdManager(mContext, mService);
+ final ArgumentCaptor<INsdManagerCallback> cbCaptor = ArgumentCaptor.forClass(
+ INsdManagerCallback.class);
+ verify(mService).connect(cbCaptor.capture());
+ mCallback = cbCaptor.getValue();
}
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testResolveServiceS() {
- mManager = makeNsdManagerS();
+ public void testResolveServiceS() throws Exception {
+ verify(mServiceConn, never()).startDaemon();
doTestResolveService();
}
@Test
@DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testResolveServicePreS() {
- mManager = makeNsdManagerPreS();
+ public void testResolveServicePreS() throws Exception {
+ verify(mServiceConn).startDaemon();
doTestResolveService();
}
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testDiscoverServiceS() {
- mManager = makeNsdManagerS();
+ public void testDiscoverServiceS() throws Exception {
+ verify(mServiceConn, never()).startDaemon();
doTestDiscoverService();
}
@Test
@DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testDiscoverServicePreS() {
- mManager = makeNsdManagerPreS();
+ public void testDiscoverServicePreS() throws Exception {
+ verify(mServiceConn).startDaemon();
doTestDiscoverService();
}
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testParallelResolveServiceS() {
- mManager = makeNsdManagerS();
+ public void testParallelResolveServiceS() throws Exception {
+ verify(mServiceConn, never()).startDaemon();
doTestParallelResolveService();
}
@Test
@DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testParallelResolveServicePreS() {
- mManager = makeNsdManagerPreS();
+ public void testParallelResolveServicePreS() throws Exception {
+ verify(mServiceConn).startDaemon();
doTestParallelResolveService();
}
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testInvalidCallsS() {
- mManager = makeNsdManagerS();
+ public void testInvalidCallsS() throws Exception {
+ verify(mServiceConn, never()).startDaemon();
doTestInvalidCalls();
}
@Test
@DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testInvalidCallsPreS() {
- mManager = makeNsdManagerPreS();
+ public void testInvalidCallsPreS() throws Exception {
+ verify(mServiceConn).startDaemon();
doTestInvalidCalls();
}
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testRegisterServiceS() {
- mManager = makeNsdManagerS();
+ public void testRegisterServiceS() throws Exception {
+ verify(mServiceConn, never()).startDaemon();
doTestRegisterService();
}
@Test
@DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testRegisterServicePreS() {
- mManager = makeNsdManagerPreS();
+ public void testRegisterServicePreS() throws Exception {
+ verify(mServiceConn).startDaemon();
doTestRegisterService();
}
- public void doTestResolveService() {
+ private void doTestResolveService() throws Exception {
NsdManager manager = mManager;
NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type");
@@ -169,18 +158,19 @@
NsdManager.ResolveListener listener = mock(NsdManager.ResolveListener.class);
manager.resolveService(request, listener);
- int key1 = verifyRequest(NsdManager.RESOLVE_SERVICE);
+ int key1 = getRequestKey(req -> verify(mServiceConn).resolveService(req.capture(), any()));
int err = 33;
- sendResponse(NsdManager.RESOLVE_SERVICE_FAILED, err, key1, null);
+ mCallback.onResolveServiceFailed(key1, err);
verify(listener, timeout(mTimeoutMs).times(1)).onResolveFailed(request, err);
manager.resolveService(request, listener);
- int key2 = verifyRequest(NsdManager.RESOLVE_SERVICE);
- sendResponse(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 0, key2, reply);
+ int key2 = getRequestKey(req ->
+ verify(mServiceConn, times(2)).resolveService(req.capture(), any()));
+ mCallback.onResolveServiceSucceeded(key2, reply);
verify(listener, timeout(mTimeoutMs).times(1)).onServiceResolved(reply);
}
- public void doTestParallelResolveService() {
+ private void doTestParallelResolveService() throws Exception {
NsdManager manager = mManager;
NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type");
@@ -190,19 +180,20 @@
NsdManager.ResolveListener listener2 = mock(NsdManager.ResolveListener.class);
manager.resolveService(request, listener1);
- int key1 = verifyRequest(NsdManager.RESOLVE_SERVICE);
+ int key1 = getRequestKey(req -> verify(mServiceConn).resolveService(req.capture(), any()));
manager.resolveService(request, listener2);
- int key2 = verifyRequest(NsdManager.RESOLVE_SERVICE);
+ int key2 = getRequestKey(req ->
+ verify(mServiceConn, times(2)).resolveService(req.capture(), any()));
- sendResponse(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 0, key2, reply);
- sendResponse(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 0, key1, reply);
+ mCallback.onResolveServiceSucceeded(key2, reply);
+ mCallback.onResolveServiceSucceeded(key1, reply);
verify(listener1, timeout(mTimeoutMs).times(1)).onServiceResolved(reply);
verify(listener2, timeout(mTimeoutMs).times(1)).onServiceResolved(reply);
}
- public void doTestRegisterService() {
+ private void doTestRegisterService() throws Exception {
NsdManager manager = mManager;
NsdServiceInfo request1 = new NsdServiceInfo("a_name", "a_type");
@@ -214,40 +205,43 @@
// Register two services
manager.registerService(request1, PROTOCOL, listener1);
- int key1 = verifyRequest(NsdManager.REGISTER_SERVICE);
+ int key1 = getRequestKey(req -> verify(mServiceConn).registerService(req.capture(), any()));
manager.registerService(request2, PROTOCOL, listener2);
- int key2 = verifyRequest(NsdManager.REGISTER_SERVICE);
+ int key2 = getRequestKey(req ->
+ verify(mServiceConn, times(2)).registerService(req.capture(), any()));
// First reques fails, second request succeeds
- sendResponse(NsdManager.REGISTER_SERVICE_SUCCEEDED, 0, key2, request2);
+ mCallback.onRegisterServiceSucceeded(key2, request2);
verify(listener2, timeout(mTimeoutMs).times(1)).onServiceRegistered(request2);
int err = 1;
- sendResponse(NsdManager.REGISTER_SERVICE_FAILED, err, key1, request1);
+ mCallback.onRegisterServiceFailed(key1, err);
verify(listener1, timeout(mTimeoutMs).times(1)).onRegistrationFailed(request1, err);
// Client retries first request, it succeeds
manager.registerService(request1, PROTOCOL, listener1);
- int key3 = verifyRequest(NsdManager.REGISTER_SERVICE);
+ int key3 = getRequestKey(req ->
+ verify(mServiceConn, times(3)).registerService(req.capture(), any()));
- sendResponse(NsdManager.REGISTER_SERVICE_SUCCEEDED, 0, key3, request1);
+ mCallback.onRegisterServiceSucceeded(key3, request1);
verify(listener1, timeout(mTimeoutMs).times(1)).onServiceRegistered(request1);
// First request is unregistered, it succeeds
manager.unregisterService(listener1);
- int key3again = verifyRequest(NsdManager.UNREGISTER_SERVICE);
+ int key3again = getRequestKey(req -> verify(mServiceConn).unregisterService(req.capture()));
assertEquals(key3, key3again);
- sendResponse(NsdManager.UNREGISTER_SERVICE_SUCCEEDED, 0, key3again, null);
+ mCallback.onUnregisterServiceSucceeded(key3again);
verify(listener1, timeout(mTimeoutMs).times(1)).onServiceUnregistered(request1);
// Second request is unregistered, it fails
manager.unregisterService(listener2);
- int key2again = verifyRequest(NsdManager.UNREGISTER_SERVICE);
+ int key2again = getRequestKey(req ->
+ verify(mServiceConn, times(2)).unregisterService(req.capture()));
assertEquals(key2, key2again);
- sendResponse(NsdManager.UNREGISTER_SERVICE_FAILED, err, key2again, null);
+ mCallback.onUnregisterServiceFailed(key2again, err);
verify(listener2, timeout(mTimeoutMs).times(1)).onUnregistrationFailed(request2, err);
// TODO: do not unregister listener until service is unregistered
@@ -260,7 +254,7 @@
//verify(listener2, timeout(mTimeoutMs).times(1)).onServiceUnregistered(request2);
}
- public void doTestDiscoverService() {
+ private void doTestDiscoverService() throws Exception {
NsdManager manager = mManager;
NsdServiceInfo reply1 = new NsdServiceInfo("a_name", "a_type");
@@ -271,69 +265,73 @@
// Client registers for discovery, request fails
manager.discoverServices("a_type", PROTOCOL, listener);
- int key1 = verifyRequest(NsdManager.DISCOVER_SERVICES);
+ int key1 = getRequestKey(req ->
+ verify(mServiceConn).discoverServices(req.capture(), any()));
int err = 1;
- sendResponse(NsdManager.DISCOVER_SERVICES_FAILED, err, key1, null);
+ mCallback.onDiscoverServicesFailed(key1, err);
verify(listener, timeout(mTimeoutMs).times(1)).onStartDiscoveryFailed("a_type", err);
// Client retries, request succeeds
manager.discoverServices("a_type", PROTOCOL, listener);
- int key2 = verifyRequest(NsdManager.DISCOVER_SERVICES);
+ int key2 = getRequestKey(req ->
+ verify(mServiceConn, times(2)).discoverServices(req.capture(), any()));
- sendResponse(NsdManager.DISCOVER_SERVICES_STARTED, 0, key2, reply1);
+ mCallback.onDiscoverServicesStarted(key2, reply1);
verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStarted("a_type");
// mdns notifies about services
- sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply1);
+ mCallback.onServiceFound(key2, reply1);
verify(listener, timeout(mTimeoutMs).times(1)).onServiceFound(reply1);
- sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply2);
+ mCallback.onServiceFound(key2, reply2);
verify(listener, timeout(mTimeoutMs).times(1)).onServiceFound(reply2);
- sendResponse(NsdManager.SERVICE_LOST, 0, key2, reply2);
+ mCallback.onServiceLost(key2, reply2);
verify(listener, timeout(mTimeoutMs).times(1)).onServiceLost(reply2);
// Client unregisters its listener
manager.stopServiceDiscovery(listener);
- int key2again = verifyRequest(NsdManager.STOP_DISCOVERY);
+ int key2again = getRequestKey(req -> verify(mServiceConn).stopDiscovery(req.capture()));
assertEquals(key2, key2again);
// TODO: unregister listener immediately and stop notifying it about services
// Notifications are still passed to the client's listener
- sendResponse(NsdManager.SERVICE_LOST, 0, key2, reply1);
+ mCallback.onServiceLost(key2, reply1);
verify(listener, timeout(mTimeoutMs).times(1)).onServiceLost(reply1);
// Client is notified of complete unregistration
- sendResponse(NsdManager.STOP_DISCOVERY_SUCCEEDED, 0, key2again, "a_type");
+ mCallback.onStopDiscoverySucceeded(key2again);
verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStopped("a_type");
// Notifications are not passed to the client anymore
- sendResponse(NsdManager.SERVICE_FOUND, 0, key2, reply3);
+ mCallback.onServiceFound(key2, reply3);
verify(listener, timeout(mTimeoutMs).times(0)).onServiceLost(reply3);
// Client registers for service discovery
reset(listener);
manager.discoverServices("a_type", PROTOCOL, listener);
- int key3 = verifyRequest(NsdManager.DISCOVER_SERVICES);
+ int key3 = getRequestKey(req ->
+ verify(mServiceConn, times(3)).discoverServices(req.capture(), any()));
- sendResponse(NsdManager.DISCOVER_SERVICES_STARTED, 0, key3, reply1);
+ mCallback.onDiscoverServicesStarted(key3, reply1);
verify(listener, timeout(mTimeoutMs).times(1)).onDiscoveryStarted("a_type");
// Client unregisters immediately, it fails
manager.stopServiceDiscovery(listener);
- int key3again = verifyRequest(NsdManager.STOP_DISCOVERY);
+ int key3again = getRequestKey(req ->
+ verify(mServiceConn, times(2)).stopDiscovery(req.capture()));
assertEquals(key3, key3again);
err = 2;
- sendResponse(NsdManager.STOP_DISCOVERY_FAILED, err, key3again, "a_type");
+ mCallback.onStopDiscoveryFailed(key3again, err);
verify(listener, timeout(mTimeoutMs).times(1)).onStopDiscoveryFailed("a_type", err);
// New notifications are not passed to the client anymore
- sendResponse(NsdManager.SERVICE_FOUND, 0, key3, reply1);
+ mCallback.onServiceFound(key3, reply1);
verify(listener, timeout(mTimeoutMs).times(0)).onServiceFound(reply1);
}
@@ -398,77 +396,10 @@
}
}
- NsdManager makeNsdManagerS() {
- // Expect we'll get 2 AsyncChannel related msgs.
- return makeManager(2);
- }
-
- NsdManager makeNsdManagerPreS() {
- // Expect we'll get 3 msgs. 2 AsyncChannel related msgs + 1 additional daemon startup msg.
- return makeManager(3);
- }
-
- NsdManager makeManager(int expectedMsgCount) {
- NsdManager manager = new NsdManager(mContext, mService);
- // Acknowledge first two messages connecting the AsyncChannel.
- verify(mServiceHandler, timeout(mTimeoutMs).times(expectedMsgCount)).handleMessage(any());
-
- reset(mServiceHandler);
- assertNotNull(mServiceHandler.chan);
- return manager;
- }
-
- int verifyRequest(int expectedMessageType) {
- HandlerUtils.waitForIdle(mServiceHandler, mTimeoutMs);
- verify(mServiceHandler, timeout(mTimeoutMs)).handleMessage(any());
- reset(mServiceHandler);
- Message received = mServiceHandler.getLastMessage();
- assertEquals(NsdManager.nameOf(expectedMessageType), NsdManager.nameOf(received.what));
- return received.arg2;
- }
-
- void sendResponse(int replyType, int arg, int key, Object obj) {
- mServiceHandler.chan.sendMessage(replyType, arg, key, obj);
- }
-
- // Implements the server side of AsyncChannel connection protocol
- public static class MockServiceHandler extends Handler {
- public final Context context;
- public AsyncChannel chan;
- public Message lastMessage;
-
- MockServiceHandler(Looper l, Context c) {
- super(l);
- context = c;
- }
-
- synchronized Message getLastMessage() {
- return lastMessage;
- }
-
- synchronized void setLastMessage(Message msg) {
- lastMessage = obtainMessage();
- lastMessage.copyFrom(msg);
- }
-
- @Override
- public void handleMessage(Message msg) {
- setLastMessage(msg);
- if (msg.what == AsyncChannel.CMD_CHANNEL_FULL_CONNECTION) {
- chan = new AsyncChannel();
- chan.connect(context, this, msg.replyTo);
- chan.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
- }
- }
-
- void stop() {
- getLooper().quitSafely();
- }
-
- static MockServiceHandler create(Context context) {
- HandlerThread t = new HandlerThread("mock-service-handler");
- t.start();
- return new MockServiceHandler(t.getLooper(), context);
- }
+ int getRequestKey(ExceptionUtils.ThrowingConsumer<ArgumentCaptor<Integer>> verifier)
+ throws Exception {
+ final ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
+ verifier.accept(captor);
+ return captor.getValue();
}
}
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 4d2970a..4172553 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -20,6 +20,7 @@
import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -33,14 +34,19 @@
import android.compat.testing.PlatformCompatChangeRule;
import android.content.ContentResolver;
import android.content.Context;
+import android.net.nsd.INsdManagerCallback;
+import android.net.nsd.INsdServiceConnector;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
+import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
import com.android.server.NsdService.DaemonConnection;
@@ -56,11 +62,15 @@
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import java.util.LinkedList;
+import java.util.Queue;
+
// TODOs:
// - test client can send requests and receive replies
// - test NSD_ON ENABLE/DISABLED listening
@@ -73,6 +83,11 @@
private static final long CLEANUP_DELAY_MS = 500;
private static final long TIMEOUT_MS = 500;
+ // Records INsdManagerCallback created when NsdService#connect is called.
+ // Only accessed on the test thread, since NsdService#connect is called by the NsdManager
+ // constructor called on the test thread.
+ private final Queue<INsdManagerCallback> mCreatedCallbacks = new LinkedList<>();
+
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
@Mock Context mContext;
@@ -83,6 +98,16 @@
HandlerThread mThread;
TestHandler mHandler;
+ private static class LinkToDeathRecorder extends Binder {
+ IBinder.DeathRecipient mDr;
+
+ @Override
+ public void linkToDeath(@NonNull DeathRecipient recipient, int flags) {
+ super.linkToDeath(recipient, flags);
+ mDr = recipient;
+ }
+ }
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -103,26 +128,30 @@
@Test
@DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testPreSClients() {
+ public void testPreSClients() throws Exception {
when(mSettings.isEnabled()).thenReturn(true);
NsdService service = makeService();
// Pre S client connected, the daemon should be started.
- NsdManager client1 = connectClient(service);
+ connectClient(service);
waitForIdle();
+ final INsdManagerCallback cb1 = getCallback();
+ final IBinder.DeathRecipient deathRecipient1 = verifyLinkToDeath(cb1);
verify(mDaemon, times(1)).maybeStart();
verifyDaemonCommands("start-service");
- NsdManager client2 = connectClient(service);
+ connectClient(service);
waitForIdle();
+ final INsdManagerCallback cb2 = getCallback();
+ final IBinder.DeathRecipient deathRecipient2 = verifyLinkToDeath(cb2);
verify(mDaemon, times(1)).maybeStart();
- client1.disconnect();
+ deathRecipient1.binderDied();
// Still 1 client remains, daemon shouldn't be stopped.
waitForIdle();
verify(mDaemon, never()).maybeStop();
- client2.disconnect();
+ deathRecipient2.binderDied();
// All clients are disconnected, the daemon should be stopped.
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
verifyDaemonCommands("stop-service");
@@ -130,43 +159,51 @@
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testNoDaemonStartedWhenClientsConnect() {
+ public void testNoDaemonStartedWhenClientsConnect() throws Exception {
when(mSettings.isEnabled()).thenReturn(true);
-
- NsdService service = makeService();
+ final NsdService service = makeService();
// Creating an NsdManager will not cause any cmds executed, which means
// no daemon is started.
- NsdManager client1 = connectClient(service);
+ connectClient(service);
waitForIdle();
verify(mDaemon, never()).execute(any());
+ final INsdManagerCallback cb1 = getCallback();
+ final IBinder.DeathRecipient deathRecipient1 = verifyLinkToDeath(cb1);
// Creating another NsdManager will not cause any cmds executed.
- NsdManager client2 = connectClient(service);
+ connectClient(service);
waitForIdle();
verify(mDaemon, never()).execute(any());
+ final INsdManagerCallback cb2 = getCallback();
+ final IBinder.DeathRecipient deathRecipient2 = verifyLinkToDeath(cb2);
// If there is no active request, try to clean up the daemon
// every time the client disconnects.
- client1.disconnect();
+ deathRecipient1.binderDied();
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
reset(mDaemon);
- client2.disconnect();
+ deathRecipient2.binderDied();
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
+ }
- client1.disconnect();
- client2.disconnect();
+ private IBinder.DeathRecipient verifyLinkToDeath(INsdManagerCallback cb)
+ throws Exception {
+ final IBinder.DeathRecipient dr = ((LinkToDeathRecorder) cb.asBinder()).mDr;
+ assertNotNull(dr);
+ return dr;
}
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testClientRequestsAreGCedAtDisconnection() {
+ public void testClientRequestsAreGCedAtDisconnection() throws Exception {
when(mSettings.isEnabled()).thenReturn(true);
-
NsdService service = makeService();
- NsdManager client = connectClient(service);
+ NsdManager client = connectClient(service);
waitForIdle();
+ final INsdManagerCallback cb1 = getCallback();
+ final IBinder.DeathRecipient deathRecipient = verifyLinkToDeath(cb1);
verify(mDaemon, never()).maybeStart();
verify(mDaemon, never()).execute(any());
@@ -195,18 +232,16 @@
verifyDaemonCommand("resolve 4 a_name a_type local.");
// Client disconnects, stop the daemon after CLEANUP_DELAY_MS.
- client.disconnect();
+ deathRecipient.binderDied();
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
// checks that request are cleaned
verifyDaemonCommands("stop-register 2", "stop-discover 3",
"stop-resolve 4", "stop-service");
-
- client.disconnect();
}
@Test
@EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)
- public void testCleanupDelayNoRequestActive() {
+ public void testCleanupDelayNoRequestActive() throws Exception {
when(mSettings.isEnabled()).thenReturn(true);
NsdService service = makeService();
@@ -218,6 +253,8 @@
client.registerService(request, PROTOCOL, listener1);
waitForIdle();
verify(mDaemon, times(1)).maybeStart();
+ final INsdManagerCallback cb1 = getCallback();
+ final IBinder.DeathRecipient deathRecipient = verifyLinkToDeath(cb1);
verifyDaemonCommands("start-service", "register 2 a_name a_type 2201");
client.unregisterService(listener1);
@@ -226,7 +263,7 @@
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
verifyDaemonCommand("stop-service");
reset(mDaemon);
- client.disconnect();
+ deathRecipient.binderDied();
// Client disconnects, after CLEANUP_DELAY_MS, maybeStop the daemon.
verifyDelayMaybeStopDaemon(CLEANUP_DELAY_MS);
}
@@ -240,12 +277,29 @@
mDaemonCallback = callback;
return mDaemon;
};
- NsdService service = new NsdService(mContext, mSettings,
- mHandler, supplier, CLEANUP_DELAY_MS);
+ final NsdService service = new NsdService(mContext, mSettings,
+ mHandler, supplier, CLEANUP_DELAY_MS) {
+ @Override
+ public INsdServiceConnector connect(INsdManagerCallback baseCb) {
+ // Wrap the callback in a transparent mock, to mock asBinder returning a
+ // LinkToDeathRecorder. This will allow recording the binder death recipient
+ // registered on the callback. Use a transparent mock and not a spy as the actual
+ // implementation class is not public and cannot be spied on by Mockito.
+ final INsdManagerCallback cb = mock(INsdManagerCallback.class,
+ AdditionalAnswers.delegatesTo(baseCb));
+ doReturn(new LinkToDeathRecorder()).when(cb).asBinder();
+ mCreatedCallbacks.add(cb);
+ return super.connect(cb);
+ }
+ };
verify(mDaemon, never()).execute(any(String.class));
return service;
}
+ private INsdManagerCallback getCallback() {
+ return mCreatedCallbacks.remove();
+ }
+
NsdManager connectClient(NsdService service) {
return new NsdManager(mContext, service);
}