Disable non-thread local network matching
Currently, apps targeting V can see thread local network.
This change introduces a mechanism to make existing
apps unable to see non-thread local networks to ensure minimal
impact on existing devices and applications while adopting this
behavior. Apps targeting B+ Sdk and run on V+ devices can see
non-thread local networks.
Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.CSLocalAgentTests \
--update-device
Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server --update-device
(on next/trunk_staging release config)
Bug: 349487600
Change-Id: I6aa43cebc20a9017c2d8a8a90ebb1d53040a27bb
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 11442ed..d47f4b3 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -17,6 +17,8 @@
package android.net;
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.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
@@ -29,6 +31,7 @@
import static android.net.TetheringTester.buildUdpPacket;
import static android.net.TetheringTester.isExpectedIcmpPacket;
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.system.OsConstants.ICMP_ECHO;
import static android.system.OsConstants.ICMP_ECHOREPLY;
@@ -52,6 +55,7 @@
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
+import android.app.compat.CompatChanges;
import android.content.Context;
import android.net.TetheringManager.TetheringRequest;
import android.net.TetheringTester.TetheredDevice;
@@ -1244,6 +1248,11 @@
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Test
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");
assumeFalse(isInterfaceForTetheringAvailable());
setIncludeTestInterfaces(true);
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index 8355d31..1d9c235 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -360,8 +360,7 @@
mUnderlyingNetworks = null;
mEnterpriseId = 0;
mReservationId = RES_ID_UNSET;
- // TODO: Change to default disabled when introduce this filtering.
- mMatchNonThreadLocalNetworks = true;
+ mMatchNonThreadLocalNetworks = false;
}
/**
@@ -2961,8 +2960,7 @@
* Flag to control whether a NetworkRequest can match non-thread local networks.
* @hide
*/
- // TODO: Change to default disabled when introduce this filtering.
- private boolean mMatchNonThreadLocalNetworks = true;
+ private boolean mMatchNonThreadLocalNetworks;
/**
* Returns the match non-thread local networks flag.
diff --git a/framework/src/android/net/connectivity/ConnectivityCompatChanges.java b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
index 2261c69..4ae10d3 100644
--- a/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
+++ b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
@@ -148,6 +148,17 @@
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT)
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() {
}
}
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index bfb51da..83df977 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -120,6 +120,7 @@
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
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_NON_THREAD_LOCAL_NETWORKS;
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.os.Process.INVALID_UID;
@@ -1471,6 +1472,10 @@
return SdkLevel.isAtLeastV();
}
+ public boolean isAtLeastB() {
+ return SdkLevel.isAtLeastB();
+ }
+
/**
* Get system properties to use in ConnectivityService.
*/
@@ -3184,6 +3189,11 @@
}
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)) {
return;
}
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSKeepConnectedTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSKeepConnectedTest.kt
index 4aeae19..c0965b4 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSKeepConnectedTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSKeepConnectedTest.kt
@@ -19,7 +19,7 @@
import android.net.LocalNetworkConfig
import android.net.NetworkCapabilities
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.NetworkScore
import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
@@ -42,7 +42,7 @@
fun testKeepConnectedLocalAgent() {
deps.setBuildSdk(VERSION_V)
val nc = NetworkCapabilities.Builder()
- .addTransportType(TRANSPORT_WIFI)
+ .addTransportType(TRANSPORT_THREAD)
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
.build()
val keepConnectedAgent = Agent(
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentCreationTests.kt b/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentCreationTests.kt
index 6805d9a..6dc9d2d 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentCreationTests.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentCreationTests.kt
@@ -18,14 +18,11 @@
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
import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
import android.net.NetworkRequest
-import android.net.NetworkScore
-import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
import android.net.VpnManager
import android.os.Build
import androidx.test.filters.SmallTest
@@ -46,11 +43,6 @@
private const val TIMEOUT_MS = 2_000L
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
@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
@@ -103,7 +95,7 @@
}
cm.registerNetworkCallback(request.build(), allNetworksCb)
val ncTemplate = NetworkCapabilities.Builder().run {
- addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ addTransportType(NetworkCapabilities.TRANSPORT_THREAD)
addCapability(NET_CAPABILITY_LOCAL_NETWORK)
}.build()
val localAgent = if (params.sdkLevel >= VERSION_V ||
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt b/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt
index d835155..9468d54 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt
@@ -39,6 +39,7 @@
import android.net.NetworkScore.KEEP_CONNECTED_LOCAL_NETWORK
import android.net.RouteInfo
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 com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
@@ -129,6 +130,7 @@
@Test
fun testStructuralConstraintViolation() {
deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback()
cm.requestNetwork(
@@ -162,6 +164,7 @@
@Test
fun testUpdateLocalAgentConfig() {
deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback()
cm.requestNetwork(
@@ -428,6 +431,7 @@
@Test
fun testMulticastRoutingConfig_UpstreamSelectorCellToWifi() {
deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback()
cm.registerNetworkCallback(
NetworkRequest.Builder().clearCapabilities()
@@ -500,6 +504,7 @@
@Test
fun testMulticastRoutingConfig_UpstreamSelectorWifiToNull() {
deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback()
cm.registerNetworkCallback(
NetworkRequest.Builder().clearCapabilities()
@@ -577,6 +582,7 @@
fun doTestUnregisterUpstreamAfterReplacement(sameIfaceName: Boolean) {
deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback()
cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb)
@@ -657,6 +663,7 @@
@Test
fun testUnregisterUpstreamAfterReplacement_neverReplaced() {
deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback()
cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb)
@@ -710,6 +717,7 @@
@Test
fun testUnregisterLocalAgentAfterReplacement() {
deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val localCb = TestableNetworkCallback()
cm.requestNetwork(
@@ -775,6 +783,7 @@
@Test
fun testDestroyedNetworkAsSelectedUpstream() {
deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val cb = TestableNetworkCallback()
cm.registerNetworkCallback(NetworkRequest.Builder().clearCapabilities().build(), cb)
@@ -827,6 +836,7 @@
@Test
fun testForwardingRules() {
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.
val lnc = FromS(
LocalNetworkConfig.Builder()
@@ -965,6 +975,7 @@
fun doTestLocalNetworkUnwanted(haveUpstream: Boolean) {
deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(true, ENABLE_MATCH_NON_THREAD_LOCAL_NETWORKS)
val nr = NetworkRequest.Builder().addCapability(NET_CAPABILITY_LOCAL_NETWORK).build()
val requestCb = TestableNetworkCallback()
@@ -1075,4 +1086,86 @@
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)
+ }
}
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSNetworkRequestStateStatsMetricsTests.kt b/tests/unit/java/com/android/server/connectivityservice/CSNetworkRequestStateStatsMetricsTests.kt
index 35f8ae5..e6a69c3 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSNetworkRequestStateStatsMetricsTests.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSNetworkRequestStateStatsMetricsTests.kt
@@ -20,6 +20,7 @@
import android.net.NetworkRequest
import android.os.Build
import android.os.Process
+import android.text.TextUtils
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.TestableNetworkCallback
@@ -54,9 +55,17 @@
cm.requestNetwork(CELL_INTERNET_NOT_METERED_NR, TestableNetworkCallback())
waitForIdle()
+ // Some fields might be altered by the service, e.g. mMatchNonThreadLocalNetworks.
+ // Check immutable differences instead.
verify(networkRequestStateStatsMetrics).onNetworkRequestReceived(
- argThat{req -> req.networkCapabilities.equals(
- CELL_INTERNET_NOT_METERED_NR.networkCapabilities)})
+ argThat { req ->
+ TextUtils.isEmpty(
+ req.networkCapabilities.describeImmutableDifferences(
+ CELL_INTERNET_NOT_METERED_NR.networkCapabilities
+ )
+ )
+ }
+ )
}
@Test
@@ -77,7 +86,13 @@
cm.unregisterNetworkCallback(cb)
waitForIdle()
verify(networkRequestStateStatsMetrics).onNetworkRequestRemoved(
- argThat{req -> req.networkCapabilities.equals(
- CELL_INTERNET_NOT_METERED_NR.networkCapabilities)})
+ argThat { req ->
+ TextUtils.isEmpty(
+ req.networkCapabilities.describeImmutableDifferences(
+ CELL_INTERNET_NOT_METERED_NR.networkCapabilities
+ )
+ )
+ }
+ )
}
}
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSQueuedCallbacksTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSQueuedCallbacksTest.kt
index fc2a06c..6d1858e 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSQueuedCallbacksTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSQueuedCallbacksTest.kt
@@ -39,6 +39,7 @@
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
+import android.net.NetworkCapabilities.TRANSPORT_THREAD
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkPolicyManager.NetworkPolicyCallback
import android.net.NetworkRequest
@@ -356,6 +357,7 @@
val localAgent = Agent(
nc = defaultNc()
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
+ .addTransportType(TRANSPORT_THREAD)
.removeCapability(NET_CAPABILITY_INTERNET),
lp = defaultLp().apply { interfaceName = "local42" },
lnc = FromS(lnc)
diff --git a/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt b/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt
index 6e07ac6..a77daa8 100644
--- a/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt
@@ -137,7 +137,7 @@
nmCallbacks.notifyNetworkTestedWithExtras(p)
}
- fun connect() {
+ fun connect(expectAvailable: Boolean = true) {
val mgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val request = NetworkRequest.Builder().apply {
clearCapabilities()
@@ -149,26 +149,30 @@
val cb = TestableNetworkCallback()
mgr.registerNetworkCallback(request, cb)
agent.markConnected()
- if (null == cb.poll { it is Available && agent.network == it.network }) {
- if (!nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) &&
- nc.hasTransport(TRANSPORT_CELLULAR)) {
- // ConnectivityService adds NOT_SUSPENDED by default to all non-cell agents. An
- // agent without NOT_SUSPENDED will not connect, instead going into the SUSPENDED
- // state, so this call will not terminate.
- // Instead of forcefully adding NOT_SUSPENDED to all agents like older tools did,
- // it's better to let the developer manage it as they see fit but help them
- // debug if they forget.
- fail(
- "Could not connect the agent. Did you forget to add " +
- "NET_CAPABILITY_NOT_SUSPENDED ?"
- )
+ if (expectAvailable) {
+ if (null == cb.poll { it is Available && agent.network == it.network }) {
+ if (!nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED) &&
+ nc.hasTransport(TRANSPORT_CELLULAR)) {
+ // ConnectivityService adds NOT_SUSPENDED by default to all non-cell agents. An
+ // agent without NOT_SUSPENDED will not connect, instead going into the
+ // SUSPENDED state, so this call will not terminate.
+ // Instead of forcefully adding NOT_SUSPENDED to all agents like older tools did,
+ // it's better to let the developer manage it as they see fit but help them
+ // debug if they forget.
+ fail(
+ "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)
}
- fun disconnect() {
+ fun disconnect(expectAvailable: Boolean = true) {
val mgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val request = NetworkRequest.Builder().apply {
clearCapabilities()
@@ -179,9 +183,14 @@
}.build()
val cb = TestableNetworkCallback(timeoutMs = SHORT_TIMEOUT_MS)
mgr.registerNetworkCallback(request, cb)
- cb.eventuallyExpect<Available> { it.network == agent.network }
- agent.unregister()
- cb.eventuallyExpect<Lost> { it.network == agent.network }
+ if (expectAvailable) {
+ cb.eventuallyExpect<Available> { 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)
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 48333c5..0fe61ec 100644
--- a/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt
@@ -112,7 +112,8 @@
internal const val VERSION_T = 3
internal const val VERSION_U = 4
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
@@ -388,6 +389,7 @@
override fun isAtLeastT() = if (isSdkUnmocked) super.isAtLeastT() else sdkLevel >= VERSION_T
override fun isAtLeastU() = if (isSdkUnmocked) super.isAtLeastU() else sdkLevel >= VERSION_U
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
diff --git a/tests/unit/java/com/android/server/connectivityservice/base/CSTestHelpers.kt b/tests/unit/java/com/android/server/connectivityservice/base/CSTestHelpers.kt
index 5e18843..f28f063 100644
--- a/tests/unit/java/com/android/server/connectivityservice/base/CSTestHelpers.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/base/CSTestHelpers.kt
@@ -34,6 +34,7 @@
import android.net.IpPrefix
import android.net.LinkAddress
import android.net.LinkProperties
+import android.net.LocalNetworkConfig
import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities
import android.net.NetworkScore
@@ -84,6 +85,11 @@
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 {
addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32))
addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))