diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt index 9017f1b96a..b67acca61d 100644 --- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt +++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt @@ -269,10 +269,9 @@ class NetworkAgentTest { history.add(OnSignalStrengthThresholdsUpdated(thresholds)) } - fun expectEmptySignalStrengths() { + fun expectSignalStrengths(thresholds: IntArray? = intArrayOf()) { expectCallback().let { - // intArrayOf() without arguments makes an empty array - assertArrayEquals(intArrayOf(), it.thresholds) + assertArrayEquals(thresholds, it.thresholds) } } @@ -292,7 +291,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().let { + fun expectValidationBypassedStatus() = expectCallback().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 +331,21 @@ class NetworkAgentTest { 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 +360,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 +376,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 { - 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() + agent.expectSignalStrengths(expectedInitSignalStrengthThresholds) + agent.expectValidationBypassedStatus() + callback.expectAvailableThenValidatedCallbacks(agent.network!!) return agent to callback } @@ -413,7 +425,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 +444,8 @@ class NetworkAgentTest { @Test fun testConnectAndUnregister() { val (agent, callback) = createConnectedNetworkAgent() - callback.expectAvailableThenValidatedCallbacks(agent.network) - agent.expectEmptySignalStrengths() - agent.expectNoInternetValidationStatus() - unregister(agent) - callback.expectCallback(agent.network) + callback.expectCallback(agent.network!!) assertFailsWith("Must not be able to register an agent twice") { agent.register() } @@ -446,11 +453,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() unregister(agent) } @@ -468,13 +472,8 @@ class NetworkAgentTest { registerNetworkCallback(request, it) } } - createConnectedNetworkAgent().let { (agent, callback) -> - callback.expectAvailableThenValidatedCallbacks(agent.network) - agent.expectCallback().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 +482,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(agent.network) + callbacks[0].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 } + callbacks[1].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 } + callbacks[2].expectCallback(agent.network!!) } callbacks.forEach { mCM.unregisterNetworkCallback(it) @@ -546,20 +545,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 +564,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(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(agent2.network!!) // tearDown() will unregister the requests and agents } @@ -658,7 +630,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 +662,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 +673,7 @@ class NetworkAgentTest { } unregister(agent) - callback.expectCallback(agent.network) + callback.expectCallback(agent.network!!) } private fun unregister(agent: TestableNetworkAgent) { @@ -789,43 +761,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,85 +791,78 @@ 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 { - agent1.setLingerDuration(Duration.ofMillis(-1)) + agentWeaker.setLingerDuration(Duration.ofMillis(-1)) } - assertFailsWith { agent1.setLingerDuration(Duration.ZERO) } + assertFailsWith { agentWeaker.setLingerDuration(Duration.ZERO) } assertFailsWith { - agent1.setLingerDuration(Duration.ofMillis(Integer.MIN_VALUE.toLong())) + agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MIN_VALUE.toLong())) } assertFailsWith { - agent1.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong() + 1)) + agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong() + 1)) } assertFailsWith { - 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(agent1.network!!) + val agentStronger = createNetworkAgent(specifier = specifierStronger) + agentStronger.register() + agentStronger.markConnected() + commonCallback.expectAvailableCallbacks(agentStronger.network!!) + callbackWeaker.expectCallback(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(agent1.network!!) + callbackWeaker.expectCallback(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 }