Merge "Instrument SDK level and change IDs to help testing"
diff --git a/Cronet/tests/mts/Android.bp b/Cronet/tests/mts/Android.bp
index 93564e4..4e4251c 100644
--- a/Cronet/tests/mts/Android.bp
+++ b/Cronet/tests/mts/Android.bp
@@ -34,25 +34,13 @@
         "--output $(out)",
 }
 
+// Library to be used in coverage tests. cronet_java_tests can't be used directly because the common
+// tests need to inherit the NetHttpTests manifest.
 android_library {
     name: "NetHttpTestsLibPreJarJar",
-    srcs: [":cronet_aml_javatests_sources"],
+    static_libs: ["cronet_java_tests"],
     sdk_version: "module_current",
     min_sdk_version: "30",
-    static_libs: [
-        "cronet_testserver_utils",
-        "androidx.test.ext.junit",
-        "androidx.test.rules",
-        "junit",
-        "truth",
-    ],
-    libs: [
-        "android.test.base",
-        "framework-connectivity-pre-jarjar",
-        // android.net.TrafficStats apis
-        "framework-connectivity-t",
-    ],
-    lint: { test: true }
 }
 
 android_test {
diff --git a/Cronet/tests/mts/jarjar_excludes.txt b/Cronet/tests/mts/jarjar_excludes.txt
index cf3a017..a3e86de 100644
--- a/Cronet/tests/mts/jarjar_excludes.txt
+++ b/Cronet/tests/mts/jarjar_excludes.txt
@@ -5,6 +5,8 @@
 # cronet_tests.so is not jarjared and uses base classes. We can remove this when there's a
 # separate java base target to depend on.
 org\.chromium\.base\..+
+J\.cronet_tests_N(\$.+)?
+
 # Do not jarjar the tests and its utils as they also do JNI with cronet_tests.so
 org\.chromium\.net\..*Test.*(\$.+)?
 org\.chromium\.net\.NativeTestServer(\$.+)?
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index b88ec7f..23ce1a4 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -195,11 +195,7 @@
     certificate: "networkstack",
     manifest: "AndroidManifest.xml",
     use_embedded_native_libs: true,
-    // The network stack *must* be included to ensure security of the device
-    required: [
-        "NetworkStack",
-        "privapp_allowlist_com.android.tethering",
-    ],
+    required: ["privapp_allowlist_com.android.tethering"],
     apex_available: ["com.android.tethering"],
     lint: { strict_updatability_linting: true },
 }
@@ -215,11 +211,7 @@
     certificate: "networkstack",
     manifest: "AndroidManifest.xml",
     use_embedded_native_libs: true,
-    // The network stack *must* be included to ensure security of the device
-    required: [
-        "NetworkStackNext",
-        "privapp_allowlist_com.android.tethering",
-    ],
+    required: ["privapp_allowlist_com.android.tethering"],
     apex_available: ["com.android.tethering"],
     lint: { strict_updatability_linting: true },
 }
diff --git a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
index 9a67007..866ecba 100644
--- a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
+++ b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
@@ -211,7 +211,7 @@
                         | (expectUnicastResponse ? MdnsConstants.QCLASS_UNICAST : 0));
     }
 
