Add LocalNetworkConfig

This doesn't do anything at this patchset, but the whole
pipe from the agent to ConnectivityService is built.

LocalNetworkInfo will be the name of the public information
sent in callbacks to clients.

Test: CSLocalAgentTests
Change-Id: I70e133031ef3b0aaf6c3e59ccc2ad895c66d339c
This commit is contained in:
Chalard Jean
2023-08-30 20:31:43 +09:00
parent 774dc3cd51
commit fa21cafc1c
18 changed files with 760 additions and 44 deletions

View File

@@ -12747,7 +12747,8 @@ public class ConnectivityServiceTest {
private NetworkAgentInfo fakeNai(NetworkCapabilities nc, NetworkInfo networkInfo) {
return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
nc, new NetworkScore.Builder().setLegacyInt(0).build(),
nc, null /* localNetworkConfig */,
new NetworkScore.Builder().setLegacyInt(0).build(),
mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker,
new ConnectivityService.Dependencies());

View File

@@ -372,9 +372,10 @@ public class LingerMonitorTest {
caps.addCapability(0);
caps.addTransportType(transport);
NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info,
new LinkProperties(), caps, new NetworkScore.Builder().setLegacyInt(50).build(),
mCtx, null, new NetworkAgentConfig.Builder().build(), mConnService, mNetd,
mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(), TEST_LINGER_DELAY_MS,
new LinkProperties(), caps, null /* localNetworkConfiguration */,
new NetworkScore.Builder().setLegacyInt(50).build(), mCtx, null,
new NetworkAgentConfig.Builder().build(), mConnService, mNetd, mDnsResolver,
NetworkProvider.ID_NONE, Binder.getCallingUid(), TEST_LINGER_DELAY_MS,
mQosCallbackTracker, new ConnectivityService.Dependencies());
if (setEverValidated) {
// As tests in this class deal with testing lingering, most tests are interested

View File

@@ -3004,8 +3004,15 @@ public class VpnTest extends VpnTestBase {
profile.mppe = useMppe;
doReturn(new Network[] { new Network(101) }).when(mConnectivityManager).getAllNetworks();
doReturn(new Network(102)).when(mConnectivityManager).registerNetworkAgent(any(), any(),
any(), any(), any(), any(), anyInt());
doReturn(new Network(102)).when(mConnectivityManager).registerNetworkAgent(
any(), // INetworkAgent
any(), // NetworkInfo
any(), // LinkProperties
any(), // NetworkCapabilities
any(), // LocalNetworkConfig
any(), // NetworkScore
any(), // NetworkAgentConfig
anyInt()); // provider ID
final Vpn vpn = startLegacyVpn(createVpn(PRIMARY_USER.id), profile);
final TestDeps deps = (TestDeps) vpn.mDeps;
@@ -3027,8 +3034,15 @@ public class VpnTest extends VpnTestBase {
assertEquals("nomppe", mtpdArgs[argsPrefix.length]);
}
verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
any(), any(), any(), any(), anyInt());
verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(
any(), // INetworkAgent
any(), // NetworkInfo
any(), // LinkProperties
any(), // NetworkCapabilities
any(), // LocalNetworkConfig
any(), // NetworkScore
any(), // NetworkAgentConfig
anyInt()); // provider ID
}, () -> { // Cleanup
vpn.mVpnRunner.exitVpnRunner();
deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier
@@ -3053,7 +3067,7 @@ public class VpnTest extends VpnTestBase {
.thenReturn(new Network[] { new Network(101) });
when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(),
any(), any(), anyInt())).thenAnswer(invocation -> {
any(), any(), any(), anyInt())).thenAnswer(invocation -> {
// The runner has registered an agent and is now ready.
legacyRunnerReady.open();
return new Network(102);
@@ -3079,7 +3093,7 @@ public class VpnTest extends VpnTestBase {
ArgumentCaptor<NetworkCapabilities> ncCaptor =
ArgumentCaptor.forClass(NetworkCapabilities.class);
verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
lpCaptor.capture(), ncCaptor.capture(), any(), any(), anyInt());
lpCaptor.capture(), ncCaptor.capture(), any(), any(), any(), anyInt());
// In this test the expected address is always v4 so /32.
// Note that the interface needs to be specified because RouteInfo objects stored in

View File

@@ -16,6 +16,7 @@
package com.android.server
import android.net.LocalNetworkConfig
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
import android.net.NetworkCapabilities.TRANSPORT_WIFI
@@ -45,8 +46,9 @@ class CSKeepConnectedTest : CSTest() {
.build()
val keepConnectedAgent = Agent(nc = nc, score = FromS(NetworkScore.Builder()
.setKeepConnectedReason(KEEP_CONNECTED_DOWNSTREAM_NETWORK)
.build()))
val dontKeepConnectedAgent = Agent(nc = nc)
.build()),
lnc = LocalNetworkConfig.Builder().build())
val dontKeepConnectedAgent = Agent(nc = nc, lnc = LocalNetworkConfig.Builder().build())
doTestKeepConnected(keepConnectedAgent, dontKeepConnectedAgent)
}

