Merge changes I627dcd0f,I81abc174,Id7948d21 am: 75090fb64e

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1731450

Change-Id: I3662e70034b16721e4ad1711654cb9f7eda45d35
This commit is contained in:
Junyu Lai
2021-06-16 11:59:37 +00:00
committed by Automerger Merge Worker
3 changed files with 226 additions and 174 deletions

View File

@@ -18,6 +18,7 @@ package android.net
import android.app.Instrumentation
import android.content.Context
import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
import android.net.NetworkCapabilities.TRANSPORT_TEST
import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable
import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn
@@ -25,14 +26,18 @@ import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetwo
import android.os.Build
import android.os.HandlerThread
import android.os.Looper
import android.util.Log
import androidx.test.InstrumentationRegistry
import com.android.net.module.util.ArrayTrackRecord
import com.android.testutils.CompatUtil
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.isDevSdkInRange
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.doReturn
@@ -41,6 +46,7 @@ import org.mockito.Mockito.verifyNoMoreInteractions
import java.util.UUID
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.fail
private const val DEFAULT_TIMEOUT_MS = 5000L
private val instrumentation: Instrumentation
@@ -51,6 +57,8 @@ private val PROVIDER_NAME = "NetworkProviderTest"
@RunWith(DevSdkIgnoreRunner::class)
@IgnoreUpTo(Build.VERSION_CODES.Q)
class NetworkProviderTest {
@Rule @JvmField
val mIgnoreRule = DevSdkIgnoreRule()
private val mCm = context.getSystemService(ConnectivityManager::class.java)
private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread")
@@ -68,6 +76,7 @@ class NetworkProviderTest {
private class TestNetworkProvider(context: Context, looper: Looper) :
NetworkProvider(context, looper, PROVIDER_NAME) {
private val TAG = this::class.simpleName
private val seenEvents = ArrayTrackRecord<CallbackEntry>().newReadHead()
sealed class CallbackEntry {
@@ -80,22 +89,30 @@ class NetworkProviderTest {
}
override fun onNetworkRequested(request: NetworkRequest, score: Int, id: Int) {
Log.d(TAG, "onNetworkRequested $request, $score, $id")
seenEvents.add(OnNetworkRequested(request, score, id))
}
override fun onNetworkRequestWithdrawn(request: NetworkRequest) {
Log.d(TAG, "onNetworkRequestWithdrawn $request")
seenEvents.add(OnNetworkRequestWithdrawn(request))
}
inline fun <reified T : CallbackEntry> expectCallback(
inline fun <reified T : CallbackEntry> eventuallyExpectCallbackThat(
crossinline predicate: (T) -> Boolean
) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) }
?: fail("Did not receive callback after ${DEFAULT_TIMEOUT_MS}ms")
}
private fun createNetworkProvider(ctx: Context = context): TestNetworkProvider {
return TestNetworkProvider(ctx, mHandlerThread.looper)
}
// In S+ framework, do not run this test, since the provider will no longer receive
// onNetworkRequested for every request. Instead, provider needs to
// call {@code registerNetworkOffer} with the description of networks they
// might have ability to setup, and expects {@link NetworkOfferCallback#onNetworkNeeded}.
@IgnoreAfter(Build.VERSION_CODES.R)
@Test
fun testOnNetworkRequested() {
val provider = createNetworkProvider()
@@ -105,13 +122,15 @@ class NetworkProviderTest {
val specifier = CompatUtil.makeTestNetworkSpecifier(
UUID.randomUUID().toString())
// Test network is not allowed to be trusted.
val nr: NetworkRequest = NetworkRequest.Builder()
.addTransportType(TRANSPORT_TEST)
.removeCapability(NET_CAPABILITY_TRUSTED)
.setNetworkSpecifier(specifier)
.build()
val cb = ConnectivityManager.NetworkCallback()
mCm.requestNetwork(nr, cb)
provider.expectCallback<OnNetworkRequested>() { callback ->
provider.eventuallyExpectCallbackThat<OnNetworkRequested>() { callback ->
callback.request.getNetworkSpecifier() == specifier &&
callback.request.hasTransport(TRANSPORT_TEST)
}
@@ -131,22 +150,24 @@ class NetworkProviderTest {
val config = NetworkAgentConfig.Builder().build()
val agent = object : NetworkAgent(context, mHandlerThread.looper, "TestAgent", nc, lp,
initialScore, config, provider) {}
agent.register()
agent.markConnected()
provider.expectCallback<OnNetworkRequested>() { callback ->
provider.eventuallyExpectCallbackThat<OnNetworkRequested>() { callback ->
callback.request.getNetworkSpecifier() == specifier &&
callback.score == initialScore &&
callback.id == agent.providerId
}
agent.sendNetworkScore(updatedScore)
provider.expectCallback<OnNetworkRequested>() { callback ->
provider.eventuallyExpectCallbackThat<OnNetworkRequested>() { callback ->
callback.request.getNetworkSpecifier() == specifier &&
callback.score == updatedScore &&
callback.id == agent.providerId
}
mCm.unregisterNetworkCallback(cb)
provider.expectCallback<OnNetworkRequestWithdrawn>() { callback ->
provider.eventuallyExpectCallbackThat<OnNetworkRequestWithdrawn>() { callback ->
callback.request.getNetworkSpecifier() == specifier &&
callback.request.hasTransport(TRANSPORT_TEST)
}

View File

@@ -650,6 +650,18 @@ public class ConnectivityManagerTest {
mCm.getBackgroundDataSetting();
}
private NetworkRequest makeDefaultRequest() {
// Make a request that is similar to the way framework tracks the system
// default network.
return new NetworkRequest.Builder()
.clearCapabilities()
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
}
private NetworkRequest makeWifiNetworkRequest() {
return new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
@@ -710,12 +722,14 @@ public class ConnectivityManagerTest {
final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
final TestNetworkCallback perUidCallback = new TestNetworkCallback();
final TestNetworkCallback bestMatchingCallback = new TestNetworkCallback();
final Handler h = new Handler(Looper.getMainLooper());
if (TestUtils.shouldTestSApis()) {
runWithShellPermissionIdentity(() -> {
mCmShim.registerSystemDefaultNetworkCallback(systemDefaultCallback, h);
mCmShim.registerDefaultNetworkCallbackForUid(Process.myUid(), perUidCallback, h);
}, NETWORK_SETTINGS);
mCm.registerBestMatchingNetworkCallback(makeDefaultRequest(), bestMatchingCallback, h);
}
Network wifiNetwork = null;
@@ -741,6 +755,10 @@ public class ConnectivityManagerTest {
assertNotNull("Did not receive onAvailable on per-UID default network callback",
perUidNetwork);
assertEquals(defaultNetwork, perUidNetwork);
final Network bestMatchingNetwork = bestMatchingCallback.waitForAvailable();
assertNotNull("Did not receive onAvailable on best matching network callback",
bestMatchingNetwork);
assertEquals(defaultNetwork, bestMatchingNetwork);
}
} catch (InterruptedException e) {
@@ -751,6 +769,7 @@ public class ConnectivityManagerTest {
if (TestUtils.shouldTestSApis()) {
mCm.unregisterNetworkCallback(systemDefaultCallback);
mCm.unregisterNetworkCallback(perUidCallback);
mCm.unregisterNetworkCallback(bestMatchingCallback);
}
}
}

View File

@@ -66,6 +66,7 @@ import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnSta
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnStopSocketKeepalive
import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnValidationStatus
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.os.Message
@@ -269,10 +270,9 @@ class NetworkAgentTest {
history.add(OnSignalStrengthThresholdsUpdated(thresholds))
}
fun expectEmptySignalStrengths() {
fun expectSignalStrengths(thresholds: IntArray? = intArrayOf()) {
expectCallback<OnSignalStrengthThresholdsUpdated>().let {
// intArrayOf() without arguments makes an empty array
assertArrayEquals(intArrayOf(), it.thresholds)
assertArrayEquals(thresholds, it.thresholds)
}
}
@@ -292,7 +292,7 @@ class NetworkAgentTest {
// a NetworkAgent whose network does not require validation (which test networks do
// not, since they lack the INTERNET capability). It always contains the default argument
// for the URI.
fun expectNoInternetValidationStatus() = expectCallback<OnValidationStatus>().let {
fun expectValidationBypassedStatus() = expectCallback<OnValidationStatus>().let {
assertEquals(it.status, VALID_NETWORK)
// The returned Uri is parsed from the empty string, which means it's an
// instance of the (private) Uri.StringUri. There are no real good ways
@@ -332,9 +332,30 @@ class NetworkAgentTest {
callbacksToCleanUp.add(callback)
}
private fun registerBestMatchingNetworkCallback(
request: NetworkRequest,
callback: TestableNetworkCallback,
handler: Handler
) {
mCM!!.registerBestMatchingNetworkCallback(request, callback, handler)
callbacksToCleanUp.add(callback)
}
private fun makeTestNetworkRequest(specifier: String? = null): NetworkRequest {
return NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.also {
if (specifier != null) {
it.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifier))
}
}
.build()
}
private fun createNetworkAgent(
context: Context = realContext,
name: String? = null,
specifier: String? = null,
initialNc: NetworkCapabilities? = null,
initialLp: LinkProperties? = null,
initialConfig: NetworkAgentConfig? = null
@@ -349,8 +370,8 @@ class NetworkAgentTest {
if (SdkLevel.isAtLeastS()) {
addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
}
if (null != name) {
setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(name))
if (null != specifier) {
setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifier))
}
}
val lp = initialLp ?: LinkProperties().apply {
@@ -365,21 +386,22 @@ class NetworkAgentTest {
private fun createConnectedNetworkAgent(
context: Context = realContext,
name: String? = null,
initialConfig: NetworkAgentConfig? = null
specifier: String? = UUID.randomUUID().toString(),
initialConfig: NetworkAgentConfig? = null,
expectedInitSignalStrengthThresholds: IntArray? = intArrayOf()
): Pair<TestableNetworkAgent, TestableNetworkCallback> {
val request: NetworkRequest = NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.build()
val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
requestNetwork(request, callback)
val config = initialConfig ?: NetworkAgentConfig.Builder().build()
val agent = createNetworkAgent(context, name, initialConfig = config)
// Ensure this NetworkAgent is never unneeded by filing a request with its specifier.
requestNetwork(makeTestNetworkRequest(specifier = specifier), callback)
val agent = createNetworkAgent(context, specifier, initialConfig = initialConfig)
agent.setTeardownDelayMillis(0)
// Connect the agent and verify initial status callbacks.
agent.register()
agent.markConnected()
agent.expectCallback<OnNetworkCreated>()
agent.expectSignalStrengths(expectedInitSignalStrengthThresholds)
agent.expectValidationBypassedStatus()
callback.expectAvailableThenValidatedCallbacks(agent.network!!)
return agent to callback
}
@@ -413,7 +435,6 @@ class NetworkAgentTest {
.setLegacySubType(subtypeLTE)
.setLegacySubTypeName(subtypeNameLTE).build()
val (agent, callback) = createConnectedNetworkAgent(initialConfig = config)
callback.expectAvailableThenValidatedCallbacks(agent.network)
agent.setLegacySubtype(subtypeUMTS, subtypeNameUMTS)
// There is no callback when networkInfo changes,
@@ -433,12 +454,8 @@ class NetworkAgentTest {
@Test
fun testConnectAndUnregister() {
val (agent, callback) = createConnectedNetworkAgent()
callback.expectAvailableThenValidatedCallbacks(agent.network)
agent.expectEmptySignalStrengths()
agent.expectNoInternetValidationStatus()
unregister(agent)
callback.expectCallback<Lost>(agent.network)
callback.expectCallback<Lost>(agent.network!!)
assertFailsWith<IllegalStateException>("Must not be able to register an agent twice") {
agent.register()
}
@@ -446,11 +463,8 @@ class NetworkAgentTest {
@Test
fun testOnBandwidthUpdateRequested() {
val (agent, callback) = createConnectedNetworkAgent()
callback.expectAvailableThenValidatedCallbacks(agent.network)
agent.expectEmptySignalStrengths()
agent.expectNoInternetValidationStatus()
mCM.requestBandwidthUpdate(agent.network)
val (agent, _) = createConnectedNetworkAgent()
mCM.requestBandwidthUpdate(agent.network!!)
agent.expectCallback<OnBandwidthUpdateRequested>()
unregister(agent)
}
@@ -468,13 +482,8 @@ class NetworkAgentTest {
registerNetworkCallback(request, it)
}
}
createConnectedNetworkAgent().let { (agent, callback) ->
callback.expectAvailableThenValidatedCallbacks(agent.network)
agent.expectCallback<OnSignalStrengthThresholdsUpdated>().let {
assertArrayEquals(it.thresholds, thresholds)
}
agent.expectNoInternetValidationStatus()
createConnectedNetworkAgent(expectedInitSignalStrengthThresholds = thresholds).let {
(agent, callback) ->
// Send signal strength and check that the callbacks are called appropriately.
val nc = NetworkCapabilities(agent.nc)
nc.setSignalStrength(20)
@@ -483,21 +492,21 @@ class NetworkAgentTest {
nc.setSignalStrength(40)
agent.sendNetworkCapabilities(nc)
callbacks[0].expectAvailableCallbacks(agent.network)
callbacks[0].expectAvailableCallbacks(agent.network!!)
callbacks[1].assertNoCallback(NO_CALLBACK_TIMEOUT)
callbacks[2].assertNoCallback(NO_CALLBACK_TIMEOUT)
nc.setSignalStrength(80)
agent.sendNetworkCapabilities(nc)
callbacks[0].expectCapabilitiesThat(agent.network) { it.signalStrength == 80 }
callbacks[1].expectAvailableCallbacks(agent.network)
callbacks[2].expectAvailableCallbacks(agent.network)
callbacks[0].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 80 }
callbacks[1].expectAvailableCallbacks(agent.network!!)
callbacks[2].expectAvailableCallbacks(agent.network!!)
nc.setSignalStrength(55)
agent.sendNetworkCapabilities(nc)
callbacks[0].expectCapabilitiesThat(agent.network) { it.signalStrength == 55 }
callbacks[1].expectCapabilitiesThat(agent.network) { it.signalStrength == 55 }
callbacks[2].expectCallback<Lost>(agent.network)
callbacks[0].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 }
callbacks[1].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 }
callbacks[2].expectCallback<Lost>(agent.network!!)
}
callbacks.forEach {
mCM.unregisterNetworkCallback(it)
@@ -546,20 +555,17 @@ class NetworkAgentTest {
@Test
fun testSendUpdates(): Unit = createConnectedNetworkAgent().let { (agent, callback) ->
callback.expectAvailableThenValidatedCallbacks(agent.network)
agent.expectEmptySignalStrengths()
agent.expectNoInternetValidationStatus()
val ifaceName = "adhocIface"
val lp = LinkProperties(agent.lp)
lp.setInterfaceName(ifaceName)
agent.sendLinkProperties(lp)
callback.expectLinkPropertiesThat(agent.network) {
callback.expectLinkPropertiesThat(agent.network!!) {
it.getInterfaceName() == ifaceName
}
val nc = NetworkCapabilities(agent.nc)
nc.addCapability(NET_CAPABILITY_NOT_METERED)
agent.sendNetworkCapabilities(nc)
callback.expectCapabilitiesThat(agent.network) {
callback.expectCapabilitiesThat(agent.network!!) {
it.hasCapability(NET_CAPABILITY_NOT_METERED)
}
}
@@ -568,56 +574,32 @@ class NetworkAgentTest {
fun testSendScore() {
// This test will create two networks and check that the one with the stronger
// score wins out for a request that matches them both.
// First create requests to make sure both networks are kept up, using the
// specifier so they are specific to each network
val name1 = UUID.randomUUID().toString()
val name2 = UUID.randomUUID().toString()
val request1 = NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(name1))
.build()
val request2 = NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(name2))
.build()
val callback1 = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
val callback2 = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
requestNetwork(request1, callback1)
requestNetwork(request2, callback2)
// Then file the interesting request
val request = NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.build()
// File the interesting request
val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
requestNetwork(request, callback)
requestNetwork(makeTestNetworkRequest(), callback)
// Connect the first Network
createConnectedNetworkAgent(name = name1).let { (agent1, _) ->
callback.expectAvailableThenValidatedCallbacks(agent1.network)
// If using the int ranking, agent1 must be upgraded to a better score so that there is
// no ambiguity when agent2 connects that agent1 is still better. If using policy
// ranking, this is not necessary.
agent1.sendNetworkScore(NetworkScore.Builder().setLegacyInt(BETTER_NETWORK_SCORE)
.build())
// Connect the second agent
createConnectedNetworkAgent(name = name2).let { (agent2, _) ->
agent2.markConnected()
// The callback should not see anything yet. With int ranking, agent1 was upgraded
// to a stronger score beforehand. With policy ranking, agent1 is preferred by
// virtue of already satisfying the request.
callback.assertNoCallback(NO_CALLBACK_TIMEOUT)
// Now downgrade the score and expect the callback now prefers agent2
agent1.sendNetworkScore(NetworkScore.Builder()
.setLegacyInt(WORSE_NETWORK_SCORE)
.setExiting(true)
.build())
callback.expectCallback<Available>(agent2.network)
}
}
// Connect the first Network, with an unused callback that kept the network up.
val (agent1, _) = createConnectedNetworkAgent()
callback.expectAvailableThenValidatedCallbacks(agent1.network!!)
// If using the int ranking, agent1 must be upgraded to a better score so that there is
// no ambiguity when agent2 connects that agent1 is still better. If using policy
// ranking, this is not necessary.
agent1.sendNetworkScore(NetworkScore.Builder().setLegacyInt(BETTER_NETWORK_SCORE)
.build())
// Connect the second agent.
val (agent2, _) = createConnectedNetworkAgent()
// The callback should not see anything yet. With int ranking, agent1 was upgraded
// to a stronger score beforehand. With policy ranking, agent1 is preferred by
// virtue of already satisfying the request.
callback.assertNoCallback(NO_CALLBACK_TIMEOUT)
// Now downgrade the score and expect the callback now prefers agent2
agent1.sendNetworkScore(NetworkScore.Builder()
.setLegacyInt(WORSE_NETWORK_SCORE)
.setExiting(true)
.build())
callback.expectCallback<Available>(agent2.network!!)
// tearDown() will unregister the requests and agents
}
@@ -658,7 +640,7 @@ class NetworkAgentTest {
callback.expectAvailableThenValidatedCallbacks(agent.network!!)
// Check that the default network's transport is propagated to the VPN.
var vpnNc = mCM.getNetworkCapabilities(agent.network)
var vpnNc = mCM.getNetworkCapabilities(agent.network!!)
assertNotNull(vpnNc)
assertEquals(VpnManager.TYPE_VPN_SERVICE,
(vpnNc.transportInfo as VpnTransportInfo).type)
@@ -690,7 +672,7 @@ class NetworkAgentTest {
// This is not very accurate because the test does not control the capabilities of the
// underlying networks, and because not congested, not roaming, and not suspended are the
// default anyway. It's still useful as an extra check though.
vpnNc = mCM.getNetworkCapabilities(agent.network)
vpnNc = mCM.getNetworkCapabilities(agent.network!!)
for (cap in listOf(NET_CAPABILITY_NOT_CONGESTED,
NET_CAPABILITY_NOT_ROAMING,
NET_CAPABILITY_NOT_SUSPENDED)) {
@@ -701,7 +683,7 @@ class NetworkAgentTest {
}
unregister(agent)
callback.expectCallback<Lost>(agent.network)
callback.expectCallback<Lost>(agent.network!!)
}
private fun unregister(agent: TestableNetworkAgent) {
@@ -789,43 +771,24 @@ class NetworkAgentTest {
fun testTemporarilyUnmeteredCapability() {
// This test will create a networks with/without NET_CAPABILITY_TEMPORARILY_NOT_METERED
// and check that the callback reflects the capability changes.
// First create a request to make sure the network is kept up
val request1 = NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.build()
val callback1 = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS).also {
registerNetworkCallback(request1, it)
}
requestNetwork(request1, callback1)
// Then file the interesting request
val request = NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.build()
val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
requestNetwork(request, callback)
// Connect the network
createConnectedNetworkAgent().let { (agent, _) ->
callback.expectAvailableThenValidatedCallbacks(agent.network)
val (agent, callback) = createConnectedNetworkAgent()
// Send TEMP_NOT_METERED and check that the callback is called appropriately.
val nc1 = NetworkCapabilities(agent.nc)
.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
agent.sendNetworkCapabilities(nc1)
callback.expectCapabilitiesThat(agent.network) {
it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
}
// Send TEMP_NOT_METERED and check that the callback is called appropriately.
val nc1 = NetworkCapabilities(agent.nc)
.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
agent.sendNetworkCapabilities(nc1)
callback.expectCapabilitiesThat(agent.network!!) {
it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
}
// Remove TEMP_NOT_METERED and check that the callback is called appropriately.
val nc2 = NetworkCapabilities(agent.nc)
.removeCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
agent.sendNetworkCapabilities(nc2)
callback.expectCapabilitiesThat(agent.network) {
!it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
}
// Remove TEMP_NOT_METERED and check that the callback is called appropriately.
val nc2 = NetworkCapabilities(agent.nc)
.removeCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
agent.sendNetworkCapabilities(nc2)
callback.expectCapabilitiesThat(agent.network!!) {
!it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
}
// tearDown() will unregister the requests and agents
@@ -838,88 +801,137 @@ class NetworkAgentTest {
// score wins out for a request that matches them both. And the weaker agent will
// be disconnected after customized linger duration.
// Connect the first Network
val name1 = UUID.randomUUID().toString()
val name2 = UUID.randomUUID().toString()
val (agent1, callback) = createConnectedNetworkAgent(name = name1)
callback.expectAvailableThenValidatedCallbacks(agent1.network!!)
// Downgrade agent1 to a worse score so that there is no ambiguity when
// agent2 connects.
agent1.sendNetworkScore(NetworkScore.Builder().setLegacyInt(WORSE_NETWORK_SCORE)
// Request the first Network, with a request that could moved to agentStronger in order to
// make agentWeaker linger later.
val specifierWeaker = UUID.randomUUID().toString()
val specifierStronger = UUID.randomUUID().toString()
val commonCallback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
requestNetwork(makeTestNetworkRequest(), commonCallback)
val agentWeaker = createNetworkAgent(specifier = specifierWeaker)
agentWeaker.register()
agentWeaker.markConnected()
commonCallback.expectAvailableThenValidatedCallbacks(agentWeaker.network!!)
// Downgrade agentWeaker to a worse score so that there is no ambiguity when
// agentStronger connects.
agentWeaker.sendNetworkScore(NetworkScore.Builder().setLegacyInt(WORSE_NETWORK_SCORE)
.setExiting(true).build())
// Verify invalid linger duration cannot be set.
assertFailsWith<IllegalArgumentException> {
agent1.setLingerDuration(Duration.ofMillis(-1))
agentWeaker.setLingerDuration(Duration.ofMillis(-1))
}
assertFailsWith<IllegalArgumentException> { agent1.setLingerDuration(Duration.ZERO) }
assertFailsWith<IllegalArgumentException> { agentWeaker.setLingerDuration(Duration.ZERO) }
assertFailsWith<IllegalArgumentException> {
agent1.setLingerDuration(Duration.ofMillis(Integer.MIN_VALUE.toLong()))
agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MIN_VALUE.toLong()))
}
assertFailsWith<IllegalArgumentException> {
agent1.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong() + 1))
agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong() + 1))
}
assertFailsWith<IllegalArgumentException> {
agent1.setLingerDuration(Duration.ofMillis(
agentWeaker.setLingerDuration(Duration.ofMillis(
NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - 1))
}
// Verify valid linger timer can be set, but it should not take effect since the network
// is still needed.
agent1.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong()))
callback.assertNoCallback(NO_CALLBACK_TIMEOUT)
agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong()))
commonCallback.assertNoCallback(NO_CALLBACK_TIMEOUT)
// Set to the value we want to verify the functionality.
agent1.setLingerDuration(Duration.ofMillis(NetworkAgent.MIN_LINGER_TIMER_MS.toLong()))
// Make a listener which can observe agent1 lost later.
agentWeaker.setLingerDuration(Duration.ofMillis(NetworkAgent.MIN_LINGER_TIMER_MS.toLong()))
// Make a listener which can observe agentWeaker lost later.
val callbackWeaker = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
registerNetworkCallback(NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(name1))
.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifierWeaker))
.build(), callbackWeaker)
callbackWeaker.expectAvailableCallbacks(agent1.network!!)
callbackWeaker.expectAvailableCallbacks(agentWeaker.network!!)
// Connect the second agent with a score better than agent1. Verify the callback for
// agent1 sees the linger expiry while the callback for both sees the winner.
// Connect the agentStronger with a score better than agentWeaker. Verify the callback for
// agentWeaker sees the linger expiry while the callback for both sees the winner.
// Record linger start timestamp prior to send score to prevent possible race, the actual
// timestamp should be slightly late than this since the service handles update
// network score asynchronously.
val lingerStart = SystemClock.elapsedRealtime()
val agent2 = createNetworkAgent(name = name2)
agent2.register()
agent2.markConnected()
callback.expectAvailableCallbacks(agent2.network!!)
callbackWeaker.expectCallback<Losing>(agent1.network!!)
val agentStronger = createNetworkAgent(specifier = specifierStronger)
agentStronger.register()
agentStronger.markConnected()
commonCallback.expectAvailableCallbacks(agentStronger.network!!)
callbackWeaker.expectCallback<Losing>(agentWeaker.network!!)
val expectedRemainingLingerDuration = lingerStart +
NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - SystemClock.elapsedRealtime()
// If the available callback is too late. The remaining duration will be reduced.
assertTrue(expectedRemainingLingerDuration > 0,
"expected remaining linger duration is $expectedRemainingLingerDuration")
callbackWeaker.assertNoCallback(expectedRemainingLingerDuration)
callbackWeaker.expectCallback<Lost>(agent1.network!!)
callbackWeaker.expectCallback<Lost>(agentWeaker.network!!)
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.R)
fun testSetSubscriberId() {
val name = "TEST-AGENT"
val imsi = UUID.randomUUID().toString()
val config = NetworkAgentConfig.Builder().setSubscriberId(imsi).build()
val request: NetworkRequest = NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(name))
.build()
val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
requestNetwork(request, callback)
val agent = createNetworkAgent(name = name, initialConfig = config)
agent.register()
agent.markConnected()
callback.expectAvailableThenValidatedCallbacks(agent.network!!)
val (agent, _) = createConnectedNetworkAgent(initialConfig = config)
val snapshots = runWithShellPermissionIdentity(ThrowingSupplier {
mCM!!.allNetworkStateSnapshots }, NETWORK_SETTINGS)
val testNetworkSnapshot = snapshots.findLast { it.network == agent.network }
assertEquals(imsi, testNetworkSnapshot!!.subscriberId)
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.R)
// TODO: Refactor helper functions to util class and move this test case to
// {@link android.net.cts.ConnectivityManagerTest}.
fun testRegisterBestMatchingNetworkCallback() {
// Register best matching network callback with additional condition that will be
// exercised later. This assumes the test network agent has NOT_VCN_MANAGED in it and
// does not have NET_CAPABILITY_TEMPORARILY_NOT_METERED.
val bestMatchingCb = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
registerBestMatchingNetworkCallback(NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
.build(), bestMatchingCb, mHandlerThread.threadHandler)
val (agent1, _) = createConnectedNetworkAgent(specifier = "AGENT-1")
bestMatchingCb.expectAvailableThenValidatedCallbacks(agent1.network!!)
// Make agent1 worse so when agent2 shows up, the callback will see that.
agent1.sendNetworkScore(NetworkScore.Builder().setExiting(true).build())
bestMatchingCb.assertNoCallback(NO_CALLBACK_TIMEOUT)
val (agent2, _) = createConnectedNetworkAgent(specifier = "AGENT-2")
bestMatchingCb.expectAvailableDoubleValidatedCallbacks(agent2.network!!)
// Change something on agent1 to trigger capabilities changed, since the callback
// only cares about the best network, verify it received nothing from agent1.
val ncAgent1 = agent1.nc
ncAgent1.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
agent1.sendNetworkCapabilities(ncAgent1)
bestMatchingCb.assertNoCallback(NO_CALLBACK_TIMEOUT)
// Make agent1 the best network again, verify the callback now tracks agent1.
agent1.sendNetworkScore(NetworkScore.Builder()
.setExiting(false).setTransportPrimary(true).build())
bestMatchingCb.expectAvailableCallbacks(agent1.network!!)
// Make agent1 temporary vcn managed, which will not satisfying the request.
// Verify the callback switch from/to the other network accordingly.
ncAgent1.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
agent1.sendNetworkCapabilities(ncAgent1)
bestMatchingCb.expectAvailableCallbacks(agent2.network!!)
ncAgent1.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
agent1.sendNetworkCapabilities(ncAgent1)
bestMatchingCb.expectAvailableDoubleValidatedCallbacks(agent1.network!!)
// Verify the callback doesn't care about agent2 disconnect.
agent2.unregister()
agentsToCleanUp.remove(agent2)
bestMatchingCb.assertNoCallback()
agent1.unregister()
agentsToCleanUp.remove(agent1)
bestMatchingCb.expectCallback<Lost>(agent1.network!!)
// tearDown() will unregister the requests and agents
}
}