-    private void sendPacketTo(MdnsSocketClientBase requestSender, InetSocketAddress address)
+    private void sendPacketTo(MdnsSocketClient requestSender, InetSocketAddress address)
             throws IOException {
         DatagramPacket packet = packetWriter.getPacket(address);
         if (expectUnicastResponse) {
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
index 0154827..06ca914 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
@@ -17,7 +17,6 @@
 package com.android.server.connectivity.mdns;
 
 import static com.android.server.connectivity.mdns.util.MdnsUtils.ensureRunningOnHandlerThread;
-import static com.android.server.connectivity.mdns.util.MdnsUtils.isNetworkMatched;
 import static com.android.server.connectivity.mdns.util.MdnsUtils.isRunningOnHandlerThread;
 
 import android.Manifest.permission;
@@ -38,6 +37,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * This class keeps tracking the set of registered {@link MdnsServiceBrowserListener} instances, and
@@ -86,15 +86,12 @@
             return list;
         }
 
-        public List<MdnsServiceTypeClient> getByMatchingNetwork(@Nullable Network network) {
+        public List<MdnsServiceTypeClient> getByNetwork(@Nullable Network network) {
             final List<MdnsServiceTypeClient> list = new ArrayList<>();
             for (int i = 0; i < clients.size(); i++) {
                 final Pair<String, Network> perNetworkServiceType = clients.keyAt(i);
                 final Network serviceTypeNetwork = perNetworkServiceType.second;
-                // The serviceTypeNetwork would be null if the MdnsSocketClient is being used. This
-                // is also the case if the socket is for a tethering interface. In either of these
-                // cases, the client is expected to process any responses.
-                if (serviceTypeNetwork == null || isNetworkMatched(network, serviceTypeNetwork)) {
+                if (Objects.equals(network, serviceTypeNetwork)) {
                     list.add(clients.valueAt(i));
                 }
             }
@@ -239,7 +236,7 @@
     private void handleOnResponseReceived(@NonNull MdnsPacket packet, int interfaceIndex,
             @Nullable Network network) {
         for (MdnsServiceTypeClient serviceTypeClient
-                : perNetworkServiceTypeClients.getByMatchingNetwork(network)) {
+                : perNetworkServiceTypeClients.getByNetwork(network)) {
             serviceTypeClient.processResponse(packet, interfaceIndex, network);
         }
     }
@@ -254,7 +251,7 @@
     private void handleOnFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode,
             @Nullable Network network) {
         for (MdnsServiceTypeClient serviceTypeClient
-                : perNetworkServiceTypeClients.getByMatchingNetwork(network)) {
+                : perNetworkServiceTypeClients.getByNetwork(network)) {
             serviceTypeClient.onFailedToParseMdnsResponse(receivedPacketNumber, errorCode);
         }
     }
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
index 52c8622..d6f2d06 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
@@ -17,7 +17,6 @@
 package com.android.server.connectivity.mdns;
 
 import static com.android.server.connectivity.mdns.util.MdnsUtils.ensureRunningOnHandlerThread;
-import static com.android.server.connectivity.mdns.util.MdnsUtils.isNetworkMatched;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,6 +33,7 @@
 import java.net.Inet6Address;
 import java.net.InetSocketAddress;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * The {@link MdnsMultinetworkSocketClient} manages the multinetwork socket for mDns
@@ -216,7 +216,10 @@
             final Network network = activeSockets.valueAt(i);
             // Check ip capability and network before sending packet
             if (((isIpv6 && socket.hasJoinedIpv6()) || (isIpv4 && socket.hasJoinedIpv4()))
-                    && isNetworkMatched(targetNetwork, network)) {
+                    // Contrary to MdnsUtils.isNetworkMatched, only send packets targeting
+                    // the null network to interfaces that have the null network (tethering
+                    // downstream interfaces).
+                    && Objects.equals(network, targetNetwork)) {
                 try {
                     socket.send(packet);
                 } catch (IOException e) {
@@ -248,12 +251,6 @@
         }
     }
 
-    /** Sends a mDNS request packet that asks for multicast response. */
-    @Override
-    public void sendMulticastPacket(@NonNull DatagramPacket packet) {
-        sendMulticastPacket(packet, null /* network */);
-    }
-
     /**
      * Sends a mDNS request packet via given network that asks for multicast response. Null network
      * means sending packet via all networks.
@@ -263,12 +260,6 @@
         mHandler.post(() -> sendMdnsPacket(packet, network));
     }
 
-    /** Sends a mDNS request packet that asks for unicast response. */
-    @Override
-    public void sendUnicastPacket(@NonNull DatagramPacket packet) {
-        sendUnicastPacket(packet, null /* network */);
-    }
-
     /**
      * Sends a mDNS request packet via given network that asks for unicast response. Null network
      * means sending packet via all networks.
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
index e56bd5b..c2c0db2 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
@@ -201,7 +201,7 @@
                     searchOptions.getSubtypes(),
                     searchOptions.isPassiveMode(),
                     ++currentSessionId,
-                    searchOptions.getNetwork());
+                    network);
             if (hadReply) {
                 requestTaskFuture = scheduleNextRunLocked(taskConfig);
             } else {
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
index 783b18a..1144d16 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
@@ -195,13 +195,11 @@
     }
 
     /** Sends a mDNS request packet that asks for multicast response. */
-    @Override
     public void sendMulticastPacket(@NonNull DatagramPacket packet) {
         sendMdnsPacket(packet, multicastPacketQueue);
     }
 
     /** Sends a mDNS request packet that asks for unicast response. */
-    @Override
     public void sendUnicastPacket(DatagramPacket packet) {
         if (useSeparateSocketForUnicast) {
             sendMdnsPacket(packet, unicastPacketQueue);
@@ -210,6 +208,36 @@
         }
     }
 
+    @Override
+    public void sendMulticastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
+        if (network != null) {
+            throw new IllegalArgumentException("This socket client does not support sending to "
+                    + "specific networks");
+        }
+        sendMulticastPacket(packet);
+    }
+
+    @Override
+    public void sendUnicastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
+        if (network != null) {
+            throw new IllegalArgumentException("This socket client does not support sending to "
+                    + "specific networks");
+        }
+        sendUnicastPacket(packet);
+    }
+
+    @Override
+    public void notifyNetworkRequested(
+            @NonNull MdnsServiceBrowserListener listener,
+            @Nullable Network network,
+            @NonNull SocketCreationCallback socketCreationCallback) {
+        if (network != null) {
+            throw new IllegalArgumentException("This socket client does not support requesting "
+                    + "specific networks");
+        }
+        socketCreationCallback.onSocketCreated(null);
+    }
+
     private void sendMdnsPacket(DatagramPacket packet, Queue<DatagramPacket> packetQueueToUse) {
         if (shouldStopSocketLoop && !MdnsConfigs.allowAddMdnsPacketAfterDiscoveryStops()) {
             LOGGER.w("sendMdnsPacket() is called after discovery already stopped");
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
index c614cd3..22cf326 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
@@ -38,35 +38,25 @@
     /*** Set callback for receiving mDns response */
     void setCallback(@Nullable Callback callback);
 
-    /*** Sends a mDNS request packet that asks for multicast response. */
-    void sendMulticastPacket(@NonNull DatagramPacket packet);
+    /**
+     * Send a mDNS request packet via given network that asks for multicast response.
+     *
+     * <p>The socket client may use a null network to identify some or all interfaces, in which case
+     * passing null sends the packet to these.
+     */
+    void sendMulticastPacket(@NonNull DatagramPacket packet, @Nullable Network network);
 
     /**
-     * Sends a mDNS request packet via given network that asks for multicast response. Null network
-     * means sending packet via all networks.
+     * Send a mDNS request packet via given network that asks for unicast response.
+     *
+     * <p>The socket client may use a null network to identify some or all interfaces, in which case
+     * passing null sends the packet to these.
      */
-    default void sendMulticastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
-        throw new UnsupportedOperationException(
-                "This socket client doesn't support per-network sending");
-    }
-
-    /*** Sends a mDNS request packet that asks for unicast response. */
-    void sendUnicastPacket(@NonNull DatagramPacket packet);
-
-    /**
-     * Sends a mDNS request packet via given network that asks for unicast response. Null network
-     * means sending packet via all networks.
-     */
-    default void sendUnicastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
-        throw new UnsupportedOperationException(
-                "This socket client doesn't support per-network sending");
-    }
+    void sendUnicastPacket(@NonNull DatagramPacket packet, @Nullable Network network);
 
     /*** Notify that the given network is requested for mdns discovery / resolution */
-    default void notifyNetworkRequested(@NonNull MdnsServiceBrowserListener listener,
-            @Nullable Network network, @NonNull SocketCreationCallback socketCreationCallback) {
-        socketCreationCallback.onSocketCreated(network);
-    }
+    void notifyNetworkRequested(@NonNull MdnsServiceBrowserListener listener,
+            @Nullable Network network, @NonNull SocketCreationCallback socketCreationCallback);
 
     /*** Notify that the network is unrequested */
     default void notifyNetworkUnrequested(@NonNull MdnsServiceBrowserListener listener) { }
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
index 89776e2..52f2712 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
@@ -18,6 +18,8 @@
 
 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -62,21 +64,24 @@
     private static final String SERVICE_TYPE_2 = "_test._tcp.local";
     private static final Network NETWORK_1 = Mockito.mock(Network.class);
     private static final Network NETWORK_2 = Mockito.mock(Network.class);
-    private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_1 =
+    private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_1_NULL_NETWORK =
             Pair.create(SERVICE_TYPE_1, null);
-    private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_1_1 =
+    private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_1_NETWORK_1 =
             Pair.create(SERVICE_TYPE_1, NETWORK_1);
-    private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_2 =
+    private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_2_NULL_NETWORK =
             Pair.create(SERVICE_TYPE_2, null);
-    private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_2_2 =
+    private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_2_NETWORK_1 =
+            Pair.create(SERVICE_TYPE_2, NETWORK_1);
+    private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_2_NETWORK_2 =
             Pair.create(SERVICE_TYPE_2, NETWORK_2);
 
     @Mock private ExecutorProvider executorProvider;
     @Mock private MdnsSocketClientBase socketClient;
-    @Mock private MdnsServiceTypeClient mockServiceTypeClientOne;
-    @Mock private MdnsServiceTypeClient mockServiceTypeClientOne1;
-    @Mock private MdnsServiceTypeClient mockServiceTypeClientTwo;
-    @Mock private MdnsServiceTypeClient mockServiceTypeClientTwo2;
+    @Mock private MdnsServiceTypeClient mockServiceTypeClientType1NullNetwork;
+    @Mock private MdnsServiceTypeClient mockServiceTypeClientType1Network1;
+    @Mock private MdnsServiceTypeClient mockServiceTypeClientType2NullNetwork;
+    @Mock private MdnsServiceTypeClient mockServiceTypeClientType2Network1;
+    @Mock private MdnsServiceTypeClient mockServiceTypeClientType2Network2;
 
     @Mock MdnsServiceBrowserListener mockListenerOne;
     @Mock MdnsServiceBrowserListener mockListenerTwo;
@@ -99,14 +104,20 @@
                             @Nullable Network network) {
                         final Pair<String, Network> perNetworkServiceType =
                                 Pair.create(serviceType, network);
-                        if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_1)) {
-                            return mockServiceTypeClientOne;
-                        } else if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_1_1)) {
-                            return mockServiceTypeClientOne1;
-                        } else if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_2)) {
-                            return mockServiceTypeClientTwo;
-                        } else if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_2_2)) {
-                            return mockServiceTypeClientTwo2;
+                        if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_1_NULL_NETWORK)) {
+                            return mockServiceTypeClientType1NullNetwork;
+                        } else if (perNetworkServiceType.equals(
+                                PER_NETWORK_SERVICE_TYPE_1_NETWORK_1)) {
+                            return mockServiceTypeClientType1Network1;
+                        } else if (perNetworkServiceType.equals(
+                                PER_NETWORK_SERVICE_TYPE_2_NULL_NETWORK)) {
+                            return mockServiceTypeClientType2NullNetwork;
+                        } else if (perNetworkServiceType.equals(
+                                PER_NETWORK_SERVICE_TYPE_2_NETWORK_1)) {
+                            return mockServiceTypeClientType2Network1;
+                        } else if (perNetworkServiceType.equals(
+                                PER_NETWORK_SERVICE_TYPE_2_NETWORK_2)) {
+                            return mockServiceTypeClientType2Network2;
                         }
                         return null;
                     }
