From eb80e8ad9fc92ba52d4ebbb8a7c157dc4dea7fff Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 13 Aug 2025 15:37:02 +0800 Subject: [PATCH] Mdns: Skip networks with NET_CAPABILITY_LOCAL_NETWORK MdnsSocketProvider expects no overlap between NetworkCallbacks, Tethering, and Wifi P2P. However, local NetworkAgents can cause overlap, leading to duplicate sockets. This commit fixes the issue by skipping networks with NET_CAPABILITY_LOCAL_NETWORK. Alternatively, the NetworkRequest should addForbiddenCapability for local networks. However, since this is a module API, it is not visible to standalone applications. Flag: EXEMPT bug fix Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.connectivity.mdns.MdnsSocketProviderTest \ --update-device Test: m service-connectivity-mdns-standalone-build-test Test: atest CtsNetTestCases:android.net.cts.NsdManagerTest \ CtsNetTestCases:android.net.cts.NsdManagerDownstreamTetheringTest Bug: 437038495 Change-Id: I78dd7d98ad80147ca26ec6130b6081ef4efb2ecc --- .../connectivity/mdns/MdnsSocketProvider.java | 13 ++++++-- .../mdns/MdnsSocketProviderTest.java | 32 +++++++++++++++---- 2 files changed, 37 insertions(+), 8 deletions(-) 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 328f4de3ae..917a85baab 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java @@ -16,6 +16,7 @@ package com.android.server.connectivity.mdns; +import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_THREAD; import static android.net.NetworkCapabilities.TRANSPORT_VPN; @@ -187,12 +188,20 @@ public class MdnsSocketProvider { @Override public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) { - mActiveNetworksTransports.put(network, networkCapabilities.getTransportTypes()); + if (!networkCapabilities.hasCapability(NET_CAPABILITY_LOCAL_NETWORK)) { + mActiveNetworksTransports.put(network, networkCapabilities.getTransportTypes()); + } } @Override public void onLinkPropertiesChanged(Network network, LinkProperties lp) { - handleLinkPropertiesChanged(network, lp); + // The correctness relies on at least one onCapabilitiesChanged + // being called before onLinkPropertiesChanged. This is guaranteed + // and publicly documented at + // ConnectivityManager.NetworkCallback#onAvailable(android.net.Network). + if (mActiveNetworksTransports.containsKey(network)) { + handleLinkPropertiesChanged(network, lp); + } } }; mTetheringEventCallback = new TetheringEventCallback() { 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 6bcc4ed442..ca48e4cf7e 100644 --- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java +++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java @@ -16,6 +16,7 @@ package com.android.server.connectivity.mdns; +import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK; import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_THREAD; @@ -551,16 +552,13 @@ public class MdnsSocketProviderTest { testCallback.expectedNoCallback(); // Notify a LinkPropertiesChanged with TEST_NETWORK. - final LinkProperties testLp = new LinkProperties(); - testLp.setInterfaceName(TEST_IFACE_NAME); - testLp.setLinkAddresses(List.of(LINKADDRV4)); - runOnHandler(() -> mNetworkCallback.onLinkPropertiesChanged(TEST_NETWORK, testLp)); + postNetworkAvailable(TRANSPORT_WIFI); verify(mTestNetworkIfaceWrapper, times(1)).getNetworkInterface(); testCallback.expectedSocketCreatedForNetwork(TEST_NETWORK, List.of(LINKADDRV4)); // Try to stop monitoring and unrequest the socket. runOnHandler(mSocketProvider::requestStopWhenInactive); - runOnHandler(()-> mSocketProvider.unrequestSocket(testCallback)); + runOnHandler(() -> mSocketProvider.unrequestSocket(testCallback)); // No callback sent when unregistered testCallback.expectedNoCallback(); verify(mCm, times(1)).unregisterNetworkCallback(any(NetworkCallback.class)); @@ -575,12 +573,14 @@ public class MdnsSocketProviderTest { runOnHandler(() -> mSocketProvider.requestSocket(null, testCallback)); testCallback.expectedNoCallback(); - // Notify a LinkPropertiesChanged with another network. + // Notify onCapabilitiesChanged and onLinkPropertiesChanged for another network. final LinkProperties otherLp = new LinkProperties(); final LinkAddress otherAddress = new LinkAddress("192.0.2.1/24"); final Network otherNetwork = new Network(456); otherLp.setInterfaceName("test2"); otherLp.setLinkAddresses(List.of(otherAddress)); + final NetworkCapabilities otherNc = makeCapabilities(new int[]{TRANSPORT_WIFI}); + runOnHandler(() -> mNetworkCallback.onCapabilitiesChanged(otherNetwork, otherNc)); runOnHandler(() -> mNetworkCallback.onLinkPropertiesChanged(otherNetwork, otherLp)); verify(mTestNetworkIfaceWrapper, times(2)).getNetworkInterface(); testCallback.expectedSocketCreatedForNetwork(otherNetwork, List.of(otherAddress)); @@ -608,6 +608,26 @@ public class MdnsSocketProviderTest { testCallback.expectedNoCallback(); } + @Test + public void testNoSocketCreatedForLocalNetwork() { + startMonitoringSockets(); + + final TestSocketCallback testCallback = new TestSocketCallback(); + runOnHandler(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback)); + + final LinkProperties testLp = new LinkProperties(); + testLp.setInterfaceName(TEST_IFACE_NAME); + testLp.setLinkAddresses(List.of(LINKADDRV4)); + + final NetworkCapabilities testNc = makeCapabilities(TRANSPORT_WIFI); + testNc.addCapability(NET_CAPABILITY_LOCAL_NETWORK); + + runOnHandler(() -> mNetworkCallback.onCapabilitiesChanged(TEST_NETWORK, testNc)); + runOnHandler(() -> mNetworkCallback.onLinkPropertiesChanged(TEST_NETWORK, testLp)); + + testCallback.expectedNoCallback(); + } + @Test public void testNoSocketCreatedForNonMulticastInterface() throws Exception { doReturn(false).when(mTestNetworkIfaceWrapper).supportsMulticast();