diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 7339d083ba..9850fdecf3 100755 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -171,6 +171,7 @@ import android.net.LinkProperties; import android.net.LocalNetworkConfig; import android.net.LocalNetworkInfo; import android.net.MatchAllNetworkSpecifier; +import android.net.MulticastRoutingConfig; import android.net.NativeNetworkConfig; import android.net.NativeNetworkType; import android.net.NattSocketKeepalive; @@ -320,6 +321,7 @@ import com.android.server.connectivity.KeepaliveResourceUtil; import com.android.server.connectivity.KeepaliveTracker; import com.android.server.connectivity.LingerMonitor; import com.android.server.connectivity.MockableSystemProperties; +import com.android.server.connectivity.MulticastRoutingCoordinatorService; import com.android.server.connectivity.MultinetworkPolicyTracker; import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkDiagnostics; @@ -347,6 +349,7 @@ import java.io.InterruptedIOException; import java.io.PrintWriter; import java.io.Writer; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketException; @@ -361,6 +364,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; @@ -496,6 +500,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mTNSLock") private TestNetworkService mTNS; private final CompanionDeviceManagerProxyService mCdmps; + private final MulticastRoutingCoordinatorService mMulticastRoutingCoordinatorService; private final RoutingCoordinatorService mRoutingCoordinatorService; private final Object mTNSLock = new Object(); @@ -1421,6 +1426,17 @@ public class ConnectivityService extends IConnectivityManager.Stub return new AutomaticOnOffKeepaliveTracker(c, h); } + public MulticastRoutingCoordinatorService makeMulticastRoutingCoordinatorService( + @NonNull Handler h) { + try { + return new MulticastRoutingCoordinatorService(h); + } catch (UnsupportedOperationException e) { + // Multicast routing is not supported by the kernel + Log.i(TAG, "Skipping unsupported MulticastRoutingCoordinatorService"); + return null; + } + } + /** * @see BatteryStatsManager */ @@ -1859,6 +1875,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } mRoutingCoordinatorService = new RoutingCoordinatorService(netd); + mMulticastRoutingCoordinatorService = + mDeps.makeMulticastRoutingCoordinatorService(mHandler); mDestroyFrozenSockets = mDeps.isAtLeastU() && mDeps.isFeatureEnabled(context, KEY_DESTROY_FROZEN_SOCKETS_VERSION); @@ -5175,9 +5193,12 @@ public class ConnectivityService extends IConnectivityManager.Stub private void removeLocalNetworkUpstream(@NonNull final NetworkAgentInfo localAgent, @NonNull final NetworkAgentInfo upstream) { try { + final String localNetworkInterfaceName = localAgent.linkProperties.getInterfaceName(); + final String upstreamNetworkInterfaceName = upstream.linkProperties.getInterfaceName(); mRoutingCoordinatorService.removeInterfaceForward( - localAgent.linkProperties.getInterfaceName(), - upstream.linkProperties.getInterfaceName()); + localNetworkInterfaceName, + upstreamNetworkInterfaceName); + disableMulticastRouting(localNetworkInterfaceName, upstreamNetworkInterfaceName); } catch (RemoteException e) { loge("Couldn't remove interface forward for " + localAgent.linkProperties.getInterfaceName() + " to " @@ -9095,6 +9116,61 @@ public class ConnectivityService extends IConnectivityManager.Stub updateCapabilities(nai.getScore(), nai, nai.networkCapabilities); } + private void maybeApplyMulticastRoutingConfig(@NonNull final NetworkAgentInfo nai, + final LocalNetworkConfig oldConfig, + final LocalNetworkConfig newConfig) { + final MulticastRoutingConfig oldUpstreamConfig = + oldConfig == null ? MulticastRoutingConfig.CONFIG_FORWARD_NONE : + oldConfig.getUpstreamMulticastRoutingConfig(); + final MulticastRoutingConfig oldDownstreamConfig = + oldConfig == null ? MulticastRoutingConfig.CONFIG_FORWARD_NONE : + oldConfig.getDownstreamMulticastRoutingConfig(); + final MulticastRoutingConfig newUpstreamConfig = + newConfig == null ? MulticastRoutingConfig.CONFIG_FORWARD_NONE : + newConfig.getUpstreamMulticastRoutingConfig(); + final MulticastRoutingConfig newDownstreamConfig = + newConfig == null ? MulticastRoutingConfig.CONFIG_FORWARD_NONE : + newConfig.getDownstreamMulticastRoutingConfig(); + + if (oldUpstreamConfig.equals(newUpstreamConfig) && + oldDownstreamConfig.equals(newDownstreamConfig)) { + return; + } + + final String downstreamNetworkName = nai.linkProperties.getInterfaceName(); + final LocalNetworkInfo lni = localNetworkInfoForNai(nai); + final Network upstreamNetwork = lni.getUpstreamNetwork(); + + if (upstreamNetwork != null) { + final String upstreamNetworkName = + getLinkProperties(upstreamNetwork).getInterfaceName(); + applyMulticastRoutingConfig(downstreamNetworkName, upstreamNetworkName, newConfig); + } + } + + private void applyMulticastRoutingConfig(@NonNull String localNetworkInterfaceName, + @NonNull String upstreamNetworkInterfaceName, + @NonNull final LocalNetworkConfig config) { + if (mMulticastRoutingCoordinatorService == null) return; + + mMulticastRoutingCoordinatorService.applyMulticastRoutingConfig(localNetworkInterfaceName, + upstreamNetworkInterfaceName, config.getUpstreamMulticastRoutingConfig()); + mMulticastRoutingCoordinatorService.applyMulticastRoutingConfig + (upstreamNetworkInterfaceName, localNetworkInterfaceName, + config.getDownstreamMulticastRoutingConfig()); + } + + private void disableMulticastRouting(@NonNull String localNetworkInterfaceName, + @NonNull String upstreamNetworkInterfaceName) { + if (mMulticastRoutingCoordinatorService == null) return; + + mMulticastRoutingCoordinatorService.applyMulticastRoutingConfig(localNetworkInterfaceName, + upstreamNetworkInterfaceName, MulticastRoutingConfig.CONFIG_FORWARD_NONE); + mMulticastRoutingCoordinatorService.applyMulticastRoutingConfig + (upstreamNetworkInterfaceName, localNetworkInterfaceName, + MulticastRoutingConfig.CONFIG_FORWARD_NONE); + } + // oldConfig is null iff this is the original registration of the local network config private void handleUpdateLocalNetworkConfig(@NonNull final NetworkAgentInfo nai, @Nullable final LocalNetworkConfig oldConfig, @@ -9108,7 +9184,6 @@ public class ConnectivityService extends IConnectivityManager.Stub Log.v(TAG, "Update local network config " + nai.network.netId + " : " + newConfig); } final LocalNetworkConfig.Builder configBuilder = new LocalNetworkConfig.Builder(); - // TODO : apply the diff for multicast routing. configBuilder.setUpstreamMulticastRoutingConfig( newConfig.getUpstreamMulticastRoutingConfig()); configBuilder.setDownstreamMulticastRoutingConfig( @@ -9167,6 +9242,7 @@ public class ConnectivityService extends IConnectivityManager.Stub configBuilder.setUpstreamSelector(oldRequest); nai.localNetworkConfig = configBuilder.build(); } + maybeApplyMulticastRoutingConfig(nai, oldConfig, newConfig); } /** @@ -10166,6 +10242,8 @@ public class ConnectivityService extends IConnectivityManager.Stub if (null != change.mOldNetwork) { mRoutingCoordinatorService.removeInterfaceForward(fromIface, change.mOldNetwork.linkProperties.getInterfaceName()); + disableMulticastRouting(fromIface, + change.mOldNetwork.linkProperties.getInterfaceName()); } // If the new upstream is already destroyed, there is no point in setting up // a forward (in fact, it might forward to the interface for some new network !) @@ -10174,6 +10252,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (null != change.mNewNetwork && !change.mNewNetwork.isDestroyed()) { mRoutingCoordinatorService.addInterfaceForward(fromIface, change.mNewNetwork.linkProperties.getInterfaceName()); + applyMulticastRoutingConfig(fromIface, + change.mNewNetwork.linkProperties.getInterfaceName(), + nai.localNetworkConfig); } } catch (final RemoteException e) { loge("Can't update forwarding rules", e); diff --git a/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt b/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt index dd0706b6ae..016608b3ae 100644 --- a/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt +++ b/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt @@ -20,6 +20,8 @@ import android.net.IpPrefix import android.net.LinkAddress import android.net.LinkProperties import android.net.LocalNetworkConfig +import android.net.MulticastRoutingConfig +import android.net.MulticastRoutingConfig.CONFIG_FORWARD_NONE import android.net.NetworkCapabilities import android.net.NetworkCapabilities.NET_CAPABILITY_DUN import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET @@ -45,6 +47,7 @@ import com.android.testutils.TestableNetworkCallback import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.clearInvocations +import org.mockito.Mockito.eq import org.mockito.Mockito.inOrder import org.mockito.Mockito.never import org.mockito.Mockito.timeout @@ -82,6 +85,24 @@ private fun keepScore() = FromS( @RunWith(DevSdkIgnoreRunner::class) @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) class CSLocalAgentTests : CSTest() { + val multicastRoutingConfigMinScope = + MulticastRoutingConfig.Builder(MulticastRoutingConfig.FORWARD_WITH_MIN_SCOPE, 4) + .build(); + val multicastRoutingConfigSelected = + MulticastRoutingConfig.Builder(MulticastRoutingConfig.FORWARD_SELECTED) + .build(); + val upstreamSelectorAny = NetworkRequest.Builder() + .addForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK) + .build() + val upstreamSelectorWifi = NetworkRequest.Builder() + .addForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK) + .addTransportType(TRANSPORT_WIFI) + .build() + val upstreamSelectorCell = NetworkRequest.Builder() + .addForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK) + .addTransportType(TRANSPORT_CELLULAR) + .build() + @Test fun testBadAgents() { deps.setBuildSdk(VERSION_V) @@ -177,6 +198,266 @@ class CSLocalAgentTests : CSTest() { localAgent.disconnect() } + private fun createLocalAgent(name: String, localNetworkConfig: FromS): + CSAgentWrapper { + val localAgent = Agent( + nc = nc(TRANSPORT_THREAD, NET_CAPABILITY_LOCAL_NETWORK), + lp = lp(name), + lnc = localNetworkConfig, + ) + return localAgent + } + + private fun createWifiAgent(name: String): CSAgentWrapper { + return Agent(score = keepScore(), lp = lp(name), + nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET)) + } + + private fun createCellAgent(name: String): CSAgentWrapper { + return Agent(score = keepScore(), lp = lp(name), + nc = nc(TRANSPORT_CELLULAR, NET_CAPABILITY_INTERNET)) + } + + private fun sendLocalNetworkConfig(localAgent: CSAgentWrapper, + upstreamSelector: NetworkRequest?, upstreamConfig: MulticastRoutingConfig, + downstreamConfig: MulticastRoutingConfig) { + val newLnc = LocalNetworkConfig.Builder() + .setUpstreamSelector(upstreamSelector) + .setUpstreamMulticastRoutingConfig(upstreamConfig) + .setDownstreamMulticastRoutingConfig(downstreamConfig) + .build() + localAgent.sendLocalNetworkConfig(newLnc) + } + + @Test + fun testMulticastRoutingConfig() { + deps.setBuildSdk(VERSION_V) + val cb = TestableNetworkCallback() + cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb) + val inOrder = inOrder(multicastRoutingCoordinatorService) + + val lnc = FromS(LocalNetworkConfig.Builder() + .setUpstreamSelector(upstreamSelectorWifi) + .setUpstreamMulticastRoutingConfig(multicastRoutingConfigMinScope) + .setDownstreamMulticastRoutingConfig(multicastRoutingConfigSelected) + .build() + ) + val localAgent = createLocalAgent("local0", lnc) + localAgent.connect() + + cb.expectAvailableCallbacks(localAgent.network, validated = false) + + val wifiAgent = createWifiAgent("wifi0") + wifiAgent.connect() + cb.expectAvailableCallbacks(wifiAgent.network, validated = false) + cb.expect(localAgent.network) { + it.info.upstreamNetwork == wifiAgent.network + } + + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "local0", "wifi0", multicastRoutingConfigMinScope) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "wifi0", "local0", multicastRoutingConfigSelected) + + wifiAgent.disconnect() + + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("local0", "wifi0", CONFIG_FORWARD_NONE) + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("wifi0", "local0", CONFIG_FORWARD_NONE) + + localAgent.disconnect() + } + + @Test + fun testMulticastRoutingConfig_2LocalNetworks() { + deps.setBuildSdk(VERSION_V) + val inOrder = inOrder(multicastRoutingCoordinatorService) + val lnc = FromS(LocalNetworkConfig.Builder() + .setUpstreamSelector(upstreamSelectorWifi) + .setUpstreamMulticastRoutingConfig(multicastRoutingConfigMinScope) + .setDownstreamMulticastRoutingConfig(multicastRoutingConfigSelected) + .build() + ) + val localAgent0 = createLocalAgent("local0", lnc) + localAgent0.connect() + + val wifiAgent = createWifiAgent("wifi0") + wifiAgent.connect() + waitForIdle() + + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "local0", "wifi0", multicastRoutingConfigMinScope) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "wifi0", "local0", multicastRoutingConfigSelected) + + val localAgent1 = createLocalAgent("local1", lnc) + localAgent1.connect() + waitForIdle() + + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "local1", "wifi0", multicastRoutingConfigMinScope) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "wifi0", "local1", multicastRoutingConfigSelected) + + localAgent0.disconnect() + localAgent1.disconnect() + wifiAgent.disconnect() + } + + @Test + fun testMulticastRoutingConfig_UpstreamNetworkCellToWifi() { + deps.setBuildSdk(VERSION_V) + val cb = TestableNetworkCallback() + cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities() + .addCapability(NET_CAPABILITY_LOCAL_NETWORK) + .build(), cb) + val inOrder = inOrder(multicastRoutingCoordinatorService) + val lnc = FromS(LocalNetworkConfig.Builder() + .setUpstreamSelector(upstreamSelectorAny) + .setUpstreamMulticastRoutingConfig(multicastRoutingConfigMinScope) + .setDownstreamMulticastRoutingConfig(multicastRoutingConfigSelected) + .build() + ) + val localAgent = createLocalAgent("local0", lnc) + val wifiAgent = createWifiAgent("wifi0") + val cellAgent = createCellAgent("cell0") + + localAgent.connect() + cb.expectAvailableCallbacks(localAgent.network, validated = false) + + cellAgent.connect() + cb.expect(localAgent.network) { + it.info.upstreamNetwork == cellAgent.network + } + + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "local0", "cell0", multicastRoutingConfigMinScope) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "cell0", "local0", multicastRoutingConfigSelected) + + wifiAgent.connect() + + cb.expect(localAgent.network) { + it.info.upstreamNetwork == wifiAgent.network + } + + // upstream should have been switched to wifi + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("local0", "cell0", CONFIG_FORWARD_NONE) + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("cell0", "local0", CONFIG_FORWARD_NONE) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "local0", "wifi0", multicastRoutingConfigMinScope) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "wifi0", "local0", multicastRoutingConfigSelected) + + localAgent.disconnect() + cellAgent.disconnect() + wifiAgent.disconnect() + } + + @Test + fun testMulticastRoutingConfig_UpstreamSelectorCellToWifi() { + deps.setBuildSdk(VERSION_V) + val cb = TestableNetworkCallback() + cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities() + .addCapability(NET_CAPABILITY_LOCAL_NETWORK) + .build(), cb) + val inOrder = inOrder(multicastRoutingCoordinatorService) + val lnc = FromS(LocalNetworkConfig.Builder() + .setUpstreamSelector(upstreamSelectorCell) + .setUpstreamMulticastRoutingConfig(multicastRoutingConfigMinScope) + .setDownstreamMulticastRoutingConfig(multicastRoutingConfigSelected) + .build() + ) + val localAgent = createLocalAgent("local0", lnc) + val wifiAgent = createWifiAgent("wifi0") + val cellAgent = createCellAgent("cell0") + + localAgent.connect() + cellAgent.connect() + wifiAgent.connect() + cb.expectAvailableCallbacks(localAgent.network, validated = false) + cb.expect(localAgent.network) { + it.info.upstreamNetwork == cellAgent.network + } + + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "local0", "cell0", multicastRoutingConfigMinScope) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "cell0", "local0", multicastRoutingConfigSelected) + + sendLocalNetworkConfig(localAgent, upstreamSelectorWifi, multicastRoutingConfigMinScope, + multicastRoutingConfigSelected) + cb.expect(localAgent.network) { + it.info.upstreamNetwork == wifiAgent.network + } + + // upstream should have been switched to wifi + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("local0", "cell0", CONFIG_FORWARD_NONE) + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("cell0", "local0", CONFIG_FORWARD_NONE) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "local0", "wifi0", multicastRoutingConfigMinScope) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "wifi0", "local0", multicastRoutingConfigSelected) + + localAgent.disconnect() + cellAgent.disconnect() + wifiAgent.disconnect() + } + + @Test + fun testMulticastRoutingConfig_UpstreamSelectorWifiToNull() { + deps.setBuildSdk(VERSION_V) + val cb = TestableNetworkCallback() + cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities() + .addCapability(NET_CAPABILITY_LOCAL_NETWORK) + .build(), cb) + val inOrder = inOrder(multicastRoutingCoordinatorService) + val lnc = FromS(LocalNetworkConfig.Builder() + .setUpstreamSelector(upstreamSelectorWifi) + .setUpstreamMulticastRoutingConfig(multicastRoutingConfigMinScope) + .setDownstreamMulticastRoutingConfig(multicastRoutingConfigSelected) + .build() + ) + val localAgent = createLocalAgent("local0", lnc) + localAgent.connect() + val wifiAgent = createWifiAgent("wifi0") + wifiAgent.connect() + cb.expectAvailableCallbacks(localAgent.network, validated = false) + cb.expect(localAgent.network) { + it.info.upstreamNetwork == wifiAgent.network + } + + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "local0", "wifi0", multicastRoutingConfigMinScope) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "wifi0", "local0", multicastRoutingConfigSelected) + + sendLocalNetworkConfig(localAgent, null, multicastRoutingConfigMinScope, + multicastRoutingConfigSelected) + cb.expect(localAgent.network) { + it.info.upstreamNetwork == null + } + + // upstream should have been switched to null + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("local0", "wifi0", CONFIG_FORWARD_NONE) + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("wifi0", "local0", CONFIG_FORWARD_NONE) + inOrder.verify(multicastRoutingCoordinatorService, never()).applyMulticastRoutingConfig( + eq("local0"), any(), eq(multicastRoutingConfigMinScope)) + inOrder.verify(multicastRoutingCoordinatorService, never()).applyMulticastRoutingConfig( + any(), eq("local0"), eq(multicastRoutingConfigSelected)) + + localAgent.disconnect() + wifiAgent.disconnect() + } + + @Test fun testUnregisterUpstreamAfterReplacement_SameIfaceName() { doTestUnregisterUpstreamAfterReplacement(true) @@ -196,11 +477,10 @@ class CSLocalAgentTests : CSTest() { val localAgent = Agent(nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_LOCAL_NETWORK), lp = lp("local0"), lnc = FromS(LocalNetworkConfig.Builder() - .setUpstreamSelector(NetworkRequest.Builder() - .addForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK) - .addTransportType(TRANSPORT_WIFI) - .build()) - .build()), + .setUpstreamSelector(upstreamSelectorWifi) + .setUpstreamMulticastRoutingConfig(multicastRoutingConfigMinScope) + .setDownstreamMulticastRoutingConfig(multicastRoutingConfigSelected) + .build()), score = FromS(NetworkScore.Builder() .setKeepConnectedReason(KEEP_CONNECTED_LOCAL_NETWORK) .build()) @@ -219,10 +499,15 @@ class CSLocalAgentTests : CSTest() { } clearInvocations(netd) - val inOrder = inOrder(netd) + clearInvocations(multicastRoutingCoordinatorService) + val inOrder = inOrder(netd, multicastRoutingCoordinatorService) wifiAgent.unregisterAfterReplacement(LONG_TIMEOUT_MS) waitForIdle() inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "wifi0") + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("local0", "wifi0", CONFIG_FORWARD_NONE) + inOrder.verify(multicastRoutingCoordinatorService) + .applyMulticastRoutingConfig("wifi0", "local0", CONFIG_FORWARD_NONE) inOrder.verify(netd).networkDestroy(wifiAgent.network.netId) val wifiIface2 = if (sameIfaceName) "wifi0" else "wifi1" @@ -235,9 +520,16 @@ class CSLocalAgentTests : CSTest() { cb.expect { it.network == wifiAgent.network } inOrder.verify(netd).ipfwdAddInterfaceForward("local0", wifiIface2) - if (sameIfaceName) { - inOrder.verify(netd, never()).ipfwdRemoveInterfaceForward(any(), any()) - } + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + "local0", wifiIface2, multicastRoutingConfigMinScope) + inOrder.verify(multicastRoutingCoordinatorService).applyMulticastRoutingConfig( + wifiIface2, "local0", multicastRoutingConfigSelected) + + inOrder.verify(netd, never()).ipfwdRemoveInterfaceForward(any(), any()) + inOrder.verify(multicastRoutingCoordinatorService, never()) + .applyMulticastRoutingConfig("local0", "wifi0", CONFIG_FORWARD_NONE) + inOrder.verify(multicastRoutingCoordinatorService, never()) + .applyMulticastRoutingConfig("wifi0", "local0", CONFIG_FORWARD_NONE) } @Test diff --git a/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt b/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt index 958c4f2961..83a11cf63f 100644 --- a/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt +++ b/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt @@ -61,9 +61,11 @@ import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker import com.android.server.connectivity.CarrierPrivilegeAuthenticator import com.android.server.connectivity.ClatCoordinator import com.android.server.connectivity.ConnectivityFlags +import com.android.server.connectivity.MulticastRoutingCoordinatorService import com.android.server.connectivity.MultinetworkPolicyTracker import com.android.server.connectivity.MultinetworkPolicyTrackerTestDependencies import com.android.server.connectivity.ProxyTracker +import com.android.server.connectivity.RoutingCoordinatorService import com.android.testutils.visibleOnHandlerThread import com.android.testutils.waitForIdle import java.util.concurrent.Executors @@ -166,6 +168,8 @@ open class CSTest { doReturn(true).`when`(it).isDataCapable() } + val multicastRoutingCoordinatorService = mock() + val deps = CSDeps() val service = makeConnectivityService(context, netd, deps).also { it.systemReadyInternal() } val cm = ConnectivityManager(context, service) @@ -179,6 +183,8 @@ open class CSTest { override fun makeHandlerThread(tag: String) = csHandlerThread override fun makeProxyTracker(context: Context, connServiceHandler: Handler) = proxyTracker + override fun makeMulticastRoutingCoordinatorService(handler: Handler) = + this@CSTest.multicastRoutingCoordinatorService override fun makeCarrierPrivilegeAuthenticator( context: Context,