Merge "Add method to destroy UDP socket" into main
diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java
index 416c6de..cbc7a4f 100644
--- a/framework/src/android/net/TestNetworkManager.java
+++ b/framework/src/android/net/TestNetworkManager.java
@@ -23,8 +23,10 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -196,45 +198,6 @@
     }
 
     /**
-     * Create a tap interface for testing purposes
-     *
-     * @param linkAddrs an array of LinkAddresses to assign to the TAP interface
-     * @return A TestNetworkInterface representing the underlying TAP interface. Close the contained
-     *     ParcelFileDescriptor to tear down the TAP interface.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
-    @NonNull
-    public TestNetworkInterface createTapInterface(@NonNull LinkAddress[] linkAddrs) {
-        try {
-            return mService.createInterface(TAP, CARRIER_UP, BRING_UP, USE_IPV6_PROV_DELAY,
-                    linkAddrs, null /* iface */);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Create a tap interface for testing purposes
-     *
-     * @param bringUp whether to bring up the interface before returning it.
-     *
-     * @return A ParcelFileDescriptor of the underlying TAP interface. Close this to tear down the
-     *     TAP interface.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
-    @NonNull
-    public TestNetworkInterface createTapInterface(boolean bringUp) {
-        try {
-            return mService.createInterface(TAP, CARRIER_UP, bringUp, USE_IPV6_PROV_DELAY,
-                    NO_ADDRS, null /* iface */);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Create a tap interface with a given interface name for testing purposes
      *
      * @param bringUp whether to bring up the interface before returning it.
@@ -258,26 +221,6 @@
     }
 
     /**
-     * Create a tap interface with or without carrier for testing purposes.
-     *
-     * Note: setting carrierUp = false is not supported until kernel version 6.0.
-     *
-     * @param carrierUp whether the created interface has a carrier or not.
-     * @param bringUp whether to bring up the interface before returning it.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
-    @NonNull
-    public TestNetworkInterface createTapInterface(boolean carrierUp, boolean bringUp) {
-        try {
-            return mService.createInterface(TAP, carrierUp, bringUp, USE_IPV6_PROV_DELAY, NO_ADDRS,
-                    null /* iface */);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Create a tap interface for testing purposes.
      *
      * Note: setting carrierUp = false is not supported until kernel version 6.0.
@@ -300,27 +243,6 @@
     }
 
     /**
-     * Create a tap interface for testing purposes.
-     *
-     * @param disableIpv6ProvisioningDelay whether to disable DAD and RS delay.
-     * @param linkAddrs an array of LinkAddresses to assign to the TAP interface
-     * @return A TestNetworkInterface representing the underlying TAP interface. Close the contained
-     *     ParcelFileDescriptor to tear down the TAP interface.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
-    @NonNull
-    public TestNetworkInterface createTapInterface(boolean disableIpv6ProvisioningDelay,
-            @NonNull LinkAddress[] linkAddrs) {
-        try {
-            return mService.createInterface(TAP, CARRIER_UP, BRING_UP, disableIpv6ProvisioningDelay,
-                    linkAddrs, null /* iface */);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Enable / disable carrier on TestNetworkInterface
      *
      * Note: TUNSETCARRIER is not supported until kernel version 5.0.