@@ -143,11 +154,12 @@
         final SocketCreationCallback callback = expectSocketCreationCallback(
                 SERVICE_TYPE_1, mockListenerOne, options);
         runOnHandler(() -> callback.onSocketCreated(null /* network */));
-        verify(mockServiceTypeClientOne).startSendAndReceive(mockListenerOne, options);
+        verify(mockServiceTypeClientType1NullNetwork).startSendAndReceive(mockListenerOne, options);
 
-        when(mockServiceTypeClientOne.stopSendAndReceive(mockListenerOne)).thenReturn(true);
+        when(mockServiceTypeClientType1NullNetwork.stopSendAndReceive(mockListenerOne))
+                .thenReturn(true);
         runOnHandler(() -> discoveryManager.unregisterListener(SERVICE_TYPE_1, mockListenerOne));
-        verify(mockServiceTypeClientOne).stopSendAndReceive(mockListenerOne);
+        verify(mockServiceTypeClientType1NullNetwork).stopSendAndReceive(mockListenerOne);
         verify(socketClient).stopDiscovery();
     }
 
@@ -158,16 +170,16 @@
         final SocketCreationCallback callback = expectSocketCreationCallback(
                 SERVICE_TYPE_1, mockListenerOne, options);
         runOnHandler(() -> callback.onSocketCreated(null /* network */));
