Merge "Disable non-thread local network matching" into main

This commit is contained in:
Treehugger Robot 2025-03-21 08:08:56 -07:00 • committed by Gerrit Code Review
commit e0051cdeb9
12 changed files with 186 additions and 39 deletions

View file

@ -17,6 +17,8 @@
package android.net; package android.net;
import static android.Manifest.permission.DUMP; import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.LOG_COMPAT_CHANGE;
import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
import static android.net.InetAddresses.parseNumericAddress; import static android.net.InetAddresses.parseNumericAddress;
import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK; import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
@ -29,6 +31,7 @@ import static android.net.TetheringTester.buildIcmpEchoPacketV4;
import static android.net.TetheringTester.buildUdpPacket; import static android.net.TetheringTester.buildUdpPacket;
import static android.net.TetheringTester.isExpectedIcmpPacket; import static android.net.TetheringTester.isExpectedIcmpPacket;
import static android.net.TetheringTester.isExpectedUdpDnsPacket; import static android.net.TetheringTester.isExpectedUdpDnsPacket;
import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS;
import static android.provider.DeviceConfig.NAMESPACE_TETHERING; import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
import static android.system.OsConstants.ICMP_ECHO; import static android.system.OsConstants.ICMP_ECHO;
import static android.system.OsConstants.ICMP_ECHOREPLY; import static android.system.OsConstants.ICMP_ECHOREPLY;
@ -52,6 +55,7 @@ import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue; import static org.junit.Assume.assumeTrue;
import android.app.compat.CompatChanges;
import android.content.Context; import android.content.Context;
import android.net.TetheringManager.TetheringRequest; import android.net.TetheringManager.TetheringRequest;
import android.net.TetheringTester.TetheredDevice; import android.net.TetheringTester.TetheredDevice;
@ -1244,6 +1248,11 @@ public class EthernetTetheringTest extends EthernetTetheringTestBase {
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Test @Test
public void testLocalAgent_networkCallbacks() throws Exception { public void testLocalAgent_networkCallbacks() throws Exception {
final boolean isMatchNonThreadLocalNetworksEnabled = runAsShell(
READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE,
() -> CompatChanges.isChangeEnabled(ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS));
assumeTrue(isMatchNonThreadLocalNetworksEnabled);
mDeviceConfigRule.setConfig(NAMESPACE_TETHERING, TETHERING_LOCAL_NETWORK_AGENT, "1"); mDeviceConfigRule.setConfig(NAMESPACE_TETHERING, TETHERING_LOCAL_NETWORK_AGENT, "1");
assumeFalse(isInterfaceForTetheringAvailable()); assumeFalse(isInterfaceForTetheringAvailable());
setIncludeTestInterfaces(true); setIncludeTestInterfaces(true);

View file

@ -360,8 +360,7 @@ public final class NetworkCapabilities implements Parcelable {
mUnderlyingNetworks = null; mUnderlyingNetworks = null;
mEnterpriseId = 0; mEnterpriseId = 0;
mReservationId = RES_ID_UNSET; mReservationId = RES_ID_UNSET;
// TODO: Change to default disabled when introduce this filtering. mMatchNonThreadLocalNetworks = false;
mMatchNonThreadLocalNetworks = true;
} }
/** /**
@ -2961,8 +2960,7 @@ public final class NetworkCapabilities implements Parcelable {
* Flag to control whether a NetworkRequest can match non-thread local networks. * Flag to control whether a NetworkRequest can match non-thread local networks.
* @hide * @hide
*/ */
// TODO: Change to default disabled when introduce this filtering. private boolean mMatchNonThreadLocalNetworks;
private boolean mMatchNonThreadLocalNetworks = true;
/** /**
* Returns the match non-thread local networks flag. * Returns the match non-thread local networks flag.

View file

@ -148,6 +148,17 @@ public final class ConnectivityCompatChanges {
@EnabledAfter(targetSdkVersion = 36) @EnabledAfter(targetSdkVersion = 36)
public static final long RESTRICT_LOCAL_NETWORK = 365139289L; public static final long RESTRICT_LOCAL_NETWORK = 365139289L;
/**
* Enable match non-threads local networks.
*
* Apps targeting a release after V can have NetworkRequests matches non-thread local networks.
*
* @hide
*/
@ChangeId
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
public static final long ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS = 349487600L;
private ConnectivityCompatChanges() { private ConnectivityCompatChanges() {
} }
} }

