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
This commit is contained in:
Junyu Lai 2025-08-13 15:37:02 +08:00
commit eb80e8ad9f
2 changed files with 37 additions and 8 deletions

View file

@ -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() {

View file

@ -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();