-        verify(mockServiceTypeClientOne).startSendAndReceive(mockListenerOne, options);
+        verify(mockServiceTypeClientType1NullNetwork).startSendAndReceive(mockListenerOne, options);
         runOnHandler(() -> callback.onSocketCreated(NETWORK_1));
-        verify(mockServiceTypeClientOne1).startSendAndReceive(mockListenerOne, options);
+        verify(mockServiceTypeClientType1Network1).startSendAndReceive(mockListenerOne, options);
 
         final SocketCreationCallback callback2 = expectSocketCreationCallback(
                 SERVICE_TYPE_2, mockListenerTwo, options);
         runOnHandler(() -> callback2.onSocketCreated(null /* network */));
-        verify(mockServiceTypeClientTwo).startSendAndReceive(mockListenerTwo, options);
+        verify(mockServiceTypeClientType2NullNetwork).startSendAndReceive(mockListenerTwo, options);
         runOnHandler(() -> callback2.onSocketCreated(NETWORK_2));
-        verify(mockServiceTypeClientTwo2).startSendAndReceive(mockListenerTwo, options);
+        verify(mockServiceTypeClientType2Network2).startSendAndReceive(mockListenerTwo, options);
     }
 
     @Test
@@ -177,103 +189,106 @@
         final SocketCreationCallback callback = expectSocketCreationCallback(
                 SERVICE_TYPE_1, mockListenerOne, options1);
         runOnHandler(() -> callback.onSocketCreated(null /* network */));
-        verify(mockServiceTypeClientOne).startSendAndReceive(mockListenerOne, options1);
+        verify(mockServiceTypeClientType1NullNetwork).startSendAndReceive(
+                mockListenerOne, options1);
         runOnHandler(() -> callback.onSocketCreated(NETWORK_1));
-        verify(mockServiceTypeClientOne1).startSendAndReceive(mockListenerOne, options1);
+        verify(mockServiceTypeClientType1Network1).startSendAndReceive(mockListenerOne, options1);
 
         final MdnsSearchOptions options2 =
                 MdnsSearchOptions.newBuilder().setNetwork(NETWORK_2).build();
         final SocketCreationCallback callback2 = expectSocketCreationCallback(
                 SERVICE_TYPE_2, mockListenerTwo, options2);
         runOnHandler(() -> callback2.onSocketCreated(NETWORK_2));
-        verify(mockServiceTypeClientTwo2).startSendAndReceive(mockListenerTwo, options2);
+        verify(mockServiceTypeClientType2Network2).startSendAndReceive(mockListenerTwo, options2);
 
         final MdnsPacket responseForServiceTypeOne = createMdnsPacket(SERVICE_TYPE_1);
         final int ifIndex = 1;
         runOnHandler(() -> discoveryManager.onResponseReceived(
                 responseForServiceTypeOne, ifIndex, null /* network */));