View file

@ -121,6 +121,7 @@ import static android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST; import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY; import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK; import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK;
import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS;
import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION; import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION;
import static android.net.connectivity.ConnectivityCompatChanges.NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION; import static android.net.connectivity.ConnectivityCompatChanges.NETWORK_BLOCKED_WITHOUT_INTERNET_PERMISSION;
import static android.os.Process.INVALID_UID; import static android.os.Process.INVALID_UID;
@ -1473,6 +1474,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return SdkLevel.isAtLeastV(); return SdkLevel.isAtLeastV();
} }
public boolean isAtLeastB() {
return SdkLevel.isAtLeastB();
}
/** /**
* Get system properties to use in ConnectivityService. * Get system properties to use in ConnectivityService.
*/ */
@ -3186,6 +3191,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} }
private void maybeDisableLocalNetworkMatching(NetworkCapabilities nc, int callingUid) { private void maybeDisableLocalNetworkMatching(NetworkCapabilities nc, int callingUid) {
// If disabled, NetworkRequest cannot match non-thread local networks even if
// specified explicitly. Compat change is enabled by default on apps targeting B+.
// Agent should not be visible on U- even if it's rolled out.
nc.setMatchNonThreadLocalNetworks(mDeps.isAtLeastV() && mDeps.isChangeEnabled(
ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS, callingUid));
if (mDeps.isChangeEnabled(ENABLE_MATCH_LOCAL_NETWORK, callingUid)) { if (mDeps.isChangeEnabled(ENABLE_MATCH_LOCAL_NETWORK, callingUid)) {
return; return;
} }

View file

@ -19,7 +19,7 @@ package com.android.server
import android.net.LocalNetworkConfig import android.net.LocalNetworkConfig
import android.net.NetworkCapabilities import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
import android.net.NetworkCapabilities.TRANSPORT_WIFI import android.net.NetworkCapabilities.TRANSPORT_THREAD
import android.net.NetworkRequest import android.net.NetworkRequest
import android.net.NetworkScore import android.net.NetworkScore
import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
@ -42,7 +42,7 @@ class CSKeepConnectedTest : CSTest() {
fun testKeepConnectedLocalAgent() { fun testKeepConnectedLocalAgent() {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
val nc = NetworkCapabilities.Builder() val nc = NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_WIFI) .addTransportType(TRANSPORT_THREAD)
.addCapability(NET_CAPABILITY_LOCAL_NETWORK) .addCapability(NET_CAPABILITY_LOCAL_NETWORK)
.build() .build()
val keepConnectedAgent = Agent( val keepConnectedAgent = Agent(

View file

@ -18,14 +18,11 @@ package com.android.server
import android.content.pm.PackageManager.FEATURE_LEANBACK import android.content.pm.PackageManager.FEATURE_LEANBACK
import android.net.INetd import android.net.INetd
import android.net.LocalNetworkConfig
import android.net.NativeNetworkConfig import android.net.NativeNetworkConfig
import android.net.NativeNetworkType import android.net.NativeNetworkType
import android.net.NetworkCapabilities import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
import android.net.NetworkRequest import android.net.NetworkRequest
import android.net.NetworkScore
import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
import android.net.VpnManager import android.net.VpnManager
import android.os.Build import android.os.Build
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
@ -46,11 +43,6 @@ import org.mockito.Mockito.timeout
private const val TIMEOUT_MS = 2_000L private const val TIMEOUT_MS = 2_000L
private const val NO_CALLBACK_TIMEOUT_MS = 200L private const val NO_CALLBACK_TIMEOUT_MS = 200L
private fun keepConnectedScore() =
FromS(NetworkScore.Builder().setKeepConnectedReason(KEEP_CONNECTED_FOR_TEST).build())
private fun defaultLnc() = FromS(LocalNetworkConfig.Builder().build())
@DevSdkIgnoreRunner.MonitorThreadLeak @DevSdkIgnoreRunner.MonitorThreadLeak
@RunWith(DevSdkIgnoreRunner::class) @RunWith(DevSdkIgnoreRunner::class)
@SmallTest @SmallTest
@ -103,7 +95,7 @@ class CSLocalAgentCreationTests : CSTest() {
} }
cm.registerNetworkCallback(request.build(), allNetworksCb) cm.registerNetworkCallback(request.build(), allNetworksCb)
val ncTemplate = NetworkCapabilities.Builder().run { val ncTemplate = NetworkCapabilities.Builder().run {
addTransportType(NetworkCapabilities.TRANSPORT_WIFI) addTransportType(NetworkCapabilities.TRANSPORT_THREAD)
addCapability(NET_CAPABILITY_LOCAL_NETWORK) addCapability(NET_CAPABILITY_LOCAL_NETWORK)
}.build() }.build()
val localAgent = if (params.sdkLevel >= VERSION_V || val localAgent = if (params.sdkLevel >= VERSION_V ||

View file

@ -39,6 +39,7 @@ import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
import android.net.NetworkScore.KEEP_CONNECTED_LOCAL_NETWORK import android.net.NetworkScore.KEEP_CONNECTED_LOCAL_NETWORK
import android.net.RouteInfo import android.net.RouteInfo
import android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK import android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK
import android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS
import android.os.Build import android.os.Build
import com.android.testutils.DevSdkIgnoreRule import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner import com.android.testutils.DevSdkIgnoreRunner
@ -129,6 +130,7 @@ class CSLocalAgentTests : CSTest() {
@Test @Test
fun testStructuralConstraintViolation() { fun testStructuralConstraintViolation() {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback() val cb = TestableNetworkCallback()
cm.requestNetwork( cm.requestNetwork(
@ -162,6 +164,7 @@ class CSLocalAgentTests : CSTest() {
@Test @Test
fun testUpdateLocalAgentConfig() { fun testUpdateLocalAgentConfig() {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback() val cb = TestableNetworkCallback()
cm.requestNetwork( cm.requestNetwork(
@ -428,6 +431,7 @@ class CSLocalAgentTests : CSTest() {
@Test @Test
fun testMulticastRoutingConfig_UpstreamSelectorCellToWifi() { fun testMulticastRoutingConfig_UpstreamSelectorCellToWifi() {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback() val cb = TestableNetworkCallback()
cm.registerNetworkCallback( cm.registerNetworkCallback(
NetworkRequest.Builder().clearCapabilities() NetworkRequest.Builder().clearCapabilities()
@ -500,6 +504,7 @@ class CSLocalAgentTests : CSTest() {
@Test @Test
fun testMulticastRoutingConfig_UpstreamSelectorWifiToNull() { fun testMulticastRoutingConfig_UpstreamSelectorWifiToNull() {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback() val cb = TestableNetworkCallback()
cm.registerNetworkCallback( cm.registerNetworkCallback(
NetworkRequest.Builder().clearCapabilities() NetworkRequest.Builder().clearCapabilities()
@ -577,6 +582,7 @@ class CSLocalAgentTests : CSTest() {
fun doTestUnregisterUpstreamAfterReplacement(sameIfaceName: Boolean) { fun doTestUnregisterUpstreamAfterReplacement(sameIfaceName: Boolean) {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback() val cb = TestableNetworkCallback()
cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb) cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb)
@ -657,6 +663,7 @@ class CSLocalAgentTests : CSTest() {
@Test @Test
fun testUnregisterUpstreamAfterReplacement_neverReplaced() { fun testUnregisterUpstreamAfterReplacement_neverReplaced() {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback() val cb = TestableNetworkCallback()
cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb) cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb)
@ -710,6 +717,7 @@ class CSLocalAgentTests : CSTest() {
@Test @Test
fun testUnregisterLocalAgentAfterReplacement() { fun testUnregisterLocalAgentAfterReplacement() {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val localCb = TestableNetworkCallback() val localCb = TestableNetworkCallback()
cm.requestNetwork( cm.requestNetwork(
@ -775,6 +783,7 @@ class CSLocalAgentTests : CSTest() {
@Test @Test
fun testDestroyedNetworkAsSelectedUpstream() { fun testDestroyedNetworkAsSelectedUpstream() {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback() val cb = TestableNetworkCallback()
cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb) cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb)
@ -827,6 +836,7 @@ class CSLocalAgentTests : CSTest() {
@Test @Test
fun testForwardingRules() { fun testForwardingRules() {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
// Set up a local agent that should forward its traffic to the best DUN upstream. // Set up a local agent that should forward its traffic to the best DUN upstream.
val lnc = FromS( val lnc = FromS(
LocalNetworkConfig.Builder() LocalNetworkConfig.Builder()
@ -965,6 +975,7 @@ class CSLocalAgentTests : CSTest() {
fun doTestLocalNetworkUnwanted(haveUpstream: Boolean) { fun doTestLocalNetworkUnwanted(haveUpstream: Boolean) {
deps.setBuildSdk(VERSION_V) deps.setBuildSdk(VERSION_V)
deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val nr = NetworkRequest.Builder().addCapability(NET_CAPABILITY_LOCAL_NETWORK).build() val nr = NetworkRequest.Builder().addCapability(NET_CAPABILITY_LOCAL_NETWORK).build()
val requestCb = TestableNetworkCallback() val requestCb = TestableNetworkCallback()
@ -1075,4 +1086,86 @@ class CSLocalAgentTests : CSTest() {
expectCallback = true expectCallback = true
) )
} }
@Test
fun testNonThreadLocalAgentMatches_disabled() {
doTestNonThreadLocalAgentMatches(
VERSION_V,
enableMatchNonThreadLocalNetworks = false,
TRANSPORT_WIFI,
expectAvailable = false
)
doTestNonThreadLocalAgentMatches(
VERSION_V,
enableMatchNonThreadLocalNetworks = false,
TRANSPORT_THREAD,
expectAvailable = true
)
doTestNonThreadLocalAgentMatches(
VERSION_B,
enableMatchNonThreadLocalNetworks = false,
TRANSPORT_WIFI,
expectAvailable = false
)
doTestNonThreadLocalAgentMatches(
VERSION_B,
enableMatchNonThreadLocalNetworks = false,
TRANSPORT_THREAD,
expectAvailable = true
)
}
@Test
fun testNonThreadLocalAgentMatches_enabled() {
doTestNonThreadLocalAgentMatches(
VERSION_V,
enableMatchNonThreadLocalNetworks = true,
TRANSPORT_WIFI,
expectAvailable = true
)
doTestNonThreadLocalAgentMatches(
VERSION_V,
enableMatchNonThreadLocalNetworks = true,
TRANSPORT_THREAD,
expectAvailable = true
)
doTestNonThreadLocalAgentMatches(
VERSION_B,
enableMatchNonThreadLocalNetworks = true,
TRANSPORT_WIFI,
expectAvailable = true
)
doTestNonThreadLocalAgentMatches(
VERSION_B,
enableMatchNonThreadLocalNetworks = true,
TRANSPORT_THREAD,
expectAvailable = true
)
}
private fun doTestNonThreadLocalAgentMatches(
sdkLevel: Int,
enableMatchNonThreadLocalNetworks: Boolean,
transport: Int,
expectAvailable: Boolean
) {
deps.setBuildSdk(sdkLevel)
deps.setChangeIdEnabled(
enableMatchNonThreadLocalNetworks,
ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS
)
val localNcTemplate = NetworkCapabilities.Builder().run {
addTransportType(transport)
addCapability(NET_CAPABILITY_LOCAL_NETWORK)
}.build()
val localAgent = Agent(
nc = localNcTemplate,
score = keepConnectedScore(),
lnc = defaultLnc()
)
// The implementation inside connect() will expect the OnAvailable.
localAgent.connect(expectAvailable)
localAgent.disconnect(expectAvailable)
}
} }

View file

@ -20,6 +20,7 @@ import android.net.NetworkCapabilities
import android.net.NetworkRequest import android.net.NetworkRequest
import android.os.Build import android.os.Build
import android.os.Process import android.os.Process
import android.text.TextUtils
import com.android.testutils.DevSdkIgnoreRule import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.TestableNetworkCallback import com.android.testutils.TestableNetworkCallback
@ -54,9 +55,17 @@ class CSNetworkRequestStateStatsMetricsTests : CSTest() {
cm.requestNetwork(CELL_INTERNET_NOT_METERED_NR, TestableNetworkCallback()) cm.requestNetwork(CELL_INTERNET_NOT_METERED_NR, TestableNetworkCallback())
waitForIdle() waitForIdle()
// Some fields might be altered by the service, e.g. mMatchNonThreadLocalNetworks.
// Check immutable differences instead.
verify(networkRequestStateStatsMetrics).onNetworkRequestReceived( verify(networkRequestStateStatsMetrics).onNetworkRequestReceived(
argThat{req -> req.networkCapabilities.equals( argThat { req ->
CELL_INTERNET_NOT_METERED_NR.networkCapabilities)}) TextUtils.isEmpty(
req.networkCapabilities.describeImmutableDifferences(
CELL_INTERNET_NOT_METERED_NR.networkCapabilities
)
)
}
)
} }
@Test @Test
@ -77,7 +86,13 @@ class CSNetworkRequestStateStatsMetricsTests : CSTest() {
cm.unregisterNetworkCallback(cb) cm.unregisterNetworkCallback(cb)
waitForIdle() waitForIdle()
verify(networkRequestStateStatsMetrics).onNetworkRequestRemoved( verify(networkRequestStateStatsMetrics).onNetworkRequestRemoved(
argThat{req -> req.networkCapabilities.equals( argThat { req ->
CELL_INTERNET_NOT_METERED_NR.networkCapabilities)}) TextUtils.isEmpty(
req.networkCapabilities.describeImmutableDifferences(
CELL_INTERNET_NOT_METERED_NR.networkCapabilities
)
)
}
)
} }
} }

View file

@ -39,6 +39,7 @@ import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_ETHERNET import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
import android.net.NetworkCapabilities.TRANSPORT_THREAD
import android.net.NetworkCapabilities.TRANSPORT_WIFI import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkPolicyManager.NetworkPolicyCallback import android.net.NetworkPolicyManager.NetworkPolicyCallback
import android.net.NetworkRequest import android.net.NetworkRequest
@ -356,6 +357,7 @@ class CSQueuedCallbacksTest(freezingBehavior: FreezingBehavior) : CSTest() {
val localAgent = Agent( val localAgent = Agent(
nc = defaultNc() nc = defaultNc()
.addCapability(NET_CAPABILITY_LOCAL_NETWORK) .addCapability(NET_CAPABILITY_LOCAL_NETWORK)
.addTransportType(TRANSPORT_THREAD)
.removeCapability(NET_CAPABILITY_INTERNET), .removeCapability(NET_CAPABILITY_INTERNET),
lp = defaultLp().apply { interfaceName = "local42" }, lp = defaultLp().apply { interfaceName = "local42" },
lnc = FromS(lnc) lnc = FromS(lnc)

View file

@ -137,7 +137,7 @@ class CSAgentWrapper(
nmCallbacks.notifyNetworkTestedWithExtras(p) nmCallbacks.notifyNetworkTestedWithExtras(p)
} }
fun connect() { fun connect(expectAvailable: Boolean = true) {
val mgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val mgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val request = NetworkRequest.Builder().apply { val request = NetworkRequest.Builder().apply {
clearCapabilities() clearCapabilities()
@ -149,26 +149,30 @@ class CSAgentWrapper(
val cb = TestableNetworkCallback() val cb = TestableNetworkCallback()
mgr.registerNetworkCallback(request, cb) mgr.registerNetworkCallback(request, cb)
agent.markConnected() agent.markConnected()
if (null == cb.poll { it is Available && agent.network == it.network }) { if (expectAvailable) {
if (!nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) && if (null == cb.poll { it is Available && agent.network == it.network }) {
nc.hasTransport(TRANSPORT_CELLULAR)) { if (!nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) &&
// ConnectivityService adds NOT_SUSPENDED by default to all non-cell agents. An nc.hasTransport(TRANSPORT_CELLULAR)) {
// agent without NOT_SUSPENDED will not connect, instead going into the SUSPENDED // ConnectivityService adds NOT_SUSPENDED by default to all non-cell agents. An
// state, so this call will not terminate. // agent without NOT_SUSPENDED will not connect, instead going into the
// Instead of forcefully adding NOT_SUSPENDED to all agents like older tools did, // SUSPENDED state, so this call will not terminate.
// it's better to let the developer manage it as they see fit but help them // Instead of forcefully adding NOT_SUSPENDED to all agents like older tools did,
// debug if they forget. // it's better to let the developer manage it as they see fit but help them
fail( // debug if they forget.
"Could not connect the agent. Did you forget to add " + fail(
"NET_CAPABILITY_NOT_SUSPENDED ?" "Could not connect the agent. Did you forget to add " +
) "NET_CAPABILITY_NOT_SUSPENDED ?"
)
}
fail("Could not connect the agent. Instrumentation failure ?")
} }
fail("Could not connect the agent. Instrumentation failure ?") } else {
cb.assertNoCallback()
} }
mgr.unregisterNetworkCallback(cb) mgr.unregisterNetworkCallback(cb)
} }
fun disconnect() { fun disconnect(expectAvailable: Boolean = true) {
val mgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val mgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val request = NetworkRequest.Builder().apply { val request = NetworkRequest.Builder().apply {
clearCapabilities() clearCapabilities()
@ -179,9 +183,14 @@ class CSAgentWrapper(
}.build() }.build()
val cb = TestableNetworkCallback(timeoutMs = SHORT_TIMEOUT_MS) val cb = TestableNetworkCallback(timeoutMs = SHORT_TIMEOUT_MS)
mgr.registerNetworkCallback(request, cb) mgr.registerNetworkCallback(request, cb)
cb.eventuallyExpect<Available> { it.network == agent.network } if (expectAvailable) {
agent.unregister() cb.eventuallyExpect<Available> { it.network == agent.network }
cb.eventuallyExpect<Lost> { it.network == agent.network } agent.unregister()
cb.eventuallyExpect<Lost> { it.network == agent.network }
} else {
agent.unregister()
cb.assertNoCallback()
}
} }
fun setTeardownDelayMillis(delayMillis: Int) = agent.setTeardownDelayMillis(delayMillis) fun setTeardownDelayMillis(delayMillis: Int) = agent.setTeardownDelayMillis(delayMillis)

View file

@ -112,7 +112,8 @@ internal const val VERSION_S = 2
internal const val VERSION_T = 3 internal const val VERSION_T = 3
internal const val VERSION_U = 4 internal const val VERSION_U = 4
internal const val VERSION_V = 5 internal const val VERSION_V = 5
internal const val VERSION_MAX = VERSION_V internal const val VERSION_B = 6
internal const val VERSION_MAX = VERSION_B
internal const val CALLING_UID_UNMOCKED = Process.INVALID_UID internal const val CALLING_UID_UNMOCKED = Process.INVALID_UID
@ -388,6 +389,7 @@ open class CSTest {
override fun isAtLeastT() = if (isSdkUnmocked) super.isAtLeastT() else sdkLevel >= VERSION_T override fun isAtLeastT() = if (isSdkUnmocked) super.isAtLeastT() else sdkLevel >= VERSION_T
override fun isAtLeastU() = if (isSdkUnmocked) super.isAtLeastU() else sdkLevel >= VERSION_U override fun isAtLeastU() = if (isSdkUnmocked) super.isAtLeastU() else sdkLevel >= VERSION_U
override fun isAtLeastV() = if (isSdkUnmocked) super.isAtLeastV() else sdkLevel >= VERSION_V override fun isAtLeastV() = if (isSdkUnmocked) super.isAtLeastV() else sdkLevel >= VERSION_V
override fun isAtLeastB() = if (isSdkUnmocked) super.isAtLeastB() else sdkLevel >= VERSION_B
private var callingUid = CALLING_UID_UNMOCKED private var callingUid = CALLING_UID_UNMOCKED

View file

@ -34,6 +34,7 @@ import android.net.INetd
import android.net.IpPrefix import android.net.IpPrefix
import android.net.LinkAddress import android.net.LinkAddress
import android.net.LinkProperties import android.net.LinkProperties
import android.net.LocalNetworkConfig
import android.net.NetworkAgentConfig import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities import android.net.NetworkCapabilities
import android.net.NetworkScore import android.net.NetworkScore
@ -84,6 +85,11 @@ internal fun defaultNc() = NetworkCapabilities.Builder()
internal fun defaultScore() = FromS(NetworkScore.Builder().build()) internal fun defaultScore() = FromS(NetworkScore.Builder().build())
internal fun keepConnectedScore() = FromS(NetworkScore.Builder()
.setKeepConnectedReason(NetworkScore.KEEP_CONNECTED_FOR_TEST).build())
internal fun defaultLnc() = FromS(LocalNetworkConfig.Builder().build())
internal fun defaultLp() = LinkProperties().apply { internal fun defaultLp() = LinkProperties().apply {
addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32)) addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32))
addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null)) addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))