View File

@@ -18,6 +18,7 @@ package com.android.server
import android.content.pm.PackageManager.FEATURE_LEANBACK
import android.net.INetd
import android.net.LocalNetworkConfig
import android.net.NativeNetworkConfig
import android.net.NativeNetworkType
import android.net.NetworkCapabilities
@@ -48,6 +49,8 @@ private const val NO_CALLBACK_TIMEOUT_MS = 200L
private fun keepConnectedScore() =
FromS(NetworkScore.Builder().setKeepConnectedReason(KEEP_CONNECTED_FOR_TEST).build())
private fun defaultLnc() = LocalNetworkConfig.Builder().build()
@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
@IgnoreUpTo(Build.VERSION_CODES.R)
@@ -93,9 +96,9 @@ class CSLocalAgentCreationTests(
addCapability(NET_CAPABILITY_LOCAL_NETWORK)
}.build()
val localAgent = if (sdkLevel >= VERSION_V || sdkLevel == VERSION_U && isTv) {
Agent(nc = ncTemplate, score = keepConnectedScore())
Agent(nc = ncTemplate, score = keepConnectedScore(), lnc = defaultLnc())
} else {
assertFailsWith<IllegalArgumentException> { Agent(nc = ncTemplate) }
assertFailsWith<IllegalArgumentException> { Agent(nc = ncTemplate, lnc = defaultLnc()) }
netdInOrder.verify(netd, never()).networkCreate(any())
return
}
@@ -111,4 +114,18 @@ class CSLocalAgentCreationTests(
localAgent.disconnect()
netdInOrder.verify(netd, timeout(TIMEOUT_MS)).networkDestroy(localAgent.network.netId)
}
@Test
fun testBadAgents() {
assertFailsWith<IllegalArgumentException> {
Agent(nc = NetworkCapabilities.Builder()
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
.build(),
lnc = null)
}
assertFailsWith<IllegalArgumentException> {
Agent(nc = NetworkCapabilities.Builder().build(),
lnc = LocalNetworkConfig.Builder().build())
}
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server
import android.net.IpPrefix
import android.net.LinkAddress
import android.net.LinkProperties
import android.net.LocalNetworkConfig
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkRequest
import android.net.RouteInfo
import android.os.Build
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.RecorderCallback
import com.android.testutils.RecorderCallback.CallbackEntry.Available
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
import com.android.testutils.TestableNetworkCallback
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertFailsWith
private fun nc(transport: Int, vararg caps: Int) = NetworkCapabilities.Builder().apply {
addTransportType(transport)
caps.forEach {
addCapability(it)
}
// Useful capabilities for everybody
addCapability(NET_CAPABILITY_NOT_RESTRICTED)
addCapability(NET_CAPABILITY_NOT_SUSPENDED)
addCapability(NET_CAPABILITY_NOT_ROAMING)
addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
}.build()
private fun lp(iface: String) = LinkProperties().apply {
interfaceName = iface
addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32))
addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
}
@RunWith(DevSdkIgnoreRunner::class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
class CSLocalAgentTests : CSTest() {
@Test
fun testBadAgents() {
assertFailsWith<IllegalArgumentException> {
Agent(nc = NetworkCapabilities.Builder()
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
.build(),
lnc = null)
}
assertFailsWith<IllegalArgumentException> {
Agent(nc = NetworkCapabilities.Builder().build(),
lnc = LocalNetworkConfig.Builder().build())
}
}
@Test
fun testUpdateLocalAgentConfig() {
deps.setBuildSdk(VERSION_V)
val cb = TestableNetworkCallback()
cm.requestNetwork(NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
.build(),
cb)
// Set up a local agent that should forward its traffic to the best DUN upstream.
val localAgent = Agent(nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_LOCAL_NETWORK),
lp = lp("local0"),
lnc = LocalNetworkConfig.Builder().build(),
)
localAgent.connect()
cb.expect<Available>(localAgent.network)
cb.expect<CapabilitiesChanged>(localAgent.network)
cb.expect<LinkPropertiesChanged>(localAgent.network)
cb.expect<BlockedStatus>(localAgent.network)
val newLnc = LocalNetworkConfig.Builder()
.setUpstreamSelector(NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI)
.build())
.build()
localAgent.sendLocalNetworkConfig(newLnc)
localAgent.disconnect()
}
}