-        verify(mockServiceTypeClientOne).processResponse(responseForServiceTypeOne, ifIndex,
-                null /* network */);
-        verify(mockServiceTypeClientOne1).processResponse(responseForServiceTypeOne, ifIndex,
-                null /* network */);
-        verify(mockServiceTypeClientTwo2).processResponse(responseForServiceTypeOne, ifIndex,
-                null /* network */);
+        // Packets for network null are only processed by the ServiceTypeClient for network null
+        verify(mockServiceTypeClientType1NullNetwork).processResponse(responseForServiceTypeOne,
+                ifIndex, null /* network */);
+        verify(mockServiceTypeClientType1Network1, never()).processResponse(any(), anyInt(), any());
+        verify(mockServiceTypeClientType2Network2, never()).processResponse(any(), anyInt(), any());
 
         final MdnsPacket responseForServiceTypeTwo = createMdnsPacket(SERVICE_TYPE_2);
         runOnHandler(() -> discoveryManager.onResponseReceived(
                 responseForServiceTypeTwo, ifIndex, NETWORK_1));
-        verify(mockServiceTypeClientOne).processResponse(responseForServiceTypeTwo, ifIndex,
-                NETWORK_1);
-        verify(mockServiceTypeClientOne1).processResponse(responseForServiceTypeTwo, ifIndex,
-                NETWORK_1);
-        verify(mockServiceTypeClientTwo2, never()).processResponse(responseForServiceTypeTwo,
+        verify(mockServiceTypeClientType1NullNetwork, never()).processResponse(any(), anyInt(),
+                eq(NETWORK_1));
+        verify(mockServiceTypeClientType1Network1).processResponse(responseForServiceTypeTwo,
                 ifIndex, NETWORK_1);
+        verify(mockServiceTypeClientType2Network2, never()).processResponse(any(), anyInt(),
+                eq(NETWORK_1));
 
         final MdnsPacket responseForSubtype =
                 createMdnsPacket("subtype._sub._googlecast._tcp.local");
         runOnHandler(() -> discoveryManager.onResponseReceived(
                 responseForSubtype, ifIndex, NETWORK_2));
-        verify(mockServiceTypeClientOne).processResponse(responseForSubtype, ifIndex, NETWORK_2);
-        verify(mockServiceTypeClientOne1, never()).processResponse(
+        verify(mockServiceTypeClientType1NullNetwork, never()).processResponse(
+                any(), anyInt(), eq(NETWORK_2));
+        verify(mockServiceTypeClientType1Network1, never()).processResponse(
+                any(), anyInt(), eq(NETWORK_2));
+        verify(mockServiceTypeClientType2Network2).processResponse(
                 responseForSubtype, ifIndex, NETWORK_2);
-        verify(mockServiceTypeClientTwo2).processResponse(responseForSubtype, ifIndex, NETWORK_2);
     }
 
     @Test
     public void testSocketCreatedAndDestroyed() throws IOException {
         // Create a ServiceTypeClient for SERVICE_TYPE_1 and NETWORK_1
-        final MdnsSearchOptions options1 =
+        final MdnsSearchOptions network1Options =
                 MdnsSearchOptions.newBuilder().setNetwork(NETWORK_1).build();
         final SocketCreationCallback callback = expectSocketCreationCallback(
-                SERVICE_TYPE_1, mockListenerOne, options1);
+                SERVICE_TYPE_1, mockListenerOne, network1Options);
         runOnHandler(() -> callback.onSocketCreated(NETWORK_1));
-        verify(mockServiceTypeClientOne1).startSendAndReceive(mockListenerOne, options1);
+        verify(mockServiceTypeClientType1Network1).startSendAndReceive(
+                mockListenerOne, network1Options);
 
-        // Create a ServiceTypeClient for SERVICE_TYPE_2 and NETWORK_2
-        final MdnsSearchOptions options2 =
-                MdnsSearchOptions.newBuilder().setNetwork(NETWORK_2).build();
+        // Create a ServiceTypeClient for SERVICE_TYPE_2 and NETWORK_1
         final SocketCreationCallback callback2 = expectSocketCreationCallback(
-                SERVICE_TYPE_2, mockListenerTwo, options2);
-        runOnHandler(() -> callback2.onSocketCreated(NETWORK_2));
-        verify(mockServiceTypeClientTwo2).startSendAndReceive(mockListenerTwo, options2);
+                SERVICE_TYPE_2, mockListenerTwo, network1Options);
+        runOnHandler(() -> callback2.onSocketCreated(NETWORK_1));
+        verify(mockServiceTypeClientType2Network1).startSendAndReceive(
+                mockListenerTwo, network1Options);
 
         // Receive a response, it should be processed on both clients.
         final MdnsPacket response = createMdnsPacket(SERVICE_TYPE_1);
         final int ifIndex = 1;
         runOnHandler(() -> discoveryManager.onResponseReceived(
-                response, ifIndex, null /* network */));
-        verify(mockServiceTypeClientOne1).processResponse(response, ifIndex, null /* network */);
-        verify(mockServiceTypeClientTwo2).processResponse(response, ifIndex, null /* network */);
+                response, ifIndex, NETWORK_1));
+        verify(mockServiceTypeClientType1Network1).processResponse(response, ifIndex, NETWORK_1);
+        verify(mockServiceTypeClientType2Network1).processResponse(response, ifIndex, NETWORK_1);
 