@@ -337,4 +259,110 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Represents a request to create a tun/tap interface for testing.
+     *
+     * @hide
+     */
+    public static class TestInterfaceRequest {
+        public final boolean isTun;
+        public final boolean hasCarrier;
+        public final boolean bringUp;
+        public final boolean disableIpv6ProvDelay;
+        @Nullable public final String ifname;
+        public final LinkAddress[] linkAddresses;
+
+        private TestInterfaceRequest(boolean isTun, boolean hasCarrier, boolean bringUp,
+                boolean disableProvDelay, @Nullable String ifname, LinkAddress[] linkAddresses) {
+            this.isTun = isTun;
+            this.hasCarrier = hasCarrier;
+            this.bringUp = bringUp;
+            this.disableIpv6ProvDelay = disableProvDelay;
+            this.ifname = ifname;
+            this.linkAddresses = linkAddresses;
+        }
+
+        /**
+         * Builder class for TestInterfaceRequest
+         *
+         * Defaults to a tap interface with carrier that has been brought up.
+         */
+        public static class Builder {
+            private boolean mIsTun = false;
+            private boolean mHasCarrier = true;
+            private boolean mBringUp = true;
+            private boolean mDisableIpv6ProvDelay = false;
+            @Nullable private String mIfname;
+            private List<LinkAddress> mLinkAddresses = new ArrayList<>();
+
+            /** Create tun interface. */
+            public Builder setTun() {
+                mIsTun = true;
+                return this;
+            }
+
+            /** Create tap interface. */
+            public Builder setTap() {
+                mIsTun = false;
+                return this;
+            }
+
+            /** Configure whether the interface has carrier. */
+            public Builder setHasCarrier(boolean hasCarrier) {
+                mHasCarrier = hasCarrier;
+                return this;
+            }
+
+            /** Configure whether the interface should be brought up. */
+            public Builder setBringUp(boolean bringUp) {
+                mBringUp = bringUp;
+                return this;
+            }
+
+            /** Disable DAD and RS delay. */
+            public Builder setDisableIpv6ProvisioningDelay(boolean disableProvDelay) {
+                mDisableIpv6ProvDelay = disableProvDelay;
+                return this;
+            }
+
+            /** Set the interface name. */
+            public Builder setInterfaceName(@Nullable String ifname) {
+                mIfname = ifname;
+                return this;
+            }
+
+            /** The addresses to configure on the interface. */
+            public Builder addLinkAddress(LinkAddress la) {
+                mLinkAddresses.add(la);
+                return this;
+            }
+
+            /** Build TestInterfaceRequest */
+            public TestInterfaceRequest build() {
+                return new TestInterfaceRequest(mIsTun, mHasCarrier, mBringUp,
+                        mDisableIpv6ProvDelay, mIfname, mLinkAddresses.toArray(new LinkAddress[0]));
+            }
+        }
+    }
+
+    /**
+     * Create a TestNetworkInterface (tun or tap) for testing purposes.
+     *
+     * @param request The request describing the interface to create.
+     * @return A TestNetworkInterface representing the underlying tun/tap interface. Close the
+     *         contained ParcelFileDescriptor to tear down the tun/tap interface.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
+    @NonNull
+    public TestNetworkInterface createTestInterface(@NonNull TestInterfaceRequest request) {
+        try {
+            // TODO: Make TestInterfaceRequest parcelable and pass it instead.
+            return mService.createInterface(request.isTun, request.hasCarrier, request.bringUp,
+                    request.disableIpv6ProvDelay, request.linkAddresses, request.ifname);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/networksecurity/TEST_MAPPING b/networksecurity/TEST_MAPPING
index 448ee84..f75bf9a 100644
--- a/networksecurity/TEST_MAPPING
+++ b/networksecurity/TEST_MAPPING
@@ -1,4 +1,9 @@
 {
+  "tethering-mainline-presubmit": [
+    {
+      "name": "NetworkSecurityUnitTests"
+    }
+  ],
   "presubmit": [
     {
       "name": "CtsNetSecConfigCertificateTransparencyTestCases"
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
index 1212e29..d91bd11 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
@@ -564,7 +564,6 @@
             // Never try mDNS on cellular, or on interfaces with incompatible flags
             if (CollectionUtils.contains(transports, TRANSPORT_CELLULAR)
                     || iface.isLoopback()
-                    || iface.isPointToPoint()
                     || iface.isVirtual()
                     || !iface.isUp()) {
                 return false;
diff --git a/service/native/libs/libclat/Android.bp b/service/native/libs/libclat/Android.bp
index 6c1c2c4..9554bd8 100644
--- a/service/native/libs/libclat/Android.bp
+++ b/service/native/libs/libclat/Android.bp
@@ -47,6 +47,7 @@
     srcs: [
         "clatutils_test.cpp",
     ],
+    stl: "libc++_static",
     header_libs: [
         "bpf_connectivity_headers",
     ],
diff --git a/service/src/com/android/server/L2capNetworkProvider.java b/service/src/com/android/server/L2capNetworkProvider.java
index 72bd858..814a068 100644
--- a/service/src/com/android/server/L2capNetworkProvider.java
+++ b/service/src/com/android/server/L2capNetworkProvider.java
@@ -58,8 +58,10 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.HandlerUtils;
 import com.android.net.module.util.ServiceConnectivityJni;
 import com.android.server.net.L2capNetwork;
+import com.android.server.net.L2capPacketForwarder;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -75,7 +77,6 @@
             // BLUETOOTH_CONNECT permission.
             NetworkCapabilities.Builder.withoutDefaultCapabilities()
                     .addTransportType(TRANSPORT_BLUETOOTH)
-                    // TODO: remove NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED.
                     .addCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)
                     .addCapability(NET_CAPABILITY_NOT_CONGESTED)
                     .addCapability(NET_CAPABILITY_NOT_METERED)
@@ -226,6 +227,7 @@
     }
 
     private void destroyAndUnregisterReservedOffer(ReservedServerOffer reservedOffer) {
+        HandlerUtils.ensureRunningOnHandlerThread(mHandler);
         // Ensure the offer still exists if this was posted on the handler.
         if (!mReservedServerOffers.contains(reservedOffer)) return;
         mReservedServerOffers.remove(reservedOffer);
@@ -237,13 +239,15 @@
     @Nullable
     private L2capNetwork createL2capNetwork(BluetoothSocket socket, NetworkCapabilities caps,
             L2capNetwork.ICallback cb) {
+        HandlerUtils.ensureRunningOnHandlerThread(mHandler);
         final String ifname = TUN_IFNAME + String.valueOf(sTunIndex++);
         final ParcelFileDescriptor tunFd = mDeps.createTunInterface(ifname);
         if (tunFd == null) {
             return null;
         }
 
-        return L2capNetwork.create(mHandler, mContext, mProvider, ifname, socket, tunFd, caps, cb);
+        return L2capNetwork.create(
+                mHandler, mContext, mProvider, ifname, socket, tunFd, caps, mDeps, cb);
     }
 
     private static void closeBluetoothSocket(BluetoothSocket socket) {
@@ -269,22 +273,26 @@
             private volatile boolean mIsRunning = true;
 
             public AcceptThread(BluetoothServerSocket serverSocket) {
+                super("L2capNetworkProvider-AcceptThread");
                 mServerSocket = serverSocket;
             }
 
             private void postDestroyAndUnregisterReservedOffer() {
+                // Called on AcceptThread
                 mHandler.post(() -> {
                     destroyAndUnregisterReservedOffer(ReservedServerOffer.this);
                 });
             }
 
             private void postCreateServerNetwork(BluetoothSocket connectedSocket) {
+                // Called on AcceptThread
                 mHandler.post(() -> {
                     final boolean success = createServerNetwork(connectedSocket);
                     if (!success) closeBluetoothSocket(connectedSocket);
                 });
             }
 
+            @Override
             public void run() {
                 while (mIsRunning) {
                     final BluetoothSocket connectedSocket;
@@ -304,6 +312,7 @@
             }
 
             public void tearDown() {
+                HandlerUtils.ensureRunningOnHandlerThread(mHandler);
                 mIsRunning = false;
                 try {
                     // BluetoothServerSocket.close() is thread-safe.
@@ -320,6 +329,7 @@
         }
 
         private boolean createServerNetwork(BluetoothSocket socket) {
+            HandlerUtils.ensureRunningOnHandlerThread(mHandler);
             // It is possible the offer went away.
             if (!mReservedServerOffers.contains(this)) return false;
 
@@ -330,17 +340,19 @@
 
             final L2capNetwork network = createL2capNetwork(socket, mReservedCapabilities,
                     new L2capNetwork.ICallback() {
-                @Override
-                public void onError(L2capNetwork network) {
-                    destroyAndUnregisterReservedOffer(ReservedServerOffer.this);
-                }
-                @Override
-                public void onNetworkUnwanted(L2capNetwork network) {
-                    // Leave reservation in place.
-                    final boolean networkExists = mL2capNetworks.remove(network);
-                    if (!networkExists) return; // already torn down.
-                    network.tearDown();
-                }
+                    @Override
+                    public void onError(L2capNetwork network) {
+                        HandlerUtils.ensureRunningOnHandlerThread(mHandler);
+                        destroyAndUnregisterReservedOffer(ReservedServerOffer.this);
+                    }
+                    @Override
+                    public void onNetworkUnwanted(L2capNetwork network) {
+                        HandlerUtils.ensureRunningOnHandlerThread(mHandler);
+                        // Leave reservation in place.
+                        final boolean networkExists = mL2capNetworks.remove(network);
+                        if (!networkExists) return; // already torn down.
+                        network.tearDown();
+                    }
             });
 
             if (network == null) {
@@ -375,6 +387,7 @@
 
         /** Called when the reservation goes away and the reserved offer must be torn down. */
         public void tearDown() {
+            HandlerUtils.ensureRunningOnHandlerThread(mHandler);
             mAcceptThread.tearDown();
             for (L2capNetwork network : mL2capNetworks) {
                 network.tearDown();
@@ -424,10 +437,12 @@
             private volatile boolean mIsAborted = false;
 
             public ConnectThread(L2capNetworkSpecifier specifier, BluetoothSocket socket) {
+                super("L2capNetworkProvider-ConnectThread");
                 mSpecifier = specifier;
                 mSocket = socket;
             }
 
+            @Override
             public void run() {
                 try {
                     mSocket.connect();
@@ -447,6 +462,7 @@
             }
 
             public void abort() {
+                HandlerUtils.ensureRunningOnHandlerThread(mHandler);
                 mIsAborted = true;
                 // Closing the BluetoothSocket is the only way to unblock connect() because it calls
                 // shutdown on the underlying (connected) SOCK_SEQPACKET.
@@ -462,6 +478,7 @@
 
         private boolean createClientNetwork(L2capNetworkSpecifier specifier,
                 BluetoothSocket socket) {
+            HandlerUtils.ensureRunningOnHandlerThread(mHandler);
             // Check whether request still exists
             final ClientRequestInfo cri = mClientNetworkRequests.get(specifier);
             if (cri == null) return false;
@@ -472,18 +489,20 @@
 
             final L2capNetwork network = createL2capNetwork(socket, caps,
                     new L2capNetwork.ICallback() {
-                // TODO: do not send onUnavailable() after the network has become available. The
-                // right thing to do here is to tearDown the network (if it still exists, because
-                // note that the request might have already been removed in the meantime, so
-                // `network` cannot be used directly.
-                @Override
-                public void onError(L2capNetwork network) {
-                    declareAllNetworkRequestsUnfulfillable(specifier);
-                }
-                @Override
-                public void onNetworkUnwanted(L2capNetwork network) {
-                    declareAllNetworkRequestsUnfulfillable(specifier);
-                }
+                    // TODO: do not send onUnavailable() after the network has become available. The
+                    // right thing to do here is to tearDown the network (if it still exists,
+                    // because note that the request might have already been removed in the
+                    // meantime, so `network` cannot be used directly.
+                    @Override
+                    public void onError(L2capNetwork network) {
+                        HandlerUtils.ensureRunningOnHandlerThread(mHandler);
+                        declareAllNetworkRequestsUnfulfillable(specifier);
+                    }
+                    @Override
+                    public void onNetworkUnwanted(L2capNetwork network) {
+                        HandlerUtils.ensureRunningOnHandlerThread(mHandler);
+                        declareAllNetworkRequestsUnfulfillable(specifier);
+                    }
             });
             if (network == null) return false;
 
@@ -595,6 +614,7 @@
          * Only call this when all associated NetworkRequests have been released.
          */
         private void releaseClientNetworkRequest(ClientRequestInfo cri) {
+            HandlerUtils.ensureRunningOnHandlerThread(mHandler);
             mClientNetworkRequests.remove(cri.specifier);
             if (cri.connectThread.isAlive()) {
                 // Note that if ConnectThread succeeds between calling #isAlive() and #abort(), the
@@ -610,6 +630,7 @@
         }
 
         private void declareAllNetworkRequestsUnfulfillable(L2capNetworkSpecifier specifier) {
+            HandlerUtils.ensureRunningOnHandlerThread(mHandler);
             final ClientRequestInfo cri = mClientNetworkRequests.get(specifier);
             if (cri == null) return;
 
@@ -629,6 +650,7 @@
             return thread;
         }
 
+        /** Create a tun interface configured for blocking i/o */
         @Nullable
         public ParcelFileDescriptor createTunInterface(String ifname) {
             final ParcelFileDescriptor fd;
@@ -651,13 +673,19 @@
             }
             return fd;
         }
+
+        /** Create an L2capPacketForwarder and start forwarding */
+        public L2capPacketForwarder createL2capPacketForwarder(Handler handler,
+                ParcelFileDescriptor tunFd, BluetoothSocket socket, boolean compressHeaders,
+                L2capPacketForwarder.ICallback cb) {
+            return new L2capPacketForwarder(handler, tunFd, socket, compressHeaders, cb);
+        }
     }
 
     public L2capNetworkProvider(Context context) {
         this(new Dependencies(), context);
     }
 
-    @VisibleForTesting
     public L2capNetworkProvider(Dependencies deps, Context context) {
         mDeps = deps;
         mContext = context;
diff --git a/service/src/com/android/server/net/L2capNetwork.java b/service/src/com/android/server/net/L2capNetwork.java
index b624bca..c7417f9 100644
--- a/service/src/com/android/server/net/L2capNetwork.java
+++ b/service/src/com/android/server/net/L2capNetwork.java
@@ -38,6 +38,8 @@
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
+import com.android.server.L2capNetworkProvider;
+
 public class L2capNetwork {
     private static final NetworkScore NETWORK_SCORE = new NetworkScore.Builder().build();
     private final String mLogTag;
@@ -115,7 +117,7 @@
 
     public L2capNetwork(String logTag, Handler handler, Context context, NetworkProvider provider,
             BluetoothSocket socket, ParcelFileDescriptor tunFd, NetworkCapabilities nc,
-            LinkProperties lp, ICallback cb) {
+            LinkProperties lp, L2capNetworkProvider.Dependencies deps, ICallback cb) {
         mLogTag = logTag;
         mHandler = handler;
         mNetworkCapabilities = nc;
@@ -123,7 +125,8 @@
         final L2capNetworkSpecifier spec = (L2capNetworkSpecifier) nc.getNetworkSpecifier();
         final boolean compressHeaders = spec.getHeaderCompression() == HEADER_COMPRESSION_6LOWPAN;
 
-        mForwarder = new L2capPacketForwarder(handler, tunFd, socket, compressHeaders, () -> {
+        mForwarder = deps.createL2capPacketForwarder(handler, tunFd, socket, compressHeaders,
+                () -> {
             // TODO: add a check that this callback is invoked on the handler thread.
             cb.onError(L2capNetwork.this);
         });
@@ -146,7 +149,7 @@
     @Nullable
     public static L2capNetwork create(Handler handler, Context context, NetworkProvider provider,
             String ifname, BluetoothSocket socket, ParcelFileDescriptor tunFd,
-            NetworkCapabilities nc, ICallback cb) {
+            NetworkCapabilities nc, L2capNetworkProvider.Dependencies deps, ICallback cb) {
         // TODO: add a check that this function is invoked on the handler thread.
         final String logTag = String.format("L2capNetwork[%s]", ifname);
 
@@ -157,7 +160,8 @@
         final LinkProperties lp = new L2capIpClient(logTag, context, ifname).start();
         if (lp == null) return null;
 
-        return new L2capNetwork(logTag, handler, context, provider, socket, tunFd, nc, lp, cb);
+        return new L2capNetwork(
+                logTag, handler, context, provider, socket, tunFd, nc, lp, deps, cb);
     }
 
     /** Get the NetworkCapabilities used for this Network */
diff --git a/service/src/com/android/server/net/L2capPacketForwarder.java b/service/src/com/android/server/net/L2capPacketForwarder.java
index 00faecf..737cb9c 100644
--- a/service/src/com/android/server/net/L2capPacketForwarder.java
+++ b/service/src/com/android/server/net/L2capPacketForwarder.java
@@ -233,6 +233,7 @@
 
         L2capThread(IReadWriteFd readFd, IReadWriteFd writeFd, boolean isIngress,
                 boolean compressHeaders) {
+            super("L2capNetworkProvider-ForwarderThread");
             mLogTag = isIngress ? "L2capForwarderThread-Ingress" : "L2capForwarderThread-Egress";
             mReadFd = readFd;
             mWriteFd = writeFd;
diff --git a/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt b/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
index 8e790ca..c6a1b09 100644
--- a/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
+++ b/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
@@ -19,8 +19,6 @@
 
 package android.net.cts
 
-import android.Manifest.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG
-import android.Manifest.permission.WRITE_DEVICE_CONFIG
 import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
 import android.content.pm.PackageManager.FEATURE_LEANBACK
 import android.content.pm.PackageManager.FEATURE_WIFI
@@ -55,8 +53,6 @@
 import android.os.SystemProperties
 import android.os.UserManager
 import android.platform.test.annotations.AppModeFull
-import android.provider.DeviceConfig
-import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY
 import android.system.Os
 import android.system.OsConstants
 import android.system.OsConstants.AF_INET6
@@ -90,7 +86,6 @@
 import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
 import com.android.testutils.SkipPresubmit
 import com.android.testutils.TestableNetworkCallback
-import com.android.testutils.runAsShell
 import com.android.testutils.waitForIdle
 import com.google.common.truth.Expect
 import com.google.common.truth.Truth.assertThat
@@ -116,7 +111,6 @@
 
 private const val TAG = "ApfIntegrationTest"
 private const val TIMEOUT_MS = 2000L
-private const val APF_NEW_RA_FILTER_VERSION = "apf_new_ra_filter_version"
 private const val POLLING_INTERVAL_MS: Int = 100
 private const val RCV_BUFFER_SIZE = 1480
 private const val PING_HEADER_LENGTH = 8
@@ -192,16 +186,6 @@
             Thread.sleep(1000)
             // TODO: check that there is no active wifi network. Otherwise, ApfFilter has already been
             // created.
-            // APF adb cmds are only implemented in ApfFilter.java. Enable experiment to prevent
-            // LegacyApfFilter.java from being used.
-            runAsShell(WRITE_DEVICE_CONFIG, WRITE_ALLOWLISTED_DEVICE_CONFIG) {
-                DeviceConfig.setProperty(
-                        NAMESPACE_CONNECTIVITY,
-                        APF_NEW_RA_FILTER_VERSION,
-                        "1",  // value => force enabled
-                        false // makeDefault
-                )
-            }
         }
 
         @AfterClass
diff --git a/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt b/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
index 1de4cf9..ceccf0b 100644
--- a/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
+++ b/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
@@ -44,6 +44,7 @@
 import android.net.RouteInfo
 import android.net.TestNetworkInterface
 import android.net.TestNetworkManager
+import android.net.TestNetworkManager.TestInterfaceRequest
 import android.net.cts.util.CtsNetUtils.TestNetworkCallback
 import android.os.HandlerThread
 import android.os.SystemClock
@@ -164,7 +165,11 @@
 
             // Only statically configure the IPv4 address; for IPv6, use the SLAAC generated
             // address.
-            iface = tnm.createTapInterface(arrayOf(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN)))
+            val req = TestInterfaceRequest.Builder()
+                    .setTap()
+                    .addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN))
+                    .build()
+            iface = tnm.createTestInterface(req)
             assertNotNull(iface)
         }
 
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index 06f2075..9f32132 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -51,6 +51,7 @@
 import android.net.StaticIpConfiguration
 import android.net.TestNetworkInterface
 import android.net.TestNetworkManager
+import android.net.TestNetworkManager.TestInterfaceRequest
 import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.EthernetStateChanged
 import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.InterfaceStateChanged
 import android.os.Build
@@ -169,7 +170,12 @@
                 // false, it is subsequently disabled. This means that the interface may briefly get
                 // link. With IPv6 provisioning delays (RS delay and DAD) disabled, this can cause
                 // tests that expect no network to come up when hasCarrier is false to become flaky.
-                tnm.createTapInterface(hasCarrier, false /* bringUp */)
+                val req = TestInterfaceRequest.Builder()
+                        .setTap()
+                        .setHasCarrier(hasCarrier)
+                        .setBringUp(false)
+                        .build()
+                tnm.createTestInterface(req)
             }
             val mtu = tapInterface.mtu
             packetReader = PollPacketReader(
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
index 1cc9985..f763bae 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
@@ -610,6 +610,7 @@
 
     @Test
     public void testSocketCreatedForMulticastInterface() throws Exception {
+        doReturn(true).when(mTestNetworkIfaceWrapper).isPointToPoint();
         doReturn(true).when(mTestNetworkIfaceWrapper).supportsMulticast();
         startMonitoringSockets();
 
@@ -621,18 +622,6 @@
     }
 
     @Test
-    public void testNoSocketCreatedForPTPInterface() throws Exception {
-        doReturn(true).when(mTestNetworkIfaceWrapper).isPointToPoint();
-        startMonitoringSockets();
-
-        final TestSocketCallback testCallback = new TestSocketCallback();
-        runOnHandler(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback));
-
-        postNetworkAvailable(TRANSPORT_BLUETOOTH);
-        testCallback.expectedNoCallback();
-    }
-
-    @Test
     public void testNoSocketCreatedForVPNInterface() throws Exception {
         // VPN interfaces generally also have IFF_POINTOPOINT, but even if they don't, they should
         // not be included even with TRANSPORT_WIFI.
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt
index d44bd0a..489c3ad 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSL2capProviderTest.kt
@@ -20,42 +20,37 @@
 import android.bluetooth.BluetoothManager
 import android.bluetooth.BluetoothServerSocket
 import android.bluetooth.BluetoothSocket
-import android.content.Context
 import android.net.L2capNetworkSpecifier
 import android.net.L2capNetworkSpecifier.HEADER_COMPRESSION_6LOWPAN
 import android.net.L2capNetworkSpecifier.HEADER_COMPRESSION_NONE
 import android.net.L2capNetworkSpecifier.ROLE_SERVER
-import android.net.NetworkCapabilities
 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED
 import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
 import android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH
-import android.net.NetworkProvider
-import android.net.NetworkProvider.NetworkOfferCallback
 import android.net.NetworkRequest
-import android.net.NetworkScore
 import android.net.NetworkSpecifier
 import android.os.Build
 import android.os.HandlerThread
-import android.os.Looper
-import com.android.server.L2capNetworkProvider
 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
 import com.android.testutils.DevSdkIgnoreRunner
 import com.android.testutils.RecorderCallback.CallbackEntry.Reserved
+import com.android.testutils.RecorderCallback.CallbackEntry.Unavailable
 import com.android.testutils.TestableNetworkCallback
+import com.android.testutils.waitForIdle
 import java.io.IOException
-import java.util.concurrent.Executor
+import java.util.Optional
 import java.util.concurrent.LinkedBlockingQueue
 import kotlin.test.assertEquals
+import kotlin.test.assertFalse
 import kotlin.test.assertNull
 import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Mock
 import org.mockito.Mockito.doAnswer
 import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.doThrow
 import org.mockito.Mockito.mock
-import org.mockito.MockitoAnnotations
 
 private const val PSM = 0x85
 private val REMOTE_MAC = byteArrayOf(1, 2, 3, 4, 5, 6)
@@ -67,14 +62,19 @@
 
 @RunWith(DevSdkIgnoreRunner::class)
 @IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRunner.MonitorThreadLeak
 class CSL2capProviderTest : CSTest() {
     private val btAdapter = mock<BluetoothAdapter>()
     private val btServerSocket = mock<BluetoothServerSocket>()
     private val btSocket = mock<BluetoothSocket>()
     private val providerDeps = mock<L2capNetworkProvider.Dependencies>()
-    private val acceptQueue = LinkedBlockingQueue<BluetoothSocket>()
+    // BlockingQueue does not support put(null) operations, as null is used as an internal sentinel
+    // value. Therefore, use Optional<BluetoothSocket> where an empty optional signals the
+    // BluetoothServerSocket#close() operation.
+    private val acceptQueue = LinkedBlockingQueue<Optional<BluetoothSocket>>()
 
     private val handlerThread = HandlerThread("CSL2capProviderTest thread").apply { start() }
+    private val registeredCallbacks = ArrayList<TestableNetworkCallback>()
 
     // Requires Dependencies mock to be setup before creation.
     private lateinit var provider: L2capNetworkProvider
@@ -83,15 +83,16 @@
     fun innerSetUp() {
         doReturn(btAdapter).`when`(bluetoothManager).getAdapter()
         doReturn(btServerSocket).`when`(btAdapter).listenUsingInsecureL2capChannel()
-        doReturn(PSM).`when`(btServerSocket).getPsm();
+        doReturn(PSM).`when`(btServerSocket).getPsm()
 
         doAnswer {
             val sock = acceptQueue.take()
-            sock ?: throw IOException()
+            if (sock == null || !sock.isPresent()) throw IOException()
+            sock.get()
         }.`when`(btServerSocket).accept()
 
         doAnswer {
-            acceptQueue.put(null)
+            acceptQueue.put(Optional.empty())
         }.`when`(btServerSocket).close()
 
         doReturn(handlerThread).`when`(providerDeps).getHandlerThread()
@@ -101,16 +102,30 @@
 
     @After
     fun innerTearDown() {
+        // Unregistering a callback which has previously been unregistered by virtue of receiving
+        // onUnavailable is a noop.
+        registeredCallbacks.forEach { cm.unregisterNetworkCallback(it) }
+        // Wait for CS handler idle, meaning the unregisterNetworkCallback has been processed and
+        // L2capNetworkProvider has been notified.
+        waitForIdle()
+
+        // While quitSafely() effectively waits for idle, it is not enough, because the tear down
+        // path itself posts on the handler thread. This means that waitForIdle() needs to run
+        // twice. The first time, to ensure all active threads have been joined, and the second time
+        // to run all associated clean up actions.
+        handlerThread.waitForIdle(HANDLER_TIMEOUT_MS)
         handlerThread.quitSafely()
         handlerThread.join()
     }
 
     private fun reserveNetwork(nr: NetworkRequest) = TestableNetworkCallback().also {
         cm.reserveNetwork(nr, csHandler, it)
+        registeredCallbacks.add(it)
     }
 
     private fun requestNetwork(nr: NetworkRequest) = TestableNetworkCallback().also {
         cm.requestNetwork(nr, it, csHandler)
+        registeredCallbacks.add(it)
     }
 
     private fun NetworkRequest.copyWithSpecifier(specifier: NetworkSpecifier): NetworkRequest {
@@ -188,4 +203,42 @@
         nr = REQUEST.copyWithSpecifier(specifier)
         reserveNetwork(nr).assertNoCallback()
     }
+
+    @Test
+    fun testBluetoothException_listenUsingInsecureL2capChannelThrows() {
+        doThrow(IOException()).`when`(btAdapter).listenUsingInsecureL2capChannel()
+        var specifier = L2capNetworkSpecifier.Builder()
+                .setRole(ROLE_SERVER)
+                .setHeaderCompression(HEADER_COMPRESSION_6LOWPAN)
+                .build()
+        var nr = REQUEST.copyWithSpecifier(specifier)
+        reserveNetwork(nr).expect<Unavailable>()
+
+        doReturn(btServerSocket).`when`(btAdapter).listenUsingInsecureL2capChannel()
+        reserveNetwork(nr).expect<Reserved>()
+    }
+
+    @Test
+    fun testBluetoothException_acceptThrows() {
+        doThrow(IOException()).`when`(btServerSocket).accept()
+        var specifier = L2capNetworkSpecifier.Builder()
+                .setRole(ROLE_SERVER)
+                .setHeaderCompression(HEADER_COMPRESSION_6LOWPAN)
+                .build()
+        var nr = REQUEST.copyWithSpecifier(specifier)
+        val cb = reserveNetwork(nr)
+        cb.expect<Reserved>()
+        cb.expect<Unavailable>()
+
+        // BluetoothServerSocket#close() puts Optional.empty() on the acceptQueue.
+        acceptQueue.clear()
+        doAnswer {
+            val sock = acceptQueue.take()
+            assertFalse(sock.isPresent())
+            throw IOException() // to indicate the socket was closed.
+        }.`when`(btServerSocket).accept()
+        val cb2 = reserveNetwork(nr)
+        cb2.expect<Reserved>()
+        cb2.assertNoCallback()
+    }
 }