Use a TAP test network for MeshCoP service test cases

Previously we were using TUN test network which is not eligible for mDNS
operations. The tests are flaky because we need to depend on other test
cases to connect to WiFi, which is not guaranteed. We'll use the TAP
test network to fix it.

Bug: 327306555
Bug: 327306158
Bug: 327306608

Change-Id: Ia6de8a507578dbdeea4a7ceaf52f417acf35baa2
diff --git a/thread/tests/cts/Android.bp b/thread/tests/cts/Android.bp
index 676eb0e..c1cf0a0 100644
--- a/thread/tests/cts/Android.bp
+++ b/thread/tests/cts/Android.bp
@@ -42,6 +42,7 @@
         "guava",
         "guava-android-testlib",
         "net-tests-utils",
+        "ThreadNetworkTestUtils",
         "truth",
     ],
     libs: [
diff --git a/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java b/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java
index 3bec36b..9549656 100644
--- a/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java
+++ b/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkControllerTest.java
@@ -17,7 +17,6 @@
 package android.net.thread.cts;
 
 import static android.Manifest.permission.ACCESS_NETWORK_STATE;
-import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
 import static android.net.thread.ThreadNetworkController.DEVICE_ROLE_CHILD;
 import static android.net.thread.ThreadNetworkController.DEVICE_ROLE_LEADER;
 import static android.net.thread.ThreadNetworkController.DEVICE_ROLE_ROUTER;
@@ -33,7 +32,6 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
-import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
 import static com.android.testutils.TestPermissionUtil.runAsShell;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -48,7 +46,6 @@
 
 import android.content.Context;
 import android.net.ConnectivityManager;
-import android.net.LinkAddress;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
@@ -62,7 +59,9 @@
 import android.net.thread.ThreadNetworkController.StateCallback;
 import android.net.thread.ThreadNetworkException;
 import android.net.thread.ThreadNetworkManager;
+import android.net.thread.utils.TapTestNetworkTracker;
 import android.os.Build;
+import android.os.HandlerThread;
 import android.os.OutcomeReceiver;
 
 import androidx.annotation.NonNull;
@@ -74,7 +73,6 @@
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
 import com.android.testutils.DevSdkIgnoreRunner;
 import com.android.testutils.FunctionalUtils.ThrowingRunnable;
-import com.android.testutils.TestNetworkTracker;
 
 import org.junit.After;
 import org.junit.Before;
@@ -110,7 +108,7 @@
     private static final int NETWORK_CALLBACK_TIMEOUT_MILLIS = 10 * 1000;
     private static final int CALLBACK_TIMEOUT_MILLIS = 1_000;
     private static final int ENABLED_TIMEOUT_MILLIS = 2_000;
-    private static final int SERVICE_DISCOVERY_TIMEOUT_MILLIS = 10 * 1000;
+    private static final int SERVICE_DISCOVERY_TIMEOUT_MILLIS = 30_000;
     private static final String MESHCOP_SERVICE_TYPE = "_meshcop._udp";
     private static final String THREAD_NETWORK_PRIVILEGED =
             "android.permission.THREAD_NETWORK_PRIVILEGED";
@@ -123,6 +121,8 @@
     private NsdManager mNsdManager;
 
     private Set<String> mGrantedPermissions;
+    private HandlerThread mHandlerThread;
+    private TapTestNetworkTracker mTestNetworkTracker;
 
     @Before
     public void setUp() throws Exception {
@@ -141,6 +141,8 @@
         setEnabledAndWait(mController, true);
 
         mNsdManager = mContext.getSystemService(NsdManager.class);
+        mHandlerThread = new HandlerThread(this.getClass().getSimpleName());
+        mHandlerThread.start();
     }
 
     @After
@@ -152,6 +154,7 @@
             future.get(LEAVE_TIMEOUT_MILLIS, MILLISECONDS);
         }
         dropAllPermissions();
+        tearDownTestNetwork();
     }
 
     @Test
@@ -829,7 +832,7 @@
 
     @Test
     public void meshcopService_threadEnabledButNotJoined_discoveredButNoNetwork() throws Exception {
-        TestNetworkTracker testNetwork = setUpTestNetwork();
+        setUpTestNetwork();
 
         setEnabledAndWait(mController, true);
         leaveAndWait(mController);
@@ -845,13 +848,11 @@
         assertThat(txtMap.get("rv")).isNotNull();
         assertThat(txtMap.get("tv")).isNotNull();
         assertThat(txtMap.get("sb")).isNotNull();
-
-        tearDownTestNetwork(testNetwork);
     }
 
     @Test
     public void meshcopService_joinedNetwork_discoveredHasNetwork() throws Exception {
-        TestNetworkTracker testNetwork = setUpTestNetwork();
+        setUpTestNetwork();
 
         String networkName = "TestNet" + new Random().nextInt(10_000);
         joinRandomizedDatasetAndWait(mController, networkName);
@@ -872,27 +873,26 @@
         assertThat(txtMap.get("tv")).isNotNull();
         assertThat(txtMap.get("sb")).isNotNull();
         assertThat(txtMap.get("id").length).isEqualTo(16);
-
-        tearDownTestNetwork(testNetwork);
     }
 
     @Test
     public void meshcopService_threadDisabled_notDiscovered() throws Exception {
-        TestNetworkTracker testNetwork = setUpTestNetwork();
+        setUpTestNetwork();
 
         CompletableFuture<NsdServiceInfo> serviceLostFuture = new CompletableFuture<>();
         NsdManager.DiscoveryListener listener =
                 discoverForServiceLost(MESHCOP_SERVICE_TYPE, serviceLostFuture);
         setEnabledAndWait(mController, false);
-
         try {
-            serviceLostFuture.get(10_000, MILLISECONDS);
+            serviceLostFuture.get(SERVICE_DISCOVERY_TIMEOUT_MILLIS, MILLISECONDS);
+        } catch (InterruptedException | ExecutionException | TimeoutException ignored) {
+            // It's fine if the service lost event didn't show up. The service may not ever be
+            // advertised.
         } finally {
             mNsdManager.stopServiceDiscovery(listener);
         }
-        assertThrows(TimeoutException.class, () -> discoverService(MESHCOP_SERVICE_TYPE));
 
-        tearDownTestNetwork(testNetwork);
+        assertThrows(TimeoutException.class, () -> discoverService(MESHCOP_SERVICE_TYPE));
     }
 
     private static void dropAllPermissions() {
@@ -1163,14 +1163,17 @@
         }
     }
 
-    TestNetworkTracker setUpTestNetwork() {
-        return runAsShell(
-                MANAGE_TEST_NETWORKS,
-                () -> initTestNetwork(mContext, new LinkAddress("2001:db8:123::/64"), 10_000));
+    private void setUpTestNetwork() {
+        assertThat(mTestNetworkTracker).isNull();
+        mTestNetworkTracker = new TapTestNetworkTracker(mContext, mHandlerThread.getLooper());
     }
 
-    void tearDownTestNetwork(TestNetworkTracker testNetwork) {
-        runAsShell(MANAGE_TEST_NETWORKS, () -> testNetwork.teardown());
+    private void tearDownTestNetwork() throws InterruptedException {
+        if (mTestNetworkTracker != null) {
+            mTestNetworkTracker.tearDown();
+        }
+        mHandlerThread.quitSafely();
+        mHandlerThread.join();
     }
 
     private static class DefaultDiscoveryListener implements NsdManager.DiscoveryListener {