-        // The client for NETWORK_1 receives the callback that the NETWORK_1 has been destroyed,
+        // The first callback receives a notification that the network has been destroyed,
         // mockServiceTypeClientOne1 should send service removed notifications and remove from the
         // list of clients.
         runOnHandler(() -> callback.onAllSocketsDestroyed(NETWORK_1));
-        verify(mockServiceTypeClientOne1).notifySocketDestroyed();
+        verify(mockServiceTypeClientType1Network1).notifySocketDestroyed();
 
-        // Receive a response again, it should be processed only on mockServiceTypeClientTwo2.
-        // Because the mockServiceTypeClientOne1 is removed from the list of clients, it is no
-        // longer able to process responses.
+        // Receive a response again, it should be processed only on
+        // mockServiceTypeClientType2Network1. Because the mockServiceTypeClientType1Network1 is
+        // removed from the list of clients, it is no longer able to process responses.
         runOnHandler(() -> discoveryManager.onResponseReceived(
-                response, ifIndex, null /* network */));
-        verify(mockServiceTypeClientOne1, times(1))
-                .processResponse(response, ifIndex, null /* network */);
-        verify(mockServiceTypeClientTwo2, times(2))
-                .processResponse(response, ifIndex, null /* network */);
+                response, ifIndex, NETWORK_1));
+        // Still times(1) as a response was received once previously
+        verify(mockServiceTypeClientType1Network1, times(1))
+                .processResponse(response, ifIndex, NETWORK_1);
+        verify(mockServiceTypeClientType2Network1, times(2))
+                .processResponse(response, ifIndex, NETWORK_1);
 
-        // The client for NETWORK_2 receives the callback that the NETWORK_1 has been destroyed,
+        // The client for NETWORK_1 receives the callback that the NETWORK_2 has been destroyed,
         // mockServiceTypeClientTwo2 shouldn't send any notifications.
-        runOnHandler(() -> callback2.onAllSocketsDestroyed(NETWORK_1));
-        verify(mockServiceTypeClientTwo2, never()).notifySocketDestroyed();
+        runOnHandler(() -> callback2.onAllSocketsDestroyed(NETWORK_2));
+        verify(mockServiceTypeClientType2Network1, never()).notifySocketDestroyed();
 
-        // Receive a response again, mockServiceTypeClientTwo2 is still in the list of clients, it's
-        // still able to process responses.
+        // Receive a response again, mockServiceTypeClientType2Network1 is still in the list of
+        // clients, it's still able to process responses.
         runOnHandler(() -> discoveryManager.onResponseReceived(
-                response, ifIndex, null /* network */));
-        verify(mockServiceTypeClientOne1, times(1))
-                .processResponse(response, ifIndex, null /* network */);
-        verify(mockServiceTypeClientTwo2, times(3))
-                .processResponse(response, ifIndex, null /* network */);
+                response, ifIndex, NETWORK_1));
+        verify(mockServiceTypeClientType1Network1, times(1))
+                .processResponse(response, ifIndex, NETWORK_1);
+        verify(mockServiceTypeClientType2Network1, times(3))
+                .processResponse(response, ifIndex, NETWORK_1);
     }
 
     private MdnsPacket createMdnsPacket(String serviceType) {
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
index c6137c6..87ba5d7 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
@@ -38,6 +38,7 @@
 import android.os.HandlerThread;
 
 import com.android.net.module.util.HexDump;
+import com.android.server.connectivity.mdns.MdnsSocketClientBase.SocketCreationCallback;
 import com.android.testutils.DevSdkIgnoreRule;
 import com.android.testutils.DevSdkIgnoreRunner;
 import com.android.testutils.HandlerUtils;
@@ -66,7 +67,7 @@
     @Mock private MdnsInterfaceSocket mSocket;
     @Mock private MdnsServiceBrowserListener mListener;
     @Mock private MdnsSocketClientBase.Callback mCallback;
-    @Mock private MdnsSocketClientBase.SocketCreationCallback mSocketCreationCallback;
+    @Mock private SocketCreationCallback mSocketCreationCallback;
     private MdnsMultinetworkSocketClient mSocketClient;
     private Handler mHandler;
 
@@ -113,22 +114,36 @@
                 InetAddresses.parseNumericAddress("192.0.2.1"), 0 /* port */);
         final DatagramPacket ipv6Packet = new DatagramPacket(BUFFER, 0 /* offset */, BUFFER.length,
                 InetAddresses.parseNumericAddress("2001:db8::"), 0 /* port */);
-        doReturn(true).when(mSocket).hasJoinedIpv4();
-        doReturn(true).when(mSocket).hasJoinedIpv6();
-        doReturn(createEmptyNetworkInterface()).when(mSocket).getInterface();
+
+        final MdnsInterfaceSocket tetherIfaceSock1 = mock(MdnsInterfaceSocket.class);
+        final MdnsInterfaceSocket tetherIfaceSock2 = mock(MdnsInterfaceSocket.class);
+        for (MdnsInterfaceSocket socket : List.of(mSocket, tetherIfaceSock1, tetherIfaceSock2)) {
+            doReturn(true).when(socket).hasJoinedIpv4();
+            doReturn(true).when(socket).hasJoinedIpv6();
+            doReturn(createEmptyNetworkInterface()).when(socket).getInterface();
+        }
+
         // Notify socket created
         callback.onSocketCreated(mNetwork, mSocket, List.of());
         verify(mSocketCreationCallback).onSocketCreated(mNetwork);
