1 /* <lambda>null2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.net.cts 17 18 import android.Manifest.permission.NETWORK_SETTINGS 19 import android.app.Instrumentation 20 import android.content.Context 21 import android.net.ConnectivityManager 22 import android.net.EthernetNetworkSpecifier 23 import android.net.INetworkAgent 24 import android.net.INetworkAgentRegistry 25 import android.net.InetAddresses 26 import android.net.IpPrefix 27 import android.net.LinkAddress 28 import android.net.LinkProperties 29 import android.net.NattKeepalivePacketData 30 import android.net.Network 31 import android.net.NetworkAgent 32 import android.net.NetworkAgentConfig 33 import android.net.NetworkAgent.INVALID_NETWORK 34 import android.net.NetworkAgent.VALID_NETWORK 35 import android.net.NetworkCapabilities 36 import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET 37 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED 38 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED 39 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED 40 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING 41 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED 42 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED 43 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN 44 import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED 45 import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED 46 import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED 47 import android.net.NetworkCapabilities.TRANSPORT_CELLULAR 48 import android.net.NetworkCapabilities.TRANSPORT_TEST 49 import android.net.NetworkCapabilities.TRANSPORT_WIFI 50 import android.net.NetworkCapabilities.TRANSPORT_VPN 51 import android.net.NetworkInfo 52 import android.net.NetworkProvider 53 import android.net.NetworkReleasedException 54 import android.net.NetworkRequest 55 import android.net.NetworkScore 56 import android.net.RouteInfo 57 import android.net.QosCallback 58 import android.net.QosCallbackException 59 import android.net.QosCallback.QosCallbackRegistrationException 60 import android.net.QosSession 61 import android.net.QosSessionAttributes 62 import android.net.QosSocketInfo 63 import android.net.SocketKeepalive 64 import android.net.Uri 65 import android.net.VpnManager 66 import android.net.VpnTransportInfo 67 import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnError 68 import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnQosSessionAvailable 69 import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnQosSessionLost 70 import android.os.Build 71 import android.os.Handler 72 import android.os.HandlerThread 73 import android.os.Message 74 import android.os.SystemClock 75 import android.platform.test.annotations.AppModeFull 76 import android.telephony.TelephonyManager 77 import android.telephony.data.EpsBearerQosSessionAttributes 78 import android.util.DebugUtils.valueToString 79 import androidx.test.InstrumentationRegistry 80 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity 81 import com.android.compatibility.common.util.ThrowingSupplier 82 import com.android.modules.utils.build.SdkLevel 83 import com.android.net.module.util.ArrayTrackRecord 84 import com.android.testutils.CompatUtil 85 import com.android.testutils.ConnectivityModuleTest 86 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo 87 import com.android.testutils.DevSdkIgnoreRunner 88 import com.android.testutils.RecorderCallback.CallbackEntry.Available 89 import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus 90 import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged 91 import com.android.testutils.RecorderCallback.CallbackEntry.Losing 92 import com.android.testutils.RecorderCallback.CallbackEntry.Lost 93 import com.android.testutils.TestableNetworkAgent 94 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnAddKeepalivePacketFilter 95 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnAutomaticReconnectDisabled 96 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnBandwidthUpdateRequested 97 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated 98 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkDestroyed 99 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkUnwanted 100 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnRegisterQosCallback 101 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnRemoveKeepalivePacketFilter 102 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnSaveAcceptUnvalidated 103 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnStartSocketKeepalive 104 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnStopSocketKeepalive 105 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnUnregisterQosCallback 106 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnValidationStatus 107 import com.android.testutils.TestableNetworkCallback 108 import com.android.testutils.assertThrows 109 import org.junit.After 110 import org.junit.Before 111 import org.junit.Test 112 import org.junit.runner.RunWith 113 import org.mockito.ArgumentMatchers.any 114 import org.mockito.ArgumentMatchers.argThat 115 import org.mockito.ArgumentMatchers.eq 116 import org.mockito.Mockito.doReturn 117 import org.mockito.Mockito.mock 118 import org.mockito.Mockito.timeout 119 import org.mockito.Mockito.verify 120 import java.io.IOException 121 import java.net.DatagramSocket 122 import java.net.InetAddress 123 import java.net.InetSocketAddress 124 import java.net.Socket 125 import java.time.Duration 126 import java.util.Arrays 127 import java.util.UUID 128 import java.util.concurrent.Executors 129 import kotlin.test.assertEquals 130 import kotlin.test.assertFailsWith 131 import kotlin.test.assertFalse 132 import kotlin.test.assertNotNull 133 import kotlin.test.assertNull 134 import kotlin.test.assertTrue 135 import kotlin.test.fail 136 137 // This test doesn't really have a constraint on how fast the methods should return. If it's 138 // going to fail, it will simply wait forever, so setting a high timeout lowers the flake ratio 139 // without affecting the run time of successful runs. Thus, set a very high timeout. 140 private const val DEFAULT_TIMEOUT_MS = 5000L 141 // When waiting for a NetworkCallback to determine there was no timeout, waiting is the 142 // only possible thing (the relevant handler is the one in the real ConnectivityService, 143 // and then there is the Binder call), so have a short timeout for this as it will be 144 // exhausted every time. 145 private const val NO_CALLBACK_TIMEOUT = 200L 146 private const val WORSE_NETWORK_SCORE = 65 147 private const val BETTER_NETWORK_SCORE = 75 148 private const val FAKE_NET_ID = 1098 149 private val instrumentation: Instrumentation 150 get() = InstrumentationRegistry.getInstrumentation() 151 private val realContext: Context 152 get() = InstrumentationRegistry.getContext() 153 private fun Message(what: Int, arg1: Int, arg2: Int, obj: Any?) = Message.obtain().also { 154 it.what = what 155 it.arg1 = arg1 156 it.arg2 = arg2 157 it.obj = obj 158 } 159 160 @RunWith(DevSdkIgnoreRunner::class) 161 // NetworkAgent is not updatable in R-, so this test does not need to be compatible with older 162 // versions. NetworkAgent was also based on AsyncChannel before S so cannot be tested the same way. 163 @IgnoreUpTo(Build.VERSION_CODES.R) 164 // NetworkAgent is updated as part of the connectivity module, and running NetworkAgent tests in MTS 165 // for modules other than Connectivity does not provide much value. Only run them in connectivity 166 // module MTS, so the tests only need to cover the case of an updated NetworkAgent. 167 @ConnectivityModuleTest 168 class NetworkAgentTest { 169 private val LOCAL_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1") 170 private val REMOTE_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.2") 171 172 private val mCM = realContext.getSystemService(ConnectivityManager::class.java)!! 173 private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread") 174 private val mFakeConnectivityService = FakeConnectivityService() 175 private val agentsToCleanUp = mutableListOf<NetworkAgent>() 176 private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>() 177 private var qosTestSocket: Socket? = null 178 179 @Before setUpnull180 fun setUp() { 181 instrumentation.getUiAutomation().adoptShellPermissionIdentity() 182 mHandlerThread.start() 183 } 184 185 @After tearDownnull186 fun tearDown() { 187 agentsToCleanUp.forEach { it.unregister() } 188 callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) } 189 qosTestSocket?.close() 190 mHandlerThread.quitSafely() 191 instrumentation.getUiAutomation().dropShellPermissionIdentity() 192 } 193 194 /** 195 * A fake that helps simulating ConnectivityService talking to a harnessed agent. 196 * This fake only supports speaking to one harnessed agent at a time because it 197 * only keeps track of one async channel. 198 */ 199 private class FakeConnectivityService { 200 val mockRegistry = mock(INetworkAgentRegistry::class.java) 201 private var agentField: INetworkAgent? = null 202 private val registry = object : INetworkAgentRegistry.Stub(), <lambda>null203 INetworkAgentRegistry by mockRegistry { 204 // asBinder has implementations in both INetworkAgentRegistry.Stub and mockRegistry, so 205 // it needs to be disambiguated. Just fail the test as it should be unused here. 206 // asBinder is used when sending the registry in binder transactions, so not in this 207 // test (the test just uses in-process direct calls). If it were used across processes, 208 // using the Stub super.asBinder() implementation would allow sending the registry in 209 // binder transactions, while recording incoming calls on the other mockito-generated 210 // methods. 211 override fun asBinder() = fail("asBinder should be unused in this test") 212 } 213 214 val agent: INetworkAgent 215 get() = agentField ?: fail("No INetworkAgent") 216 connectnull217 fun connect(agent: INetworkAgent) { 218 this.agentField = agent 219 agent.onRegistered(registry) 220 } 221 disconnectnull222 fun disconnect() = agent.onDisconnected() 223 } 224 225 private fun requestNetwork(request: NetworkRequest, callback: TestableNetworkCallback) { 226 mCM.requestNetwork(request, callback) 227 callbacksToCleanUp.add(callback) 228 } 229 registerNetworkCallbacknull230 private fun registerNetworkCallback( 231 request: NetworkRequest, 232 callback: TestableNetworkCallback 233 ) { 234 mCM.registerNetworkCallback(request, callback) 235 callbacksToCleanUp.add(callback) 236 } 237 registerBestMatchingNetworkCallbacknull238 private fun registerBestMatchingNetworkCallback( 239 request: NetworkRequest, 240 callback: TestableNetworkCallback, 241 handler: Handler 242 ) { 243 mCM!!.registerBestMatchingNetworkCallback(request, callback, handler) 244 callbacksToCleanUp.add(callback) 245 } 246 makeTestNetworkRequestnull247 private fun makeTestNetworkRequest(specifier: String? = null): NetworkRequest { 248 return NetworkRequest.Builder() 249 .clearCapabilities() 250 .addTransportType(TRANSPORT_TEST) 251 .also { 252 if (specifier != null) { 253 it.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifier)) 254 } 255 } 256 .build() 257 } 258 makeTestNetworkCapabilitiesnull259 private fun makeTestNetworkCapabilities( 260 specifier: String? = null, 261 transports: IntArray = intArrayOf() 262 ) = NetworkCapabilities().apply { 263 addTransportType(TRANSPORT_TEST) 264 removeCapability(NET_CAPABILITY_TRUSTED) 265 removeCapability(NET_CAPABILITY_INTERNET) 266 addCapability(NET_CAPABILITY_NOT_SUSPENDED) 267 addCapability(NET_CAPABILITY_NOT_ROAMING) 268 addCapability(NET_CAPABILITY_NOT_VPN) 269 if (SdkLevel.isAtLeastS()) { 270 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 271 } 272 if (null != specifier) { 273 setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifier)) 274 } 275 for (t in transports) { addTransportType(t) } 276 // Most transports are not allowed on test networks unless the network is marked restricted. 277 // This test does not need 278 if (transports.size > 0) removeCapability(NET_CAPABILITY_NOT_RESTRICTED) 279 } 280 createNetworkAgentnull281 private fun createNetworkAgent( 282 context: Context = realContext, 283 specifier: String? = null, 284 initialNc: NetworkCapabilities? = null, 285 initialLp: LinkProperties? = null, 286 initialConfig: NetworkAgentConfig? = null 287 ): TestableNetworkAgent { 288 val nc = initialNc ?: makeTestNetworkCapabilities(specifier) 289 val lp = initialLp ?: LinkProperties().apply { 290 addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32)) 291 addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null)) 292 } 293 val config = initialConfig ?: NetworkAgentConfig.Builder().build() 294 return TestableNetworkAgent(context, mHandlerThread.looper, nc, lp, config).also { 295 agentsToCleanUp.add(it) 296 } 297 } 298 createConnectedNetworkAgentnull299 private fun createConnectedNetworkAgent( 300 context: Context = realContext, 301 specifier: String? = UUID.randomUUID().toString(), 302 initialConfig: NetworkAgentConfig? = null, 303 expectedInitSignalStrengthThresholds: IntArray? = intArrayOf(), 304 transports: IntArray = intArrayOf() 305 ): Pair<TestableNetworkAgent, TestableNetworkCallback> { 306 val callback = TestableNetworkCallback() 307 // Ensure this NetworkAgent is never unneeded by filing a request with its specifier. 308 requestNetwork(makeTestNetworkRequest(specifier = specifier), callback) 309 val nc = makeTestNetworkCapabilities(specifier, transports) 310 val agent = createNetworkAgent(context, initialConfig = initialConfig, initialNc = nc) 311 agent.setTeardownDelayMillis(0) 312 // Connect the agent and verify initial status callbacks. 313 agent.register() 314 agent.markConnected() 315 agent.expectCallback<OnNetworkCreated>() 316 agent.expectSignalStrengths(expectedInitSignalStrengthThresholds) 317 agent.expectValidationBypassedStatus() 318 callback.expectAvailableThenValidatedCallbacks(agent.network!!) 319 return agent to callback 320 } 321 connectNetworknull322 private fun connectNetwork(vararg transports: Int): Pair<TestableNetworkAgent, Network> { 323 val (agent, callback) = createConnectedNetworkAgent(transports = transports) 324 val network = agent.network!! 325 // createConnectedNetworkAgent internally files a request; release it so that the network 326 // will be torn down if unneeded. 327 mCM.unregisterNetworkCallback(callback) 328 return agent to network 329 } 330 <lambda>null331 private fun createNetworkAgentWithFakeCS() = createNetworkAgent().also { 332 mFakeConnectivityService.connect(it.registerForTest(Network(FAKE_NET_ID))) 333 } 334 335 @Test testSetSubtypeNameAndExtraInfoByAgentConfignull336 fun testSetSubtypeNameAndExtraInfoByAgentConfig() { 337 val subtypeLTE = TelephonyManager.NETWORK_TYPE_LTE 338 val subtypeNameLTE = "LTE" 339 val legacyExtraInfo = "mylegacyExtraInfo" 340 val config = NetworkAgentConfig.Builder() 341 .setLegacySubType(subtypeLTE) 342 .setLegacySubTypeName(subtypeNameLTE) 343 .setLegacyExtraInfo(legacyExtraInfo).build() 344 val (agent, callback) = createConnectedNetworkAgent(initialConfig = config) 345 val networkInfo = mCM.getNetworkInfo(agent.network) 346 assertEquals(subtypeLTE, networkInfo.getSubtype()) 347 assertEquals(subtypeNameLTE, networkInfo.getSubtypeName()) 348 assertEquals(legacyExtraInfo, config.getLegacyExtraInfo()) 349 } 350 351 @Test testSetLegacySubtypeInNetworkAgentnull352 fun testSetLegacySubtypeInNetworkAgent() { 353 val subtypeLTE = TelephonyManager.NETWORK_TYPE_LTE 354 val subtypeUMTS = TelephonyManager.NETWORK_TYPE_UMTS 355 val subtypeNameLTE = "LTE" 356 val subtypeNameUMTS = "UMTS" 357 val config = NetworkAgentConfig.Builder() 358 .setLegacySubType(subtypeLTE) 359 .setLegacySubTypeName(subtypeNameLTE).build() 360 val (agent, callback) = createConnectedNetworkAgent(initialConfig = config) 361 agent.setLegacySubtype(subtypeUMTS, subtypeNameUMTS) 362 363 // There is no callback when networkInfo changes, 364 // so use the NetworkCapabilities callback to ensure 365 // that networkInfo is ready for verification. 366 val nc = NetworkCapabilities(agent.nc) 367 nc.addCapability(NET_CAPABILITY_NOT_METERED) 368 agent.sendNetworkCapabilities(nc) 369 callback.expectCapabilitiesThat(agent.network) { 370 it.hasCapability(NET_CAPABILITY_NOT_METERED) 371 } 372 val networkInfo = mCM.getNetworkInfo(agent.network) 373 assertEquals(subtypeUMTS, networkInfo.getSubtype()) 374 assertEquals(subtypeNameUMTS, networkInfo.getSubtypeName()) 375 } 376 377 @Test testConnectAndUnregisternull378 fun testConnectAndUnregister() { 379 val (agent, callback) = createConnectedNetworkAgent() 380 unregister(agent) 381 callback.expectCallback<Lost>(agent.network!!) 382 assertFailsWith<IllegalStateException>("Must not be able to register an agent twice") { 383 agent.register() 384 } 385 } 386 387 @Test testOnBandwidthUpdateRequestednull388 fun testOnBandwidthUpdateRequested() { 389 val (agent, _) = createConnectedNetworkAgent() 390 mCM.requestBandwidthUpdate(agent.network!!) 391 agent.expectCallback<OnBandwidthUpdateRequested>() 392 unregister(agent) 393 } 394 395 @Test testSignalStrengthThresholdsnull396 fun testSignalStrengthThresholds() { 397 val thresholds = intArrayOf(30, 50, 65) 398 val callbacks = thresholds.map { strength -> 399 val request = NetworkRequest.Builder() 400 .clearCapabilities() 401 .addTransportType(TRANSPORT_TEST) 402 .setSignalStrength(strength) 403 .build() 404 TestableNetworkCallback(DEFAULT_TIMEOUT_MS).also { 405 registerNetworkCallback(request, it) 406 } 407 } 408 createConnectedNetworkAgent(expectedInitSignalStrengthThresholds = thresholds).let { 409 (agent, callback) -> 410 // Send signal strength and check that the callbacks are called appropriately. 411 val nc = NetworkCapabilities(agent.nc) 412 nc.setSignalStrength(20) 413 agent.sendNetworkCapabilities(nc) 414 callbacks.forEach { it.assertNoCallback(NO_CALLBACK_TIMEOUT) } 415 416 nc.setSignalStrength(40) 417 agent.sendNetworkCapabilities(nc) 418 callbacks[0].expectAvailableCallbacks(agent.network!!) 419 callbacks[1].assertNoCallback(NO_CALLBACK_TIMEOUT) 420 callbacks[2].assertNoCallback(NO_CALLBACK_TIMEOUT) 421 422 nc.setSignalStrength(80) 423 agent.sendNetworkCapabilities(nc) 424 callbacks[0].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 80 } 425 callbacks[1].expectAvailableCallbacks(agent.network!!) 426 callbacks[2].expectAvailableCallbacks(agent.network!!) 427 428 nc.setSignalStrength(55) 429 agent.sendNetworkCapabilities(nc) 430 callbacks[0].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 } 431 callbacks[1].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 } 432 callbacks[2].expectCallback<Lost>(agent.network!!) 433 } 434 callbacks.forEach { 435 mCM.unregisterNetworkCallback(it) 436 } 437 } 438 439 @Test agentnull440 fun testSocketKeepalive(): Unit = createNetworkAgentWithFakeCS().let { agent -> 441 val packet = NattKeepalivePacketData( 442 LOCAL_IPV4_ADDRESS /* srcAddress */, 1234 /* srcPort */, 443 REMOTE_IPV4_ADDRESS /* dstAddress */, 4567 /* dstPort */, 444 ByteArray(100 /* size */)) 445 val slot = 4 446 val interval = 37 447 448 mFakeConnectivityService.agent.onAddNattKeepalivePacketFilter(slot, packet) 449 mFakeConnectivityService.agent.onStartNattSocketKeepalive(slot, interval, packet) 450 451 agent.expectCallback<OnAddKeepalivePacketFilter>().let { 452 assertEquals(it.slot, slot) 453 assertEquals(it.packet, packet) 454 } 455 agent.expectCallback<OnStartSocketKeepalive>().let { 456 assertEquals(it.slot, slot) 457 assertEquals(it.interval, interval) 458 assertEquals(it.packet, packet) 459 } 460 461 agent.assertNoCallback() 462 463 // Check that when the agent sends a keepalive event, ConnectivityService receives the 464 // expected message. 465 agent.sendSocketKeepaliveEvent(slot, SocketKeepalive.ERROR_UNSUPPORTED) 466 verify(mFakeConnectivityService.mockRegistry, timeout(DEFAULT_TIMEOUT_MS)) 467 .sendSocketKeepaliveEvent(slot, SocketKeepalive.ERROR_UNSUPPORTED) 468 469 mFakeConnectivityService.agent.onStopSocketKeepalive(slot) 470 mFakeConnectivityService.agent.onRemoveKeepalivePacketFilter(slot) 471 agent.expectCallback<OnStopSocketKeepalive>().let { 472 assertEquals(it.slot, slot) 473 } 474 agent.expectCallback<OnRemoveKeepalivePacketFilter>().let { 475 assertEquals(it.slot, slot) 476 } 477 } 478 479 @Test agentnull480 fun testSendUpdates(): Unit = createConnectedNetworkAgent().let { (agent, callback) -> 481 val ifaceName = "adhocIface" 482 val lp = LinkProperties(agent.lp) 483 lp.setInterfaceName(ifaceName) 484 agent.sendLinkProperties(lp) 485 callback.expectLinkPropertiesThat(agent.network!!) { 486 it.getInterfaceName() == ifaceName 487 } 488 val nc = NetworkCapabilities(agent.nc) 489 nc.addCapability(NET_CAPABILITY_NOT_METERED) 490 agent.sendNetworkCapabilities(nc) 491 callback.expectCapabilitiesThat(agent.network!!) { 492 it.hasCapability(NET_CAPABILITY_NOT_METERED) 493 } 494 } 495 ncWithAllowedUidsnull496 private fun ncWithAllowedUids(vararg uids: Int) = NetworkCapabilities.Builder() 497 .addTransportType(TRANSPORT_TEST) 498 .setAllowedUids(uids.toSet()).build() 499 500 @Test 501 fun testRejectedUpdates() { 502 val callback = TestableNetworkCallback(DEFAULT_TIMEOUT_MS) 503 // will be cleaned up in tearDown 504 registerNetworkCallback(makeTestNetworkRequest(), callback) 505 val agent = createNetworkAgent(initialNc = ncWithAllowedUids(200)) 506 agent.register() 507 agent.markConnected() 508 509 // Make sure the UIDs have been ignored. 510 callback.expectCallback<Available>(agent.network!!) 511 callback.expectCapabilitiesThat(agent.network!!) { 512 it.allowedUids.isEmpty() && !it.hasCapability(NET_CAPABILITY_VALIDATED) 513 } 514 callback.expectCallback<LinkPropertiesChanged>(agent.network!!) 515 callback.expectCallback<BlockedStatus>(agent.network!!) 516 callback.expectCapabilitiesThat(agent.network!!) { 517 it.allowedUids.isEmpty() && it.hasCapability(NET_CAPABILITY_VALIDATED) 518 } 519 callback.assertNoCallback(NO_CALLBACK_TIMEOUT) 520 521 // Make sure that the UIDs are also ignored upon update 522 agent.sendNetworkCapabilities(ncWithAllowedUids(200, 300)) 523 callback.assertNoCallback(NO_CALLBACK_TIMEOUT) 524 } 525 526 @Test testSendScorenull527 fun testSendScore() { 528 // This test will create two networks and check that the one with the stronger 529 // score wins out for a request that matches them both. 530 531 // File the interesting request 532 val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 533 requestNetwork(makeTestNetworkRequest(), callback) 534 535 // Connect the first Network, with an unused callback that kept the network up. 536 val (agent1, _) = createConnectedNetworkAgent() 537 callback.expectAvailableThenValidatedCallbacks(agent1.network!!) 538 // If using the int ranking, agent1 must be upgraded to a better score so that there is 539 // no ambiguity when agent2 connects that agent1 is still better. If using policy 540 // ranking, this is not necessary. 541 agent1.sendNetworkScore(NetworkScore.Builder().setLegacyInt(BETTER_NETWORK_SCORE) 542 .build()) 543 544 // Connect the second agent. 545 val (agent2, _) = createConnectedNetworkAgent() 546 // The callback should not see anything yet. With int ranking, agent1 was upgraded 547 // to a stronger score beforehand. With policy ranking, agent1 is preferred by 548 // virtue of already satisfying the request. 549 callback.assertNoCallback(NO_CALLBACK_TIMEOUT) 550 // Now downgrade the score and expect the callback now prefers agent2 551 agent1.sendNetworkScore(NetworkScore.Builder() 552 .setLegacyInt(WORSE_NETWORK_SCORE) 553 .setExiting(true) 554 .build()) 555 callback.expectCallback<Available>(agent2.network!!) 556 557 // tearDown() will unregister the requests and agents 558 } 559 hasAllTransportsnull560 private fun hasAllTransports(nc: NetworkCapabilities?, transports: IntArray) = 561 nc != null && transports.all { nc.hasTransport(it) } 562 563 @Test 564 @IgnoreUpTo(Build.VERSION_CODES.R) testSetUnderlyingNetworksAndVpnSpecifiernull565 fun testSetUnderlyingNetworksAndVpnSpecifier() { 566 val mySessionId = "MySession12345" 567 val request = NetworkRequest.Builder() 568 .addTransportType(TRANSPORT_TEST) 569 .addTransportType(TRANSPORT_VPN) 570 .removeCapability(NET_CAPABILITY_NOT_VPN) 571 .removeCapability(NET_CAPABILITY_TRUSTED) // TODO: add to VPN! 572 .build() 573 val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 574 registerNetworkCallback(request, callback) 575 576 val nc = NetworkCapabilities().apply { 577 addTransportType(TRANSPORT_TEST) 578 addTransportType(TRANSPORT_VPN) 579 removeCapability(NET_CAPABILITY_NOT_VPN) 580 setTransportInfo(VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE, mySessionId)) 581 if (SdkLevel.isAtLeastS()) { 582 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 583 } 584 } 585 val defaultNetwork = mCM.activeNetwork 586 assertNotNull(defaultNetwork) 587 val defaultNetworkCapabilities = mCM.getNetworkCapabilities(defaultNetwork) 588 val defaultNetworkTransports = defaultNetworkCapabilities.transportTypes 589 590 val agent = createNetworkAgent(initialNc = nc) 591 agent.register() 592 agent.markConnected() 593 callback.expectAvailableThenValidatedCallbacks(agent.network!!) 594 595 // Check that the default network's transport is propagated to the VPN. 596 var vpnNc = mCM.getNetworkCapabilities(agent.network!!) 597 assertNotNull(vpnNc) 598 assertEquals(VpnManager.TYPE_VPN_SERVICE, 599 (vpnNc.transportInfo as VpnTransportInfo).type) 600 assertEquals(mySessionId, (vpnNc.transportInfo as VpnTransportInfo).sessionId) 601 602 val testAndVpn = intArrayOf(TRANSPORT_TEST, TRANSPORT_VPN) 603 assertTrue(hasAllTransports(vpnNc, testAndVpn)) 604 assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_VPN)) 605 assertTrue(hasAllTransports(vpnNc, defaultNetworkTransports), 606 "VPN transports ${Arrays.toString(vpnNc.transportTypes)}" + 607 " lacking transports from ${Arrays.toString(defaultNetworkTransports)}") 608 609 // Check that when no underlying networks are announced the underlying transport disappears. 610 agent.setUnderlyingNetworks(listOf<Network>()) 611 callback.expectCapabilitiesThat(agent.network!!) { 612 it.transportTypes.size == 2 && hasAllTransports(it, testAndVpn) 613 } 614 615 // Put the underlying network back and check that the underlying transport reappears. 616 val expectedTransports = (defaultNetworkTransports.toSet() + TRANSPORT_TEST + TRANSPORT_VPN) 617 .toIntArray() 618 agent.setUnderlyingNetworks(null) 619 callback.expectCapabilitiesThat(agent.network!!) { 620 it.transportTypes.size == expectedTransports.size && 621 hasAllTransports(it, expectedTransports) 622 } 623 624 // Check that some underlying capabilities are propagated. 625 // This is not very accurate because the test does not control the capabilities of the 626 // underlying networks, and because not congested, not roaming, and not suspended are the 627 // default anyway. It's still useful as an extra check though. 628 vpnNc = mCM.getNetworkCapabilities(agent.network!!) 629 for (cap in listOf(NET_CAPABILITY_NOT_CONGESTED, 630 NET_CAPABILITY_NOT_ROAMING, 631 NET_CAPABILITY_NOT_SUSPENDED)) { 632 val capStr = valueToString(NetworkCapabilities::class.java, "NET_CAPABILITY_", cap) 633 if (defaultNetworkCapabilities.hasCapability(cap) && !vpnNc.hasCapability(cap)) { 634 fail("$capStr not propagated from underlying: $defaultNetworkCapabilities") 635 } 636 } 637 638 unregister(agent) 639 callback.expectCallback<Lost>(agent.network!!) 640 } 641 unregisternull642 private fun unregister(agent: TestableNetworkAgent) { 643 agent.unregister() 644 agent.eventuallyExpect<OnNetworkUnwanted>() 645 agent.eventuallyExpect<OnNetworkDestroyed>() 646 } 647 648 @Test 649 @IgnoreUpTo(Build.VERSION_CODES.R) testAgentStartsInConnectingnull650 fun testAgentStartsInConnecting() { 651 val mockContext = mock(Context::class.java) 652 val mockCm = mock(ConnectivityManager::class.java) 653 doReturn(mockCm).`when`(mockContext).getSystemService(Context.CONNECTIVITY_SERVICE) 654 val agent = createNetworkAgent(mockContext) 655 agent.register() 656 verify(mockCm).registerNetworkAgent(any(), 657 argThat<NetworkInfo> { it.detailedState == NetworkInfo.DetailedState.CONNECTING }, 658 any(LinkProperties::class.java), 659 any(NetworkCapabilities::class.java), 660 any(NetworkScore::class.java), 661 any(NetworkAgentConfig::class.java), 662 eq(NetworkProvider.ID_NONE)) 663 } 664 665 @Test testSetAcceptUnvalidatednull666 fun testSetAcceptUnvalidated() { 667 createNetworkAgentWithFakeCS().let { agent -> 668 mFakeConnectivityService.agent.onSaveAcceptUnvalidated(true) 669 agent.expectCallback<OnSaveAcceptUnvalidated>().let { 670 assertTrue(it.accept) 671 } 672 agent.assertNoCallback() 673 } 674 } 675 676 @Test testSetAcceptUnvalidatedPreventAutomaticReconnectnull677 fun testSetAcceptUnvalidatedPreventAutomaticReconnect() { 678 createNetworkAgentWithFakeCS().let { agent -> 679 mFakeConnectivityService.agent.onSaveAcceptUnvalidated(false) 680 mFakeConnectivityService.agent.onPreventAutomaticReconnect() 681 agent.expectCallback<OnSaveAcceptUnvalidated>().let { 682 assertFalse(it.accept) 683 } 684 agent.expectCallback<OnAutomaticReconnectDisabled>() 685 agent.assertNoCallback() 686 // When automatic reconnect is turned off, the network is torn down and 687 // ConnectivityService disconnects. As part of the disconnect, ConnectivityService will 688 // also send itself a message to unregister the NetworkAgent from its internal 689 // structure. 690 mFakeConnectivityService.disconnect() 691 agent.expectCallback<OnNetworkUnwanted>() 692 } 693 } 694 695 @Test testPreventAutomaticReconnectnull696 fun testPreventAutomaticReconnect() { 697 createNetworkAgentWithFakeCS().let { agent -> 698 mFakeConnectivityService.agent.onPreventAutomaticReconnect() 699 agent.expectCallback<OnAutomaticReconnectDisabled>() 700 agent.assertNoCallback() 701 mFakeConnectivityService.disconnect() 702 agent.expectCallback<OnNetworkUnwanted>() 703 } 704 } 705 706 @Test agentnull707 fun testValidationStatus() = createNetworkAgentWithFakeCS().let { agent -> 708 val uri = Uri.parse("http://www.google.com") 709 mFakeConnectivityService.agent.onValidationStatusChanged(VALID_NETWORK, 710 uri.toString()) 711 agent.expectCallback<OnValidationStatus>().let { 712 assertEquals(it.status, VALID_NETWORK) 713 assertEquals(it.uri, uri) 714 } 715 716 mFakeConnectivityService.agent.onValidationStatusChanged(INVALID_NETWORK, null) 717 agent.expectCallback<OnValidationStatus>().let { 718 assertEquals(it.status, INVALID_NETWORK) 719 assertNull(it.uri) 720 } 721 } 722 723 @Test testTemporarilyUnmeteredCapabilitynull724 fun testTemporarilyUnmeteredCapability() { 725 // This test will create a networks with/without NET_CAPABILITY_TEMPORARILY_NOT_METERED 726 // and check that the callback reflects the capability changes. 727 728 // Connect the network 729 val (agent, callback) = createConnectedNetworkAgent() 730 731 // Send TEMP_NOT_METERED and check that the callback is called appropriately. 732 val nc1 = NetworkCapabilities(agent.nc) 733 .addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 734 agent.sendNetworkCapabilities(nc1) 735 callback.expectCapabilitiesThat(agent.network!!) { 736 it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 737 } 738 739 // Remove TEMP_NOT_METERED and check that the callback is called appropriately. 740 val nc2 = NetworkCapabilities(agent.nc) 741 .removeCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 742 agent.sendNetworkCapabilities(nc2) 743 callback.expectCapabilitiesThat(agent.network!!) { 744 !it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 745 } 746 747 // tearDown() will unregister the requests and agents 748 } 749 750 @Test 751 @IgnoreUpTo(Build.VERSION_CODES.R) testSetLingerDurationnull752 fun testSetLingerDuration() { 753 // This test will create two networks and check that the one with the stronger 754 // score wins out for a request that matches them both. And the weaker agent will 755 // be disconnected after customized linger duration. 756 757 // Request the first Network, with a request that could moved to agentStronger in order to 758 // make agentWeaker linger later. 759 val specifierWeaker = UUID.randomUUID().toString() 760 val specifierStronger = UUID.randomUUID().toString() 761 val commonCallback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 762 requestNetwork(makeTestNetworkRequest(), commonCallback) 763 val agentWeaker = createNetworkAgent(specifier = specifierWeaker) 764 agentWeaker.register() 765 agentWeaker.markConnected() 766 commonCallback.expectAvailableThenValidatedCallbacks(agentWeaker.network!!) 767 // Downgrade agentWeaker to a worse score so that there is no ambiguity when 768 // agentStronger connects. 769 agentWeaker.sendNetworkScore(NetworkScore.Builder().setLegacyInt(WORSE_NETWORK_SCORE) 770 .setExiting(true).build()) 771 772 // Verify invalid linger duration cannot be set. 773 assertFailsWith<IllegalArgumentException> { 774 agentWeaker.setLingerDuration(Duration.ofMillis(-1)) 775 } 776 assertFailsWith<IllegalArgumentException> { agentWeaker.setLingerDuration(Duration.ZERO) } 777 assertFailsWith<IllegalArgumentException> { 778 agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MIN_VALUE.toLong())) 779 } 780 assertFailsWith<IllegalArgumentException> { 781 agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong() + 1)) 782 } 783 assertFailsWith<IllegalArgumentException> { 784 agentWeaker.setLingerDuration(Duration.ofMillis( 785 NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - 1)) 786 } 787 // Verify valid linger timer can be set, but it should not take effect since the network 788 // is still needed. 789 agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong())) 790 commonCallback.assertNoCallback(NO_CALLBACK_TIMEOUT) 791 // Set to the value we want to verify the functionality. 792 agentWeaker.setLingerDuration(Duration.ofMillis(NetworkAgent.MIN_LINGER_TIMER_MS.toLong())) 793 // Make a listener which can observe agentWeaker lost later. 794 val callbackWeaker = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 795 registerNetworkCallback(NetworkRequest.Builder() 796 .clearCapabilities() 797 .addTransportType(TRANSPORT_TEST) 798 .setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifierWeaker)) 799 .build(), callbackWeaker) 800 callbackWeaker.expectAvailableCallbacks(agentWeaker.network!!) 801 802 // Connect the agentStronger with a score better than agentWeaker. Verify the callback for 803 // agentWeaker sees the linger expiry while the callback for both sees the winner. 804 // Record linger start timestamp prior to send score to prevent possible race, the actual 805 // timestamp should be slightly late than this since the service handles update 806 // network score asynchronously. 807 val lingerStart = SystemClock.elapsedRealtime() 808 val agentStronger = createNetworkAgent(specifier = specifierStronger) 809 agentStronger.register() 810 agentStronger.markConnected() 811 commonCallback.expectAvailableCallbacks(agentStronger.network!!) 812 callbackWeaker.expectCallback<Losing>(agentWeaker.network!!) 813 val expectedRemainingLingerDuration = lingerStart + 814 NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - SystemClock.elapsedRealtime() 815 // If the available callback is too late. The remaining duration will be reduced. 816 assertTrue(expectedRemainingLingerDuration > 0, 817 "expected remaining linger duration is $expectedRemainingLingerDuration") 818 callbackWeaker.assertNoCallback(expectedRemainingLingerDuration) 819 callbackWeaker.expectCallback<Lost>(agentWeaker.network!!) 820 } 821 822 @Test 823 @IgnoreUpTo(Build.VERSION_CODES.R) testSetSubscriberIdnull824 fun testSetSubscriberId() { 825 val imsi = UUID.randomUUID().toString() 826 val config = NetworkAgentConfig.Builder().setSubscriberId(imsi).build() 827 828 val (agent, _) = createConnectedNetworkAgent(initialConfig = config) 829 val snapshots = runWithShellPermissionIdentity(ThrowingSupplier { 830 mCM!!.allNetworkStateSnapshots }, NETWORK_SETTINGS) 831 val testNetworkSnapshot = snapshots.findLast { it.network == agent.network } 832 assertEquals(imsi, testNetworkSnapshot!!.subscriberId) 833 } 834 835 @Test 836 @IgnoreUpTo(Build.VERSION_CODES.R) 837 // TODO: Refactor helper functions to util class and move this test case to 838 // {@link android.net.cts.ConnectivityManagerTest}. testRegisterBestMatchingNetworkCallbacknull839 fun testRegisterBestMatchingNetworkCallback() { 840 // Register best matching network callback with additional condition that will be 841 // exercised later. This assumes the test network agent has NOT_VCN_MANAGED in it and 842 // does not have NET_CAPABILITY_TEMPORARILY_NOT_METERED. 843 val bestMatchingCb = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 844 registerBestMatchingNetworkCallback(NetworkRequest.Builder() 845 .clearCapabilities() 846 .addTransportType(TRANSPORT_TEST) 847 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 848 .build(), bestMatchingCb, mHandlerThread.threadHandler) 849 850 val (agent1, _) = createConnectedNetworkAgent(specifier = "AGENT-1") 851 bestMatchingCb.expectAvailableThenValidatedCallbacks(agent1.network!!) 852 // Make agent1 worse so when agent2 shows up, the callback will see that. 853 agent1.sendNetworkScore(NetworkScore.Builder().setExiting(true).build()) 854 bestMatchingCb.assertNoCallback(NO_CALLBACK_TIMEOUT) 855 856 val (agent2, _) = createConnectedNetworkAgent(specifier = "AGENT-2") 857 bestMatchingCb.expectAvailableDoubleValidatedCallbacks(agent2.network!!) 858 859 // Change something on agent1 to trigger capabilities changed, since the callback 860 // only cares about the best network, verify it received nothing from agent1. 861 val ncAgent1 = agent1.nc 862 ncAgent1.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 863 agent1.sendNetworkCapabilities(ncAgent1) 864 bestMatchingCb.assertNoCallback(NO_CALLBACK_TIMEOUT) 865 866 // Make agent1 the best network again, verify the callback now tracks agent1. 867 agent1.sendNetworkScore(NetworkScore.Builder() 868 .setExiting(false).setTransportPrimary(true).build()) 869 bestMatchingCb.expectAvailableCallbacks(agent1.network!!) 870 871 // Make agent1 temporary vcn managed, which will not satisfying the request. 872 // Verify the callback switch from/to the other network accordingly. 873 ncAgent1.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 874 agent1.sendNetworkCapabilities(ncAgent1) 875 bestMatchingCb.expectAvailableCallbacks(agent2.network!!) 876 ncAgent1.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 877 agent1.sendNetworkCapabilities(ncAgent1) 878 bestMatchingCb.expectAvailableDoubleValidatedCallbacks(agent1.network!!) 879 880 // Verify the callback doesn't care about agent2 disconnect. 881 agent2.unregister() 882 agentsToCleanUp.remove(agent2) 883 bestMatchingCb.assertNoCallback() 884 agent1.unregister() 885 agentsToCleanUp.remove(agent1) 886 bestMatchingCb.expectCallback<Lost>(agent1.network!!) 887 888 // tearDown() will unregister the requests and agents 889 } 890 891 private class TestableQosCallback : QosCallback() { 892 val history = ArrayTrackRecord<CallbackEntry>().newReadHead() 893 894 sealed class CallbackEntry { 895 data class OnQosSessionAvailable(val sess: QosSession, val attr: QosSessionAttributes) 896 : CallbackEntry() 897 data class OnQosSessionLost(val sess: QosSession) 898 : CallbackEntry() 899 data class OnError(val ex: QosCallbackException) 900 : CallbackEntry() 901 } 902 onQosSessionAvailablenull903 override fun onQosSessionAvailable(sess: QosSession, attr: QosSessionAttributes) { 904 history.add(OnQosSessionAvailable(sess, attr)) 905 } 906 onQosSessionLostnull907 override fun onQosSessionLost(sess: QosSession) { 908 history.add(OnQosSessionLost(sess)) 909 } 910 onErrornull911 override fun onError(ex: QosCallbackException) { 912 history.add(OnError(ex)) 913 } 914 expectCallbacknull915 inline fun <reified T : CallbackEntry> expectCallback(): T { 916 val foundCallback = history.poll(DEFAULT_TIMEOUT_MS) 917 assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback") 918 return foundCallback 919 } 920 expectCallbacknull921 inline fun <reified T : CallbackEntry> expectCallback(valid: (T) -> Boolean) { 922 val foundCallback = history.poll(DEFAULT_TIMEOUT_MS) 923 assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback") 924 assertTrue(valid(foundCallback), "Unexpected callback : $foundCallback") 925 } 926 assertNoCallbacknull927 fun assertNoCallback() { 928 assertNull(history.poll(NO_CALLBACK_TIMEOUT), 929 "Callback received") 930 } 931 } 932 setupForQosCallbackTestingnull933 private fun setupForQosCallbackTesting(): Pair<TestableNetworkAgent, Socket> { 934 val request = NetworkRequest.Builder() 935 .clearCapabilities() 936 .addTransportType(TRANSPORT_TEST) 937 .build() 938 939 val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 940 requestNetwork(request, callback) 941 val (agent, _) = createConnectedNetworkAgent() 942 943 qosTestSocket = assertNotNull(agent.network?.socketFactory?.createSocket()).also { 944 it.bind(InetSocketAddress(InetAddress.getLoopbackAddress(), 0)) 945 } 946 return Pair(agent, qosTestSocket!!) 947 } 948 949 @AppModeFull(reason = "Instant apps don't have permission to bind sockets.") 950 @Test testQosCallbackRegisterWithUnregisternull951 fun testQosCallbackRegisterWithUnregister() { 952 val (agent, socket) = setupForQosCallbackTesting() 953 954 val qosCallback = TestableQosCallback() 955 var callbackId = -1 956 Executors.newSingleThreadExecutor().let { executor -> 957 try { 958 val info = QosSocketInfo(agent.network!!, socket) 959 mCM.registerQosCallback(info, executor, qosCallback) 960 callbackId = agent.expectCallback<OnRegisterQosCallback>().callbackId 961 962 assertFailsWith<QosCallbackRegistrationException>( 963 "The same callback cannot be " + 964 "registered more than once without first being unregistered") { 965 mCM.registerQosCallback(info, executor, qosCallback) 966 } 967 } finally { 968 socket.close() 969 mCM.unregisterQosCallback(qosCallback) 970 agent.expectCallback<OnUnregisterQosCallback> { it.callbackId == callbackId } 971 executor.shutdown() 972 } 973 } 974 } 975 976 @AppModeFull(reason = "Instant apps don't have permission to bind sockets.") 977 @Test testQosCallbackOnQosSessionnull978 fun testQosCallbackOnQosSession() { 979 val (agent, socket) = setupForQosCallbackTesting() 980 val qosCallback = TestableQosCallback() 981 Executors.newSingleThreadExecutor().let { executor -> 982 try { 983 val info = QosSocketInfo(agent.network!!, socket) 984 assertEquals(agent.network, info.getNetwork()) 985 mCM.registerQosCallback(info, executor, qosCallback) 986 val callbackId = agent.expectCallback<OnRegisterQosCallback>().callbackId 987 988 val uniqueSessionId = 4294967397 989 val sessId = 101 990 991 val attributes = createEpsAttributes(5) 992 assertEquals(attributes.qosIdentifier, 5) 993 agent.sendQosSessionAvailable(callbackId, sessId, attributes) 994 qosCallback.expectCallback<OnQosSessionAvailable> { 995 it.sess.sessionId == sessId && it.sess.uniqueId == uniqueSessionId && 996 it.sess.sessionType == QosSession.TYPE_EPS_BEARER 997 } 998 999 agent.sendQosSessionLost(callbackId, sessId, QosSession.TYPE_EPS_BEARER) 1000 qosCallback.expectCallback<OnQosSessionLost> { 1001 it.sess.sessionId == sessId && it.sess.uniqueId == uniqueSessionId && 1002 it.sess.sessionType == QosSession.TYPE_EPS_BEARER 1003 } 1004 1005 // Make sure that we don't get more qos callbacks 1006 mCM.unregisterQosCallback(qosCallback) 1007 agent.expectCallback<OnUnregisterQosCallback>() 1008 1009 agent.sendQosSessionLost(callbackId, sessId, QosSession.TYPE_EPS_BEARER) 1010 qosCallback.assertNoCallback() 1011 } finally { 1012 socket.close() 1013 1014 // safety precaution 1015 mCM.unregisterQosCallback(qosCallback) 1016 1017 executor.shutdown() 1018 } 1019 } 1020 } 1021 1022 @AppModeFull(reason = "Instant apps don't have permission to bind sockets.") 1023 @Test testQosCallbackOnErrornull1024 fun testQosCallbackOnError() { 1025 val (agent, socket) = setupForQosCallbackTesting() 1026 val qosCallback = TestableQosCallback() 1027 Executors.newSingleThreadExecutor().let { executor -> 1028 try { 1029 val info = QosSocketInfo(agent.network!!, socket) 1030 mCM.registerQosCallback(info, executor, qosCallback) 1031 val callbackId = agent.expectCallback<OnRegisterQosCallback>().callbackId 1032 1033 val sessId = 101 1034 val attributes = createEpsAttributes() 1035 1036 // Double check that this is wired up and ready to go 1037 agent.sendQosSessionAvailable(callbackId, sessId, attributes) 1038 qosCallback.expectCallback<OnQosSessionAvailable>() 1039 1040 // Check that onError is coming through correctly 1041 agent.sendQosCallbackError(callbackId, 1042 QosCallbackException.EX_TYPE_FILTER_NOT_SUPPORTED) 1043 qosCallback.expectCallback<OnError> { 1044 it.ex.cause is UnsupportedOperationException 1045 } 1046 1047 // Ensure that when an error occurs the callback was also unregistered 1048 agent.sendQosSessionLost(callbackId, sessId, QosSession.TYPE_EPS_BEARER) 1049 qosCallback.assertNoCallback() 1050 } finally { 1051 socket.close() 1052 1053 // Make sure that the callback is fully unregistered 1054 mCM.unregisterQosCallback(qosCallback) 1055 1056 executor.shutdown() 1057 } 1058 } 1059 } 1060 1061 @AppModeFull(reason = "Instant apps don't have permission to bind sockets.") 1062 @Test testQosCallbackIdsAreMappedCorrectlynull1063 fun testQosCallbackIdsAreMappedCorrectly() { 1064 val (agent, socket) = setupForQosCallbackTesting() 1065 val qosCallback1 = TestableQosCallback() 1066 val qosCallback2 = TestableQosCallback() 1067 Executors.newSingleThreadExecutor().let { executor -> 1068 try { 1069 val info = QosSocketInfo(agent.network!!, socket) 1070 mCM.registerQosCallback(info, executor, qosCallback1) 1071 val callbackId1 = agent.expectCallback<OnRegisterQosCallback>().callbackId 1072 1073 mCM.registerQosCallback(info, executor, qosCallback2) 1074 val callbackId2 = agent.expectCallback<OnRegisterQosCallback>().callbackId 1075 1076 val sessId1 = 101 1077 val attributes1 = createEpsAttributes(1) 1078 1079 // Check #1 1080 agent.sendQosSessionAvailable(callbackId1, sessId1, attributes1) 1081 qosCallback1.expectCallback<OnQosSessionAvailable>() 1082 qosCallback2.assertNoCallback() 1083 1084 // Check #2 1085 val sessId2 = 102 1086 val attributes2 = createEpsAttributes(2) 1087 agent.sendQosSessionAvailable(callbackId2, sessId2, attributes2) 1088 qosCallback1.assertNoCallback() 1089 qosCallback2.expectCallback<OnQosSessionAvailable> { sessId2 == it.sess.sessionId } 1090 } finally { 1091 socket.close() 1092 1093 // Make sure that the callback is fully unregistered 1094 mCM.unregisterQosCallback(qosCallback1) 1095 mCM.unregisterQosCallback(qosCallback2) 1096 1097 executor.shutdown() 1098 } 1099 } 1100 } 1101 1102 @AppModeFull(reason = "Instant apps don't have permission to bind sockets.") 1103 @Test testQosCallbackWhenNetworkReleasednull1104 fun testQosCallbackWhenNetworkReleased() { 1105 val (agent, socket) = setupForQosCallbackTesting() 1106 Executors.newSingleThreadExecutor().let { executor -> 1107 try { 1108 val qosCallback1 = TestableQosCallback() 1109 val qosCallback2 = TestableQosCallback() 1110 try { 1111 val info = QosSocketInfo(agent.network!!, socket) 1112 mCM.registerQosCallback(info, executor, qosCallback1) 1113 mCM.registerQosCallback(info, executor, qosCallback2) 1114 agent.unregister() 1115 1116 qosCallback1.expectCallback<OnError> { 1117 it.ex.cause is NetworkReleasedException 1118 } 1119 1120 qosCallback2.expectCallback<OnError> { 1121 it.ex.cause is NetworkReleasedException 1122 } 1123 } finally { 1124 socket.close() 1125 mCM.unregisterQosCallback(qosCallback1) 1126 mCM.unregisterQosCallback(qosCallback2) 1127 } 1128 } finally { 1129 socket.close() 1130 executor.shutdown() 1131 } 1132 } 1133 } 1134 createEpsAttributesnull1135 private fun createEpsAttributes(qci: Int = 1): EpsBearerQosSessionAttributes { 1136 val remoteAddresses = ArrayList<InetSocketAddress>() 1137 remoteAddresses.add(InetSocketAddress("2001:db8::123", 80)) 1138 return EpsBearerQosSessionAttributes( 1139 qci, 2, 3, 4, 5, 1140 remoteAddresses 1141 ) 1142 } 1143 1144 @AppModeFull(reason = "Instant apps don't have permission to bind sockets.") 1145 @Test testUnregisterAfterReplacementnull1146 fun testUnregisterAfterReplacement() { 1147 // Keeps an eye on all test networks. 1148 val matchAllCallback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 1149 registerNetworkCallback(makeTestNetworkRequest(), matchAllCallback) 1150 1151 // File a request that matches and keeps up the best-scoring test network. 1152 val testCallback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 1153 requestNetwork(makeTestNetworkRequest(), testCallback) 1154 1155 // Connect the first network. This should satisfy the request. 1156 val (agent1, network1) = connectNetwork() 1157 matchAllCallback.expectAvailableThenValidatedCallbacks(network1) 1158 testCallback.expectAvailableThenValidatedCallbacks(network1) 1159 // Check that network1 exists by binding a socket to it and getting no exceptions. 1160 network1.bindSocket(DatagramSocket()) 1161 1162 // Connect a second agent. network1 is preferred because it was already registered, so 1163 // testCallback will not see any events. agent2 is be torn down because it has no requests. 1164 val (agent2, network2) = connectNetwork() 1165 matchAllCallback.expectAvailableThenValidatedCallbacks(network2) 1166 matchAllCallback.expectCallback<Lost>(network2) 1167 agent2.expectCallback<OnNetworkUnwanted>() 1168 agent2.expectCallback<OnNetworkDestroyed>() 1169 assertNull(mCM.getLinkProperties(network2)) 1170 1171 // Mark the first network as awaiting replacement. This should destroy the underlying 1172 // native network and send onNetworkDestroyed, but will not send any NetworkCallbacks, 1173 // because for callback and scoring purposes network1 is still connected. 1174 agent1.unregisterAfterReplacement(5_000 /* timeoutMillis */) 1175 agent1.expectCallback<OnNetworkDestroyed>() 1176 assertThrows(IOException::class.java) { network1.bindSocket(DatagramSocket()) } 1177 assertNotNull(mCM.getLinkProperties(network1)) 1178 1179 // Calling unregisterAfterReplacement more than once has no effect. 1180 // If it did, this test would fail because the 1ms timeout means that the network would be 1181 // torn down before the replacement arrives. 1182 agent1.unregisterAfterReplacement(1 /* timeoutMillis */) 1183 1184 // Connect a third network. Because network1 is awaiting replacement, network3 is preferred 1185 // as soon as it validates (until then, it is outscored by network1). 1186 // The fact that the first events seen by matchAllCallback is the connection of network3 1187 // implicitly ensures that no callbacks are sent since network1 was lost. 1188 val (agent3, network3) = connectNetwork() 1189 matchAllCallback.expectAvailableThenValidatedCallbacks(network3) 1190 testCallback.expectAvailableDoubleValidatedCallbacks(network3) 1191 1192 // As soon as the replacement arrives, network1 is disconnected. 1193 // Check that this happens before the replacement timeout (5 seconds) fires. 1194 matchAllCallback.expectCallback<Lost>(network1, 2_000 /* timeoutMs */) 1195 agent1.expectCallback<OnNetworkUnwanted>() 1196 1197 // Test lingering: 1198 // - Connect a higher-scoring network and check that network3 starts lingering. 1199 // - Mark network3 awaiting replacement. 1200 // - Check that network3 is torn down immediately without waiting for the linger timer or 1201 // the replacement timer to fire. This is a regular teardown, so it results in 1202 // onNetworkUnwanted before onNetworkDestroyed. 1203 val (agent4, agent4callback) = createConnectedNetworkAgent() 1204 val network4 = agent4.network!! 1205 matchAllCallback.expectAvailableThenValidatedCallbacks(network4) 1206 agent4.sendNetworkScore(NetworkScore.Builder().setTransportPrimary(true).build()) 1207 matchAllCallback.expectCallback<Losing>(network3) 1208 testCallback.expectAvailableCallbacks(network4, validated = true) 1209 mCM.unregisterNetworkCallback(agent4callback) 1210 agent3.unregisterAfterReplacement(5_000) 1211 agent3.expectCallback<OnNetworkUnwanted>() 1212 matchAllCallback.expectCallback<Lost>(network3, 1000L) 1213 agent3.expectCallback<OnNetworkDestroyed>() 1214 1215 // Now mark network4 awaiting replacement with a low timeout, and check that if no 1216 // replacement arrives, it is torn down. 1217 agent4.unregisterAfterReplacement(100 /* timeoutMillis */) 1218 matchAllCallback.expectCallback<Lost>(network4, 1000L /* timeoutMs */) 1219 testCallback.expectCallback<Lost>(network4, 1000L /* timeoutMs */) 1220 agent4.expectCallback<OnNetworkDestroyed>() 1221 agent4.expectCallback<OnNetworkUnwanted>() 1222 1223 // If a network that is awaiting replacement is unregistered, it disconnects immediately, 1224 // before the replacement timeout fires. 1225 val (agent5, network5) = connectNetwork() 1226 matchAllCallback.expectAvailableThenValidatedCallbacks(network5) 1227 testCallback.expectAvailableThenValidatedCallbacks(network5) 1228 agent5.unregisterAfterReplacement(5_000 /* timeoutMillis */) 1229 agent5.unregister() 1230 matchAllCallback.expectCallback<Lost>(network5, 1000L /* timeoutMs */) 1231 testCallback.expectCallback<Lost>(network5, 1000L /* timeoutMs */) 1232 agent5.expectCallback<OnNetworkDestroyed>() 1233 agent5.expectCallback<OnNetworkUnwanted>() 1234 1235 // If wifi is replaced within the timeout, the device does not switch to cellular. 1236 val (cellAgent, cellNetwork) = connectNetwork(TRANSPORT_CELLULAR) 1237 testCallback.expectAvailableThenValidatedCallbacks(cellNetwork) 1238 matchAllCallback.expectAvailableThenValidatedCallbacks(cellNetwork) 1239 1240 val (wifiAgent, wifiNetwork) = connectNetwork(TRANSPORT_WIFI) 1241 testCallback.expectAvailableCallbacks(wifiNetwork, validated = true) 1242 testCallback.expectCapabilitiesThat(wifiNetwork) { 1243 it.hasCapability(NET_CAPABILITY_VALIDATED) 1244 } 1245 matchAllCallback.expectAvailableCallbacks(wifiNetwork, validated = false) 1246 matchAllCallback.expectCallback<Losing>(cellNetwork) 1247 matchAllCallback.expectCapabilitiesThat(wifiNetwork) { 1248 it.hasCapability(NET_CAPABILITY_VALIDATED) 1249 } 1250 1251 wifiAgent.unregisterAfterReplacement(5_000 /* timeoutMillis */) 1252 wifiAgent.expectCallback<OnNetworkDestroyed>() 1253 1254 // Once the network is awaiting replacement, changing LinkProperties, NetworkCapabilities or 1255 // score, or calling reportNetworkConnectivity, have no effect. 1256 val wifiSpecifier = mCM.getNetworkCapabilities(wifiNetwork)!!.networkSpecifier 1257 assertNotNull(wifiSpecifier) 1258 assertTrue(wifiSpecifier is EthernetNetworkSpecifier) 1259 1260 val wifiNc = makeTestNetworkCapabilities(wifiSpecifier.interfaceName, 1261 intArrayOf(TRANSPORT_WIFI)) 1262 wifiAgent.sendNetworkCapabilities(wifiNc) 1263 val wifiLp = mCM.getLinkProperties(wifiNetwork)!! 1264 val newRoute = RouteInfo(IpPrefix("192.0.2.42/24")) 1265 assertFalse(wifiLp.getRoutes().contains(newRoute)) 1266 wifiLp.addRoute(newRoute) 1267 wifiAgent.sendLinkProperties(wifiLp) 1268 mCM.reportNetworkConnectivity(wifiNetwork, false) 1269 // The test implicitly checks that no callbacks are sent here, because the next events seen 1270 // by the callbacks are for the new network connecting. 1271 1272 val (newWifiAgent, newWifiNetwork) = connectNetwork(TRANSPORT_WIFI) 1273 testCallback.expectAvailableCallbacks(newWifiNetwork, validated = true) 1274 matchAllCallback.expectAvailableThenValidatedCallbacks(newWifiNetwork) 1275 matchAllCallback.expectCallback<Lost>(wifiNetwork) 1276 wifiAgent.expectCallback<OnNetworkUnwanted>() 1277 } 1278 1279 @Test testUnregisterAgentBeforeAgentFullyConnectednull1280 fun testUnregisterAgentBeforeAgentFullyConnected() { 1281 val specifier = UUID.randomUUID().toString() 1282 val callback = TestableNetworkCallback() 1283 val transports = intArrayOf(TRANSPORT_CELLULAR) 1284 // Ensure this NetworkAgent is never unneeded by filing a request with its specifier. 1285 requestNetwork(makeTestNetworkRequest(specifier = specifier), callback) 1286 val nc = makeTestNetworkCapabilities(specifier, transports) 1287 val agent = createNetworkAgent(realContext, initialNc = nc) 1288 // Connect the agent 1289 agent.register() 1290 // Mark agent connected then unregister agent immediately. Verify that both available and 1291 // lost callback should be sent still. 1292 agent.markConnected() 1293 agent.unregister() 1294 callback.expectCallback<Available>(agent.network!!) 1295 callback.eventuallyExpect<Lost> { it.network == agent.network } 1296 } 1297 } 1298