View File

@@ -21,6 +21,7 @@ import android.net.ConnectivityManager
import android.net.INetworkMonitor
import android.net.INetworkMonitorCallbacks
import android.net.LinkProperties
import android.net.LocalNetworkConfig
import android.net.Network
import android.net.NetworkAgent
import android.net.NetworkAgentConfig
@@ -69,6 +70,7 @@ class CSAgentWrapper(
nac: NetworkAgentConfig,
val nc: NetworkCapabilities,
val lp: LinkProperties,
val lnc: LocalNetworkConfig?,
val score: FromS<NetworkScore>,
val provider: NetworkProvider?
) : TestableNetworkCallback.HasNetwork {
@@ -100,7 +102,7 @@ class CSAgentWrapper(
// Create the actual agent. NetworkAgent is abstract, so make an anonymous subclass.
if (deps.isAtLeastS()) {
agent = object : NetworkAgent(context, csHandlerThread.looper, TAG,
nc, lp, score.value, nac, provider) {}
nc, lp, lnc, score.value, nac, provider) {}
} else {
agent = object : NetworkAgent(context, csHandlerThread.looper, TAG,
nc, lp, 50 /* score */, nac, provider) {}
@@ -165,4 +167,6 @@ class CSAgentWrapper(
agent.unregister()
cb.eventuallyExpect<Lost> { it.network == agent.network }
}
fun sendLocalNetworkConfig(lnc: LocalNetworkConfig) = agent.sendLocalNetworkConfig(lnc)
}

View File

@@ -27,6 +27,7 @@ import android.net.ConnectivityManager
import android.net.INetd
import android.net.InetAddresses
import android.net.LinkProperties
import android.net.LocalNetworkConfig
import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
@@ -292,10 +293,11 @@ open class CSTest {
nc: NetworkCapabilities = defaultNc(),
nac: NetworkAgentConfig = emptyAgentConfig(nc.getLegacyType()),
lp: LinkProperties = defaultLp(),
lnc: LocalNetworkConfig? = null,
score: FromS<NetworkScore> = defaultScore(),
provider: NetworkProvider? = null
) = CSAgentWrapper(context, deps, csHandlerThread, networkStack, nac, nc, lp, score, provider)
) = CSAgentWrapper(context, deps, csHandlerThread, networkStack,
nac, nc, lp, lnc, score, provider)
fun Agent(vararg transports: Int, lp: LinkProperties = defaultLp()): CSAgentWrapper {
val nc = NetworkCapabilities.Builder().apply {
transports.forEach {