+        callback.onSocketCreated(null, tetherIfaceSock1, List.of());
+        verify(mSocketCreationCallback).onSocketCreated(null);
+        callback.onSocketCreated(null, tetherIfaceSock2, List.of());
+        verify(mSocketCreationCallback, times(2)).onSocketCreated(null);
 
         // Send packet to IPv4 with target network and verify sending has been called.
         mSocketClient.sendMulticastPacket(ipv4Packet, mNetwork);
         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
         verify(mSocket).send(ipv4Packet);
+        verify(tetherIfaceSock1, never()).send(any());
+        verify(tetherIfaceSock2, never()).send(any());
 
         // Send packet to IPv6 without target network and verify sending has been called.
-        mSocketClient.sendMulticastPacket(ipv6Packet);
+        mSocketClient.sendMulticastPacket(ipv6Packet, null);
         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
-        verify(mSocket).send(ipv6Packet);
+        verify(mSocket, never()).send(ipv6Packet);
+        verify(tetherIfaceSock1).send(ipv6Packet);
+        verify(tetherIfaceSock2).send(ipv6Packet);
     }
 
     @Test
@@ -181,61 +196,86 @@
 
     @Test
     public void testSocketRemovedAfterNetworkUnrequested() throws IOException {
-        // Request a socket
-        final SocketCallback callback = expectSocketCallback(mListener, mNetwork);
+        // Request sockets on all networks
+        final SocketCallback callback = expectSocketCallback(mListener, null);
         final DatagramPacket ipv4Packet = new DatagramPacket(BUFFER, 0 /* offset */, BUFFER.length,
                 InetAddresses.parseNumericAddress("192.0.2.1"), 0 /* port */);
+
+        // Notify 3 socket created, including 2 tethered interfaces (null network)
+        final MdnsInterfaceSocket socket2 = mock(MdnsInterfaceSocket.class);
+        final MdnsInterfaceSocket socket3 = mock(MdnsInterfaceSocket.class);
         doReturn(true).when(mSocket).hasJoinedIpv4();
         doReturn(true).when(mSocket).hasJoinedIpv6();
-        doReturn(createEmptyNetworkInterface()).when(mSocket).getInterface();
-        // Notify socket created
-        callback.onSocketCreated(mNetwork, mSocket, List.of());
-        verify(mSocketCreationCallback).onSocketCreated(mNetwork);
-
-        // Send IPv4 packet and verify sending has been called.
-        mSocketClient.sendMulticastPacket(ipv4Packet);
-        HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
-        verify(mSocket).send(ipv4Packet);
-
-        // Request another socket with null network
-        final MdnsServiceBrowserListener listener2 = mock(MdnsServiceBrowserListener.class);
-        final Network network2 = mock(Network.class);
-        final MdnsInterfaceSocket socket2 = mock(MdnsInterfaceSocket.class);
-        final SocketCallback callback2 = expectSocketCallback(listener2, null);
         doReturn(true).when(socket2).hasJoinedIpv4();
         doReturn(true).when(socket2).hasJoinedIpv6();
+        doReturn(true).when(socket3).hasJoinedIpv4();
+        doReturn(true).when(socket3).hasJoinedIpv6();
+        doReturn(createEmptyNetworkInterface()).when(mSocket).getInterface();
         doReturn(createEmptyNetworkInterface()).when(socket2).getInterface();
-        // Notify socket created for two networks.
-        callback2.onSocketCreated(mNetwork, mSocket, List.of());
-        callback2.onSocketCreated(network2, socket2, List.of());
-        verify(mSocketCreationCallback, times(2)).onSocketCreated(mNetwork);
-        verify(mSocketCreationCallback).onSocketCreated(network2);
+        doReturn(createEmptyNetworkInterface()).when(socket3).getInterface();
 
-        // Send IPv4 packet and verify sending to two sockets.
-        mSocketClient.sendMulticastPacket(ipv4Packet);
+        callback.onSocketCreated(mNetwork, mSocket, List.of());
+        callback.onSocketCreated(null, socket2, List.of());
+        callback.onSocketCreated(null, socket3, List.of());
+        verify(mSocketCreationCallback).onSocketCreated(mNetwork);
+        verify(mSocketCreationCallback, times(2)).onSocketCreated(null);
+
+        // Send IPv4 packet on the non-null Network and verify sending has been called.
+        mSocketClient.sendMulticastPacket(ipv4Packet, mNetwork);
         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
-        verify(mSocket, times(2)).send(ipv4Packet);
-        verify(socket2).send(ipv4Packet);
+        verify(mSocket).send(ipv4Packet);
+        verify(socket2, never()).send(any());
+        verify(socket3, never()).send(any());
 
-        // Unrequest another socket
+        // Request another socket with null network, get the same interfaces
+        final SocketCreationCallback socketCreationCb2 = mock(SocketCreationCallback.class);
+        final MdnsServiceBrowserListener listener2 = mock(MdnsServiceBrowserListener.class);
+
+        // requestSocket is called a second time
+        final ArgumentCaptor<SocketCallback> callback2Captor =
+                ArgumentCaptor.forClass(SocketCallback.class);
+        mHandler.post(() -> mSocketClient.notifyNetworkRequested(
+                listener2, null, socketCreationCb2));
+        HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+        verify(mProvider, times(2)).requestSocket(eq(null), callback2Captor.capture());
+        final SocketCallback callback2 = callback2Captor.getAllValues().get(1);
+
+        // Notify socket created for all networks.
+        callback2.onSocketCreated(mNetwork, mSocket, List.of());
+        callback2.onSocketCreated(null, socket2, List.of());
+        callback2.onSocketCreated(null, socket3, List.of());
+        verify(socketCreationCb2).onSocketCreated(mNetwork);
+        verify(socketCreationCb2, times(2)).onSocketCreated(null);
+
+        // Send IPv4 packet to null network and verify sending to the 2 tethered interface sockets.
+        mSocketClient.sendMulticastPacket(ipv4Packet, null);
+        HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+        // ipv4Packet still sent only once on mSocket: times(1) matches the packet sent earlier on
+        // mNetwork
+        verify(mSocket, times(1)).send(ipv4Packet);
+        verify(socket2).send(ipv4Packet);
+        verify(socket3).send(ipv4Packet);
+
+        // Unregister the second request
         mHandler.post(() -> mSocketClient.notifyNetworkUnrequested(listener2));
         verify(mProvider, timeout(DEFAULT_TIMEOUT)).unrequestSocket(callback2);
 
-        // Send IPv4 packet again and verify only sending via mSocket
-        mSocketClient.sendMulticastPacket(ipv4Packet);
+        // Send IPv4 packet again and verify it's still sent a second time
+        mSocketClient.sendMulticastPacket(ipv4Packet, null);
         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
-        verify(mSocket, times(3)).send(ipv4Packet);
-        verify(socket2).send(ipv4Packet);
+        verify(socket2, times(2)).send(ipv4Packet);
+        verify(socket3, times(2)).send(ipv4Packet);
 
-        // Unrequest remaining socket
+        // Unrequest remaining sockets
         mHandler.post(() -> mSocketClient.notifyNetworkUnrequested(mListener));
         verify(mProvider, timeout(DEFAULT_TIMEOUT)).unrequestSocket(callback);
 
         // Send IPv4 packet and verify no more sending.
-        mSocketClient.sendMulticastPacket(ipv4Packet);
+        mSocketClient.sendMulticastPacket(ipv4Packet, null);
         HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
-        verify(mSocket, times(3)).send(ipv4Packet);
-        verify(socket2).send(ipv4Packet);
+        verify(mSocket, times(1)).send(ipv4Packet);
+        verify(socket2, times(2)).send(ipv4Packet);
+        verify(socket3, times(2)).send(ipv4Packet);
     }
 
     @Test
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
index 42d296b..f15e8ff 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
@@ -952,7 +952,7 @@
         currentThreadExecutor.getAndClearLastScheduledRunnable().run();
         // Send twice for IPv4 and IPv6
         inOrder.verify(mockSocketClient, times(2)).sendUnicastPacket(srvTxtQueryCaptor.capture(),
-                eq(null) /* network */);
+                eq(mockNetwork));
 
         final MdnsPacket srvTxtQueryPacket = MdnsPacket.parse(
                 new MdnsPacketReader(srvTxtQueryCaptor.getValue()));
@@ -987,7 +987,7 @@
                 ArgumentCaptor.forClass(DatagramPacket.class);
         currentThreadExecutor.getAndClearLastScheduledRunnable().run();
         inOrder.verify(mockSocketClient, times(2)).sendMulticastPacket(addressQueryCaptor.capture(),
-                eq(null) /* network */);
+                eq(mockNetwork));
 
         final MdnsPacket addressQueryPacket = MdnsPacket.parse(
                 new MdnsPacketReader(addressQueryCaptor.getValue()));
@@ -1255,17 +1255,17 @@
         currentThreadExecutor.getAndClearLastScheduledRunnable().run();
         if (expectsUnicastResponse) {
             verify(mockSocketClient).sendUnicastPacket(
-                    expectedIPv4Packets[index], null /* network */);
+                    expectedIPv4Packets[index], mockNetwork);
             if (multipleSocketDiscovery) {
                 verify(mockSocketClient).sendUnicastPacket(
-                        expectedIPv6Packets[index], null /* network */);
+                        expectedIPv6Packets[index], mockNetwork);
             }
         } else {
             verify(mockSocketClient).sendMulticastPacket(
-                    expectedIPv4Packets[index], null /* network */);
+                    expectedIPv4Packets[index], mockNetwork);
             if (multipleSocketDiscovery) {
                 verify(mockSocketClient).sendMulticastPacket(
-                        expectedIPv6Packets[index], null /* network */);
+                        expectedIPv6Packets[index], mockNetwork);
             }
         }
     }