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.NEARBY_WIFI_DEVICES 19 import android.Manifest.permission.NETWORK_SETTINGS 20 import android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE 21 import android.app.Instrumentation 22 import android.content.Context 23 import android.content.pm.PackageManager 24 import android.content.pm.PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION 25 import android.net.ConnectivityManager 26 import android.net.EthernetNetworkSpecifier 27 import android.net.INetworkAgent 28 import android.net.INetworkAgentRegistry 29 import android.net.InetAddresses 30 import android.net.IpPrefix 31 import android.net.LinkAddress 32 import android.net.LinkProperties 33 import android.net.NattKeepalivePacketData 34 import android.net.Network 35 import android.net.NetworkAgent 36 import android.net.NetworkAgent.INVALID_NETWORK 37 import android.net.NetworkAgent.VALID_NETWORK 38 import android.net.NetworkAgentConfig 39 import android.net.NetworkCapabilities 40 import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET 41 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED 42 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED 43 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED 44 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING 45 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED 46 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED 47 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN 48 import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED 49 import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED 50 import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED 51 import android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH 52 import android.net.NetworkCapabilities.TRANSPORT_CELLULAR 53 import android.net.NetworkCapabilities.TRANSPORT_ETHERNET 54 import android.net.NetworkCapabilities.TRANSPORT_TEST 55 import android.net.NetworkCapabilities.TRANSPORT_VPN 56 import android.net.NetworkCapabilities.TRANSPORT_WIFI 57 import android.net.NetworkInfo 58 import android.net.NetworkProvider 59 import android.net.NetworkReleasedException 60 import android.net.NetworkRequest 61 import android.net.NetworkScore 62 import android.net.NetworkSpecifier 63 import android.net.QosCallback 64 import android.net.QosCallback.QosCallbackRegistrationException 65 import android.net.QosCallbackException 66 import android.net.QosSession 67 import android.net.QosSessionAttributes 68 import android.net.QosSocketInfo 69 import android.net.RouteInfo 70 import android.net.SocketKeepalive 71 import android.net.TelephonyNetworkSpecifier 72 import android.net.TestNetworkInterface 73 import android.net.TestNetworkManager 74 import android.net.TransportInfo 75 import android.net.Uri 76 import android.net.VpnManager 77 import android.net.VpnTransportInfo 78 import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnError 79 import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnQosSessionAvailable 80 import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnQosSessionLost 81 import android.net.wifi.WifiInfo 82 import android.os.Build 83 import android.os.Handler 84 import android.os.HandlerThread 85 import android.os.Looper 86 import android.os.Message 87 import android.os.Process 88 import android.os.SystemClock 89 import android.platform.test.annotations.AppModeFull 90 import android.system.Os 91 import android.system.OsConstants.AF_INET6 92 import android.system.OsConstants.IPPROTO_TCP 93 import android.system.OsConstants.IPPROTO_UDP 94 import android.system.OsConstants.SOCK_DGRAM 95 import android.telephony.SubscriptionManager 96 import android.telephony.TelephonyManager 97 import android.telephony.data.EpsBearerQosSessionAttributes 98 import android.util.ArraySet 99 import android.util.DebugUtils.valueToString 100 import androidx.test.InstrumentationRegistry 101 import com.android.compatibility.common.util.SystemUtil.runShellCommand 102 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity 103 import com.android.compatibility.common.util.ThrowingSupplier 104 import com.android.modules.utils.build.SdkLevel 105 import com.android.net.module.util.ArrayTrackRecord 106 import com.android.net.module.util.NetworkStackConstants.ETHER_MTU 107 import com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN 108 import com.android.net.module.util.NetworkStackConstants.IPV6_PROTOCOL_OFFSET 109 import com.android.net.module.util.NetworkStackConstants.UDP_HEADER_LEN 110 import com.android.testutils.CompatUtil 111 import com.android.testutils.ConnectivityModuleTest 112 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo 113 import com.android.testutils.DevSdkIgnoreRunner 114 import com.android.testutils.PollPacketReader 115 import com.android.testutils.RecorderCallback.CallbackEntry.Available 116 import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus 117 import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged 118 import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged 119 import com.android.testutils.RecorderCallback.CallbackEntry.Losing 120 import com.android.testutils.RecorderCallback.CallbackEntry.Lost 121 import com.android.testutils.TestableNetworkAgent 122 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnAddKeepalivePacketFilter 123 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnAutomaticReconnectDisabled 124 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnBandwidthUpdateRequested 125 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated 126 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkDestroyed 127 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkUnwanted 128 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnRegisterQosCallback 129 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnRemoveKeepalivePacketFilter 130 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnSaveAcceptUnvalidated 131 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnStartSocketKeepalive 132 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnStopSocketKeepalive 133 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnUnregisterQosCallback 134 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnValidationStatus 135 import com.android.testutils.TestableNetworkCallback 136 import com.android.testutils.assertThrows 137 import com.android.testutils.com.android.testutils.CarrierConfigRule 138 import com.android.testutils.runAsShell 139 import com.android.testutils.tryTest 140 import com.android.testutils.waitForIdle 141 import java.io.Closeable 142 import java.io.IOException 143 import java.net.DatagramSocket 144 import java.net.InetAddress 145 import java.net.InetSocketAddress 146 import java.net.Socket 147 import java.nio.ByteBuffer 148 import java.time.Duration 149 import java.util.Arrays 150 import java.util.UUID 151 import java.util.concurrent.Executors 152 import kotlin.collections.ArrayList 153 import kotlin.random.Random 154 import kotlin.test.assertEquals 155 import kotlin.test.assertFailsWith 156 import kotlin.test.assertFalse 157 import kotlin.test.assertNotNull 158 import kotlin.test.assertNull 159 import kotlin.test.assertTrue 160 import kotlin.test.fail 161 import org.junit.After 162 import org.junit.Assume.assumeTrue 163 import org.junit.Before 164 import org.junit.Rule 165 import org.junit.Test 166 import org.junit.runner.RunWith 167 import org.mockito.ArgumentMatchers.any 168 import org.mockito.ArgumentMatchers.anyInt 169 import org.mockito.ArgumentMatchers.argThat 170 import org.mockito.ArgumentMatchers.eq 171 import org.mockito.Mockito.doReturn 172 import org.mockito.Mockito.mock 173 import org.mockito.Mockito.timeout 174 import org.mockito.Mockito.verify 175 176 private const val TAG = "NetworkAgentTest" 177 178 // This test doesn't really have a constraint on how fast the methods should return. If it's 179 // going to fail, it will simply wait forever, so setting a high timeout lowers the flake ratio 180 // without affecting the run time of successful runs. Thus, set a very high timeout. 181 private const val DEFAULT_TIMEOUT_MS = 5000L 182 183 private const val QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER = 184 "queue_network_agent_events_in_system_server" 185 186 187 // When waiting for a NetworkCallback to determine there was no timeout, waiting is the 188 // only possible thing (the relevant handler is the one in the real ConnectivityService, 189 // and then there is the Binder call), so have a short timeout for this as it will be 190 // exhausted every time. 191 private const val NO_CALLBACK_TIMEOUT = 200L 192 private const val WORSE_NETWORK_SCORE = 65 193 private const val BETTER_NETWORK_SCORE = 75 194 private const val FAKE_NET_ID = 1098 195 private val instrumentation: Instrumentation 196 get() = InstrumentationRegistry.getInstrumentation() 197 private val realContext: Context 198 get() = InstrumentationRegistry.getContext() 199 private fun Message(what: Int, arg1: Int, arg2: Int, obj: Any?) = Message.obtain().also { 200 it.what = what 201 it.arg1 = arg1 202 it.arg2 = arg2 203 it.obj = obj 204 } 205 206 private val LINK_ADDRESS = LinkAddress("2001:db8::1/64") 207 private val REMOTE_ADDRESS = InetAddresses.parseNumericAddress("2001:db8::123") 208 private val PREFIX = IpPrefix("2001:db8::/64") 209 private val NEXTHOP = InetAddresses.parseNumericAddress("fe80::abcd") 210 211 @AppModeFull(reason = "Instant apps can't use NetworkAgent because it needs NETWORK_FACTORY'.") 212 // NetworkAgent is updated as part of the connectivity module, and running NetworkAgent tests in MTS 213 // for modules other than Connectivity does not provide much value. Only run them in connectivity 214 // module MTS, so the tests only need to cover the case of an updated NetworkAgent. 215 @ConnectivityModuleTest 216 @DevSdkIgnoreRunner.RestoreDefaultNetwork 217 // NetworkAgent is not updatable in R-, so this test does not need to be compatible with older 218 // versions. NetworkAgent was also based on AsyncChannel before S so cannot be tested the same way. 219 @IgnoreUpTo(Build.VERSION_CODES.R) 220 @RunWith(DevSdkIgnoreRunner::class) 221 class NetworkAgentTest { 222 @get:Rule 223 val carrierConfigRule = CarrierConfigRule() 224 225 private val LOCAL_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1") 226 private val REMOTE_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.2") 227 228 private val mCM = realContext.getSystemService(ConnectivityManager::class.java)!! 229 private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread") 230 private val mFakeConnectivityService = FakeConnectivityService() 231 private val agentsToCleanUp = mutableListOf<NetworkAgent>() 232 private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>() 233 private var qosTestSocket: Closeable? = null // either Socket or DatagramSocket 234 private val ifacesToCleanUp = mutableListOf<TestNetworkInterface>() 235 236 // Unless the queuing in system server feature is chickened out, native networks are created 237 // immediately. Historically they would only created as they'd connect, which would force 238 // the code to apply link properties multiple times and suffer errors early on. Creating 239 // them early required that ordering between the client and the system server is guaranteed 240 // (at least to some extent), which has been done by moving the event queue from the client 241 // to the system server. When that feature is not chickened out, create networks immediately. 242 private val SHOULD_CREATE_NETWORKS_IMMEDIATELY 243 get() = mCM.isConnectivityServiceFeatureEnabledForTesting( 244 QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER 245 ) 246 247 248 @Before setUpnull249 fun setUp() { 250 instrumentation.getUiAutomation().adoptShellPermissionIdentity() 251 if (SdkLevel.isAtLeastT()) { 252 instrumentation.getUiAutomation().grantRuntimePermission( 253 "android.net.cts", 254 NEARBY_WIFI_DEVICES 255 ) 256 } 257 mHandlerThread.start() 258 } 259 260 @After tearDownnull261 fun tearDown() { 262 agentsToCleanUp.forEach { it.unregister() } 263 callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) } 264 ifacesToCleanUp.forEach { it.fileDescriptor.close() } 265 qosTestSocket?.close() 266 mHandlerThread.quitSafely() 267 mHandlerThread.join() 268 instrumentation.getUiAutomation().dropShellPermissionIdentity() 269 } 270 271 /** 272 * A fake that helps simulating ConnectivityService talking to a harnessed agent. 273 * This fake only supports speaking to one harnessed agent at a time because it 274 * only keeps track of one async channel. 275 */ 276 private class FakeConnectivityService { 277 val mockRegistry = mock(INetworkAgentRegistry::class.java) 278 private var agentField: INetworkAgent? = null 279 val registry: INetworkAgentRegistry = object : INetworkAgentRegistry.Stub(), <lambda>null280 INetworkAgentRegistry by mockRegistry { 281 // asBinder has implementations in both INetworkAgentRegistry.Stub and mockRegistry, so 282 // it needs to be disambiguated. Just fail the test as it should be unused here. 283 // asBinder is used when sending the registry in binder transactions, so not in this 284 // test (the test just uses in-process direct calls). If it were used across processes, 285 // using the Stub super.asBinder() implementation would allow sending the registry in 286 // binder transactions, while recording incoming calls on the other mockito-generated 287 // methods. 288 override fun asBinder() = fail("asBinder should be unused in this test") 289 } 290 291 val agent: INetworkAgent 292 get() = agentField ?: fail("No INetworkAgent") 293 connectnull294 fun connect(agent: INetworkAgent) { 295 this.agentField = agent 296 agent.onRegistered() 297 } 298 disconnectnull299 fun disconnect() = agent.onDisconnected() 300 } 301 302 private fun requestNetwork(request: NetworkRequest, callback: TestableNetworkCallback) { 303 mCM.requestNetwork(request, callback) 304 callbacksToCleanUp.add(callback) 305 } 306 registerNetworkCallbacknull307 private fun registerNetworkCallback( 308 request: NetworkRequest, 309 callback: TestableNetworkCallback 310 ) { 311 mCM.registerNetworkCallback(request, callback) 312 callbacksToCleanUp.add(callback) 313 } 314 registerBestMatchingNetworkCallbacknull315 private fun registerBestMatchingNetworkCallback( 316 request: NetworkRequest, 317 callback: TestableNetworkCallback, 318 handler: Handler 319 ) { 320 mCM.registerBestMatchingNetworkCallback(request, callback, handler) 321 callbacksToCleanUp.add(callback) 322 } 323 asEthSpecifiernull324 private fun String?.asEthSpecifier(): NetworkSpecifier? = 325 if (null == this) null else CompatUtil.makeEthernetNetworkSpecifier(this) 326 private fun makeTestNetworkRequest(specifier: NetworkSpecifier? = null) = 327 NetworkRequest.Builder().run { 328 clearCapabilities() 329 addTransportType(TRANSPORT_TEST) 330 if (specifier != null) setNetworkSpecifier(specifier) 331 build() 332 } 333 makeTestNetworkRequestnull334 private fun makeTestNetworkRequest(specifier: String?) = 335 makeTestNetworkRequest(specifier.asEthSpecifier()) 336 337 private fun makeTestNetworkCapabilities( 338 specifier: String? = null, 339 transports: IntArray = intArrayOf() 340 ) = NetworkCapabilities().apply { 341 addTransportType(TRANSPORT_TEST) 342 removeCapability(NET_CAPABILITY_TRUSTED) 343 removeCapability(NET_CAPABILITY_INTERNET) 344 addCapability(NET_CAPABILITY_NOT_SUSPENDED) 345 addCapability(NET_CAPABILITY_NOT_ROAMING) 346 if (!transports.contains(TRANSPORT_VPN)) addCapability(NET_CAPABILITY_NOT_VPN) 347 if (SdkLevel.isAtLeastS()) { 348 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 349 } 350 if (null != specifier) { 351 setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifier)) 352 } 353 for (t in transports) { addTransportType(t) } 354 // Most transports are not allowed on test networks unless the network is marked restricted. 355 // This test does not need 356 if (transports.size > 0) removeCapability(NET_CAPABILITY_NOT_RESTRICTED) 357 } 358 makeTestLinkPropertiesnull359 private fun makeTestLinkProperties(ifName: String): LinkProperties { 360 return LinkProperties().apply { 361 interfaceName = ifName 362 addLinkAddress(LINK_ADDRESS) 363 addRoute(RouteInfo(PREFIX, null /* nextHop */, ifName)) 364 addRoute(RouteInfo(IpPrefix("::/0"), NEXTHOP, ifName)) 365 } 366 } 367 createNetworkAgentnull368 private fun createNetworkAgent( 369 context: Context = realContext, 370 specifier: String? = null, 371 initialNc: NetworkCapabilities? = null, 372 initialLp: LinkProperties? = null, 373 initialConfig: NetworkAgentConfig? = null 374 ): TestableNetworkAgent { 375 val nc = initialNc ?: makeTestNetworkCapabilities(specifier) 376 val lp = initialLp ?: LinkProperties().apply { 377 addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32)) 378 addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null)) 379 } 380 val config = initialConfig ?: NetworkAgentConfig.Builder().build() 381 return TestableNetworkAgent(context, mHandlerThread.looper, nc, lp, config).also { 382 agentsToCleanUp.add(it) 383 } 384 } 385 createConnectedNetworkAgentnull386 private fun createConnectedNetworkAgent( 387 context: Context = realContext, 388 lp: LinkProperties? = null, 389 specifier: String? = UUID.randomUUID().toString(), 390 initialConfig: NetworkAgentConfig? = null, 391 expectedInitSignalStrengthThresholds: IntArray = intArrayOf(), 392 transports: IntArray = intArrayOf() 393 ): Pair<TestableNetworkAgent, TestableNetworkCallback> { 394 val callback = TestableNetworkCallback() 395 // Ensure this NetworkAgent is never unneeded by filing a request with its specifier. 396 requestNetwork(makeTestNetworkRequest(specifier), callback) 397 val nc = makeTestNetworkCapabilities(specifier, transports) 398 val agent = createNetworkAgent( 399 context, 400 initialConfig = initialConfig, 401 initialLp = lp, 402 initialNc = nc 403 ) 404 // Connect the agent and verify initial status callbacks. 405 agent.register() 406 agent.setTeardownDelayMillis(0) 407 agent.markConnected() 408 agent.expectCallback<OnNetworkCreated>() 409 agent.expectPostConnectionCallbacks(expectedInitSignalStrengthThresholds) 410 callback.expectAvailableThenValidatedCallbacks(agent.network!!) 411 return agent to callback 412 } 413 connectNetworknull414 private fun connectNetwork(vararg transports: Int, lp: LinkProperties? = null): 415 Pair<TestableNetworkAgent, Network> { 416 val (agent, callback) = createConnectedNetworkAgent(transports = transports, lp = lp) 417 val network = agent.network!! 418 // createConnectedNetworkAgent internally files a request; release it so that the network 419 // will be torn down if unneeded. 420 mCM.unregisterNetworkCallback(callback) 421 return agent to network 422 } 423 <lambda>null424 private fun createNetworkAgentWithFakeCS() = createNetworkAgent().also { 425 val binder = it.registerForTest(Network(FAKE_NET_ID), mFakeConnectivityService.registry) 426 mFakeConnectivityService.connect(binder) 427 } 428 expectPostConnectionCallbacksnull429 private fun TestableNetworkAgent.expectPostConnectionCallbacks( 430 thresholds: IntArray = intArrayOf() 431 ) { 432 expectSignalStrengths(thresholds) 433 expectValidationBypassedStatus() 434 assertNoCallback() 435 } 436 createTunInterfacenull437 private fun createTunInterface(addrs: Collection<LinkAddress> = emptyList()): 438 TestNetworkInterface = realContext.getSystemService( 439 TestNetworkManager::class.java 440 )!!.createTunInterface(addrs).also { 441 ifacesToCleanUp.add(it) 442 } 443 assertLinkPropertiesEventuallynull444 fun assertLinkPropertiesEventually( 445 n: Network, 446 description: String, 447 condition: (LinkProperties?) -> Boolean 448 ): LinkProperties? { 449 val deadline = SystemClock.elapsedRealtime() + DEFAULT_TIMEOUT_MS 450 do { 451 val lp = mCM.getLinkProperties(n) 452 if (condition(lp)) return lp 453 SystemClock.sleep(10 /* ms */) 454 } while (SystemClock.elapsedRealtime() < deadline) 455 fail("Network $n LinkProperties did not $description after $DEFAULT_TIMEOUT_MS ms") 456 } 457 assertLinkPropertiesEventuallyNotNullnull458 fun assertLinkPropertiesEventuallyNotNull(n: Network) { 459 assertLinkPropertiesEventually(n, "become non-null") { it != null } 460 } 461 assertLinkPropertiesEventuallyNullnull462 fun assertLinkPropertiesEventuallyNull(n: Network) { 463 assertLinkPropertiesEventually(n, "become null") { it == null } 464 } 465 466 @Test testSetSubtypeNameAndExtraInfoByAgentConfignull467 fun testSetSubtypeNameAndExtraInfoByAgentConfig() { 468 val subtypeLTE = TelephonyManager.NETWORK_TYPE_LTE 469 val subtypeNameLTE = "LTE" 470 val legacyExtraInfo = "mylegacyExtraInfo" 471 val config = NetworkAgentConfig.Builder() 472 .setLegacySubType(subtypeLTE) 473 .setLegacySubTypeName(subtypeNameLTE) 474 .setLegacyExtraInfo(legacyExtraInfo).build() 475 val (agent, callback) = createConnectedNetworkAgent(initialConfig = config) 476 val networkInfo = mCM.getNetworkInfo(agent.network) 477 assertEquals(subtypeLTE, networkInfo?.getSubtype()) 478 assertEquals(subtypeNameLTE, networkInfo?.getSubtypeName()) 479 assertEquals(legacyExtraInfo, config.getLegacyExtraInfo()) 480 } 481 482 @Test testSetLegacySubtypeInNetworkAgentnull483 fun testSetLegacySubtypeInNetworkAgent() { 484 val subtypeLTE = TelephonyManager.NETWORK_TYPE_LTE 485 val subtypeUMTS = TelephonyManager.NETWORK_TYPE_UMTS 486 val subtypeNameLTE = "LTE" 487 val subtypeNameUMTS = "UMTS" 488 val config = NetworkAgentConfig.Builder() 489 .setLegacySubType(subtypeLTE) 490 .setLegacySubTypeName(subtypeNameLTE).build() 491 val (agent, callback) = createConnectedNetworkAgent(initialConfig = config) 492 agent.setLegacySubtype(subtypeUMTS, subtypeNameUMTS) 493 494 // There is no callback when networkInfo changes, 495 // so use the NetworkCapabilities callback to ensure 496 // that networkInfo is ready for verification. 497 val nc = NetworkCapabilities(agent.nc) 498 nc.addCapability(NET_CAPABILITY_NOT_METERED) 499 agent.sendNetworkCapabilities(nc) 500 callback.expectCaps(agent.network!!) { it.hasCapability(NET_CAPABILITY_NOT_METERED) } 501 val networkInfo = mCM.getNetworkInfo(agent.network!!)!! 502 assertEquals(subtypeUMTS, networkInfo.getSubtype()) 503 assertEquals(subtypeNameUMTS, networkInfo.getSubtypeName()) 504 } 505 506 @Test testConnectAndUnregisternull507 fun testConnectAndUnregister() { 508 val (agent, callback) = createConnectedNetworkAgent() 509 unregister(agent) 510 callback.expect<Lost>(agent.network!!) 511 assertFailsWith<IllegalStateException>("Must not be able to register an agent twice") { 512 agent.register() 513 } 514 } 515 516 @Test testOnBandwidthUpdateRequestednull517 fun testOnBandwidthUpdateRequested() { 518 val (agent, _) = createConnectedNetworkAgent() 519 mCM.requestBandwidthUpdate(agent.network!!) 520 agent.expectCallback<OnBandwidthUpdateRequested>() 521 unregister(agent) 522 } 523 524 @Test testSignalStrengthThresholdsnull525 fun testSignalStrengthThresholds() { 526 val thresholds = intArrayOf(30, 50, 65) 527 val callbacks = thresholds.map { strength -> 528 val request = NetworkRequest.Builder() 529 .clearCapabilities() 530 .addTransportType(TRANSPORT_TEST) 531 .setSignalStrength(strength) 532 .build() 533 TestableNetworkCallback(DEFAULT_TIMEOUT_MS).also { 534 registerNetworkCallback(request, it) 535 } 536 } 537 createConnectedNetworkAgent(expectedInitSignalStrengthThresholds = thresholds).let { 538 (agent, callback) -> 539 // Send signal strength and check that the callbacks are called appropriately. 540 val nc = NetworkCapabilities(agent.nc) 541 val net = agent.network!! 542 nc.setSignalStrength(20) 543 agent.sendNetworkCapabilities(nc) 544 callbacks.forEach { it.assertNoCallback(NO_CALLBACK_TIMEOUT) } 545 546 nc.setSignalStrength(40) 547 agent.sendNetworkCapabilities(nc) 548 callbacks[0].expectAvailableCallbacks(net) 549 callbacks[1].assertNoCallback(NO_CALLBACK_TIMEOUT) 550 callbacks[2].assertNoCallback(NO_CALLBACK_TIMEOUT) 551 552 nc.setSignalStrength(80) 553 agent.sendNetworkCapabilities(nc) 554 callbacks[0].expectCaps(net) { it.signalStrength == 80 } 555 callbacks[1].expectAvailableCallbacks(net) 556 callbacks[2].expectAvailableCallbacks(net) 557 558 nc.setSignalStrength(55) 559 agent.sendNetworkCapabilities(nc) 560 callbacks[0].expectCaps(net) { it.signalStrength == 55 } 561 callbacks[1].expectCaps(net) { it.signalStrength == 55 } 562 callbacks[2].expect<Lost>(net) 563 } 564 callbacks.forEach { 565 mCM.unregisterNetworkCallback(it) 566 } 567 } 568 569 @Test agentnull570 fun testSocketKeepalive(): Unit = createNetworkAgentWithFakeCS().let { agent -> 571 val packet = NattKeepalivePacketData( 572 LOCAL_IPV4_ADDRESS /* srcAddress */, 573 1234 /* srcPort */, 574 REMOTE_IPV4_ADDRESS /* dstAddress */, 575 4567 /* dstPort */, 576 ByteArray(100 /* size */) 577 ) 578 val slot = 4 579 val interval = 37 580 581 mFakeConnectivityService.agent.onAddNattKeepalivePacketFilter(slot, packet) 582 mFakeConnectivityService.agent.onStartNattSocketKeepalive(slot, interval, packet) 583 584 agent.expectCallback<OnAddKeepalivePacketFilter>().let { 585 assertEquals(it.slot, slot) 586 assertEquals(it.packet, packet) 587 } 588 agent.expectCallback<OnStartSocketKeepalive>().let { 589 assertEquals(it.slot, slot) 590 assertEquals(it.interval, interval) 591 assertEquals(it.packet, packet) 592 } 593 594 agent.assertNoCallback() 595 596 // Check that when the agent sends a keepalive event, ConnectivityService receives the 597 // expected message. 598 agent.sendSocketKeepaliveEvent(slot, SocketKeepalive.ERROR_UNSUPPORTED) 599 verify(mFakeConnectivityService.mockRegistry, timeout(DEFAULT_TIMEOUT_MS)) 600 .sendSocketKeepaliveEvent(slot, SocketKeepalive.ERROR_UNSUPPORTED) 601 602 mFakeConnectivityService.agent.onStopSocketKeepalive(slot) 603 mFakeConnectivityService.agent.onRemoveKeepalivePacketFilter(slot) 604 agent.expectCallback<OnStopSocketKeepalive>().let { 605 assertEquals(it.slot, slot) 606 } 607 agent.expectCallback<OnRemoveKeepalivePacketFilter>().let { 608 assertEquals(it.slot, slot) 609 } 610 } 611 612 @Test agentnull613 fun testSendUpdates(): Unit = createConnectedNetworkAgent().let { (agent, callback) -> 614 val ifaceName = "adhocIface" 615 val lp = LinkProperties(agent.lp) 616 lp.setInterfaceName(ifaceName) 617 agent.sendLinkProperties(lp) 618 callback.expect<LinkPropertiesChanged>(agent.network!!) { it.lp.interfaceName == ifaceName } 619 val nc = NetworkCapabilities(agent.nc) 620 nc.addCapability(NET_CAPABILITY_NOT_METERED) 621 agent.sendNetworkCapabilities(nc) 622 callback.expectCaps(agent.network!!) { it.hasCapability(NET_CAPABILITY_NOT_METERED) } 623 } 624 ncWithAllowedUidsnull625 private fun ncWithAllowedUids(vararg uids: Int) = NetworkCapabilities.Builder() 626 .addTransportType(TRANSPORT_TEST) 627 .setAllowedUids(uids.toSet()).build() 628 629 /** 630 * Get the single element from this ArraySet, or fail() if doesn't contain exactly 1 element. 631 */ 632 fun <T> ArraySet<T>.getSingleElement(): T { 633 if (size != 1) fail("Expected exactly one element, contained $size") 634 return iterator().next() 635 } 636 doTestAllowedUidsnull637 private fun doTestAllowedUids( 638 transports: IntArray, 639 uid: Int, 640 expectUidsPresent: Boolean, 641 specifier: NetworkSpecifier?, 642 transportInfo: TransportInfo? 643 ) { 644 val callback = TestableNetworkCallback(DEFAULT_TIMEOUT_MS) 645 val agent = createNetworkAgent(initialNc = NetworkCapabilities.Builder().run { 646 addTransportType(TRANSPORT_TEST) 647 transports.forEach { addTransportType(it) } 648 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 649 addCapability(NET_CAPABILITY_NOT_SUSPENDED) 650 removeCapability(NET_CAPABILITY_NOT_RESTRICTED) 651 setNetworkSpecifier(specifier) 652 setTransportInfo(transportInfo) 653 setAllowedUids(setOf(uid)) 654 setOwnerUid(Process.myUid()) 655 setAdministratorUids(intArrayOf(Process.myUid())) 656 build() 657 }) 658 runWithShellPermissionIdentity { 659 agent.register() 660 } 661 agent.markConnected() 662 663 registerNetworkCallback(makeTestNetworkRequest(specifier), callback) 664 callback.expect<Available>(agent.network!!) 665 callback.expect<CapabilitiesChanged>(agent.network!!) { 666 if (expectUidsPresent) { 667 it.caps.allowedUidsNoCopy.getSingleElement() == uid 668 } else { 669 it.caps.allowedUidsNoCopy.isEmpty() 670 } 671 } 672 agent.unregister() 673 callback.eventuallyExpect<Lost> { it.network == agent.network } 674 // callback will be unregistered in tearDown() 675 } 676 doTestAllowedUidsnull677 private fun doTestAllowedUids( 678 transport: Int, 679 uid: Int, 680 expectUidsPresent: Boolean 681 ) { 682 doTestAllowedUids( 683 intArrayOf(transport), 684 uid, 685 expectUidsPresent, 686 specifier = null, 687 transportInfo = null 688 ) 689 } 690 doTestAllowedUidsWithSubIdnull691 private fun doTestAllowedUidsWithSubId( 692 subId: Int, 693 transport: Int, 694 uid: Int, 695 expectUidsPresent: Boolean 696 ) { 697 doTestAllowedUidsWithSubId(subId, intArrayOf(transport), uid, expectUidsPresent) 698 } 699 doTestAllowedUidsWithSubIdnull700 private fun doTestAllowedUidsWithSubId( 701 subId: Int, 702 transports: IntArray, 703 uid: Int, 704 expectUidsPresent: Boolean 705 ) { 706 val specifier = when { 707 transports.size != 1 -> null 708 TRANSPORT_ETHERNET in transports -> EthernetNetworkSpecifier("testInterface") 709 TRANSPORT_CELLULAR in transports -> TelephonyNetworkSpecifier(subId) 710 else -> null 711 } 712 val transportInfo = if (TRANSPORT_WIFI in transports && SdkLevel.isAtLeastV()) { 713 // setSubscriptionId only exists in V+ 714 WifiInfo.Builder().setSubscriptionId(subId).build() 715 } else { 716 null 717 } 718 doTestAllowedUids(transports, uid, expectUidsPresent, specifier, transportInfo) 719 } 720 Stringnull721 private fun String.execute() = runShellCommand(this).trim() 722 723 @Test 724 @IgnoreUpTo(Build.VERSION_CODES.S) 725 fun testAllowedUids() { 726 doTestAllowedUids(TRANSPORT_CELLULAR, Process.myUid(), expectUidsPresent = false) 727 doTestAllowedUids(TRANSPORT_WIFI, Process.myUid(), expectUidsPresent = false) 728 doTestAllowedUids(TRANSPORT_BLUETOOTH, Process.myUid(), expectUidsPresent = false) 729 730 // TODO(b/315136340): Allow ownerUid to see allowedUids and add cases that expect uids 731 // present 732 } 733 734 @Test 735 @IgnoreUpTo(Build.VERSION_CODES.S) testAllowedUids_WithCarrierServicePackagenull736 fun testAllowedUids_WithCarrierServicePackage() { 737 assumeTrue(realContext.packageManager.hasSystemFeature(FEATURE_TELEPHONY_SUBSCRIPTION)) 738 739 // Use a different package than this one to make sure that a package that doesn't hold 740 // carrier service permission can be set as an allowed UID. 741 val servicePackage = "android.net.cts.carrierservicepackage" 742 val uid = try { 743 realContext.packageManager.getApplicationInfo(servicePackage, 0).uid 744 } catch (e: PackageManager.NameNotFoundException) { 745 fail( 746 "$servicePackage could not be installed, please check the SuiteApkInstaller" + 747 " installed CtsCarrierServicePackage.apk", 748 e 749 ) 750 } 751 752 val tm = realContext.getSystemService(TelephonyManager::class.java)!! 753 val defaultSubId = SubscriptionManager.getDefaultSubscriptionId() 754 assertTrue( 755 defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID, 756 "getDefaultSubscriptionId returns INVALID_SUBSCRIPTION_ID" 757 ) 758 tryTest { 759 // This process is not the carrier service UID, so allowedUids should be ignored in all 760 // the following cases. 761 doTestAllowedUidsWithSubId( 762 defaultSubId, 763 TRANSPORT_CELLULAR, 764 uid, 765 expectUidsPresent = false 766 ) 767 doTestAllowedUidsWithSubId( 768 defaultSubId, 769 TRANSPORT_WIFI, 770 uid, 771 expectUidsPresent = false 772 ) 773 doTestAllowedUidsWithSubId( 774 defaultSubId, 775 TRANSPORT_BLUETOOTH, 776 uid, 777 expectUidsPresent = false 778 ) 779 780 // The tools to set the carrier service package override do not exist before U, 781 // so there is no way to test the rest of this test on < U. 782 if (!SdkLevel.isAtLeastU()) return@tryTest 783 // Acquiring carrier privilege is necessary to override the carrier service package. 784 val defaultSlotIndex = SubscriptionManager.getSlotIndex(defaultSubId) 785 carrierConfigRule.acquireCarrierPrivilege(defaultSubId) 786 carrierConfigRule.setCarrierServicePackageOverride(defaultSubId, servicePackage) 787 val actualServicePackage: String? = runAsShell(READ_PRIVILEGED_PHONE_STATE) { 788 tm.getCarrierServicePackageNameForLogicalSlot(defaultSlotIndex) 789 } 790 assertEquals(servicePackage, actualServicePackage) 791 792 // Wait for CarrierServiceAuthenticator to have seen the update of the service package 793 val timeout = SystemClock.elapsedRealtime() + DEFAULT_TIMEOUT_MS 794 while (true) { 795 if (SystemClock.elapsedRealtime() > timeout) { 796 fail( 797 "Couldn't make $servicePackage the service package for $defaultSubId: " + 798 "dumpsys connectivity".execute().split("\n") 799 .filter { it.contains("Logical slot = $defaultSlotIndex.*") } 800 ) 801 } 802 if ("dumpsys connectivity" 803 .execute() 804 .split("\n") 805 .filter { it.contains("Logical slot = $defaultSlotIndex : uid = $uid") } 806 .isNotEmpty()) { 807 // Found the configuration 808 break 809 } 810 Thread.sleep(500) 811 } 812 813 // Cell and WiFi are allowed to set UIDs, but not Bluetooth or agents with multiple 814 // transports. 815 // TODO(b/315136340): Allow ownerUid to see allowedUids and enable below test case 816 // doTestAllowedUids(defaultSubId, TRANSPORT_CELLULAR, uid, expectUidsPresent = true) 817 if (SdkLevel.isAtLeastV()) { 818 // Cannot be tested before V because WifiInfo.Builder#setSubscriptionId doesn't 819 // exist 820 // TODO(b/315136340): Allow ownerUid to see allowedUids and enable below test case 821 // doTestAllowedUids(defaultSubId, TRANSPORT_WIFI, uid, expectUidsPresent = true) 822 } 823 doTestAllowedUidsWithSubId( 824 defaultSubId, 825 TRANSPORT_BLUETOOTH, 826 uid, 827 expectUidsPresent = false 828 ) 829 doTestAllowedUidsWithSubId( 830 defaultSubId, 831 intArrayOf(TRANSPORT_CELLULAR, TRANSPORT_WIFI), 832 uid, 833 expectUidsPresent = false 834 ) 835 } 836 } 837 838 @Test testRejectedUpdatesnull839 fun testRejectedUpdates() { 840 val callback = TestableNetworkCallback(DEFAULT_TIMEOUT_MS) 841 // will be cleaned up in tearDown 842 registerNetworkCallback(makeTestNetworkRequest(), callback) 843 val agent = createNetworkAgent(initialNc = ncWithAllowedUids(200)) 844 agent.register() 845 agent.markConnected() 846 847 // Make sure the UIDs have been ignored. 848 callback.expect<Available>(agent.network!!) 849 callback.expectCaps(agent.network!!) { 850 it.allowedUids.isEmpty() && !it.hasCapability(NET_CAPABILITY_VALIDATED) 851 } 852 callback.expect<LinkPropertiesChanged>(agent.network!!) 853 callback.expect<BlockedStatus>(agent.network!!) 854 callback.expectCaps(agent.network!!) { 855 it.allowedUids.isEmpty() && it.hasCapability(NET_CAPABILITY_VALIDATED) 856 } 857 callback.assertNoCallback(NO_CALLBACK_TIMEOUT) 858 859 // Make sure that the UIDs are also ignored upon update 860 agent.sendNetworkCapabilities(ncWithAllowedUids(200, 300)) 861 callback.assertNoCallback(NO_CALLBACK_TIMEOUT) 862 } 863 864 @Test testSendScorenull865 fun testSendScore() { 866 // This test will create two networks and check that the one with the stronger 867 // score wins out for a request that matches them both. 868 869 // File the interesting request 870 val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 871 requestNetwork(makeTestNetworkRequest(), callback) 872 873 // Connect the first Network, with an unused callback that kept the network up. 874 val (agent1, _) = createConnectedNetworkAgent() 875 callback.expectAvailableThenValidatedCallbacks(agent1.network!!) 876 // If using the int ranking, agent1 must be upgraded to a better score so that there is 877 // no ambiguity when agent2 connects that agent1 is still better. If using policy 878 // ranking, this is not necessary. 879 agent1.sendNetworkScore( 880 NetworkScore.Builder().setLegacyInt(BETTER_NETWORK_SCORE) 881 .build() 882 ) 883 884 // Connect the second agent. 885 val (agent2, _) = createConnectedNetworkAgent() 886 // The callback should not see anything yet. With int ranking, agent1 was upgraded 887 // to a stronger score beforehand. With policy ranking, agent1 is preferred by 888 // virtue of already satisfying the request. 889 callback.assertNoCallback(NO_CALLBACK_TIMEOUT) 890 // Now downgrade the score and expect the callback now prefers agent2 891 agent1.sendNetworkScore( 892 NetworkScore.Builder() 893 .setLegacyInt(WORSE_NETWORK_SCORE) 894 .setExiting(true) 895 .build() 896 ) 897 callback.expect<Available>(agent2.network!!) 898 899 // tearDown() will unregister the requests and agents 900 } 901 hasAllTransportsnull902 private fun NetworkCapabilities?.hasAllTransports(transports: IntArray) = 903 this != null && transports.all { hasTransport(it) } 904 905 @Test 906 @IgnoreUpTo(Build.VERSION_CODES.R) testSetUnderlyingNetworksAndVpnSpecifiernull907 fun testSetUnderlyingNetworksAndVpnSpecifier() { 908 val mySessionId = "MySession12345" 909 val request = NetworkRequest.Builder() 910 .addTransportType(TRANSPORT_TEST) 911 .addTransportType(TRANSPORT_VPN) 912 .removeCapability(NET_CAPABILITY_NOT_VPN) 913 .removeCapability(NET_CAPABILITY_TRUSTED) // TODO: add to VPN! 914 .build() 915 val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 916 registerNetworkCallback(request, callback) 917 918 val nc = NetworkCapabilities().apply { 919 addTransportType(TRANSPORT_TEST) 920 addTransportType(TRANSPORT_VPN) 921 removeCapability(NET_CAPABILITY_NOT_VPN) 922 setTransportInfo(VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE, mySessionId)) 923 if (SdkLevel.isAtLeastS()) { 924 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 925 } 926 } 927 val defaultNetwork = mCM.activeNetwork 928 assertNotNull(defaultNetwork) 929 val defaultNetworkCapabilities = mCM.getNetworkCapabilities(defaultNetwork) 930 assertNotNull(defaultNetworkCapabilities) 931 val defaultNetworkTransports = defaultNetworkCapabilities.transportTypes 932 933 val agent = createNetworkAgent(initialNc = nc) 934 agent.register() 935 agent.markConnected() 936 callback.expectAvailableThenValidatedCallbacks(agent.network!!) 937 938 // Check that the default network's transport is propagated to the VPN. 939 var vpnNc = mCM.getNetworkCapabilities(agent.network!!) 940 assertNotNull(vpnNc) 941 assertEquals( 942 VpnManager.TYPE_VPN_SERVICE, 943 (vpnNc.transportInfo as VpnTransportInfo).type 944 ) 945 assertEquals(mySessionId, (vpnNc.transportInfo as VpnTransportInfo).sessionId) 946 947 val testAndVpn = intArrayOf(TRANSPORT_TEST, TRANSPORT_VPN) 948 assertTrue(vpnNc.hasAllTransports(testAndVpn)) 949 assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_VPN)) 950 assertTrue( 951 vpnNc.hasAllTransports(defaultNetworkTransports), 952 "VPN transports ${Arrays.toString(vpnNc.transportTypes)}" + 953 " lacking transports from ${Arrays.toString(defaultNetworkTransports)}" 954 ) 955 956 // Check that when no underlying networks are announced the underlying transport disappears. 957 agent.setUnderlyingNetworks(listOf<Network>()) 958 callback.expectCaps(agent.network!!) { 959 it.transportTypes.size == 2 && it.hasAllTransports(testAndVpn) 960 } 961 962 // Put the underlying network back and check that the underlying transport reappears. 963 val expectedTransports = (defaultNetworkTransports.toSet() + TRANSPORT_TEST + TRANSPORT_VPN) 964 .toIntArray() 965 agent.setUnderlyingNetworks(null) 966 callback.expectCaps(agent.network!!) { 967 it.transportTypes.size == expectedTransports.size && 968 it.hasAllTransports(expectedTransports) 969 } 970 971 // Check that some underlying capabilities are propagated. 972 // This is not very accurate because the test does not control the capabilities of the 973 // underlying networks, and because not congested, not roaming, and not suspended are the 974 // default anyway. It's still useful as an extra check though. 975 vpnNc = mCM.getNetworkCapabilities(agent.network!!)!! 976 for (cap in listOf( 977 NET_CAPABILITY_NOT_CONGESTED, 978 NET_CAPABILITY_NOT_ROAMING, 979 NET_CAPABILITY_NOT_SUSPENDED 980 )) { 981 val capStr = valueToString(NetworkCapabilities::class.java, "NET_CAPABILITY_", cap) 982 if (defaultNetworkCapabilities.hasCapability(cap) && !vpnNc.hasCapability(cap)) { 983 fail("$capStr not propagated from underlying: $defaultNetworkCapabilities") 984 } 985 } 986 987 unregister(agent) 988 callback.expect<Lost>(agent.network!!) 989 } 990 doTestOemVpnTypenull991 fun doTestOemVpnType(type: Int) { 992 val mySessionId = "MySession12345" 993 val nc = NetworkCapabilities().apply { 994 addTransportType(TRANSPORT_TEST) 995 addTransportType(TRANSPORT_VPN) 996 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 997 removeCapability(NET_CAPABILITY_NOT_VPN) 998 setTransportInfo(VpnTransportInfo(type, mySessionId)) 999 } 1000 1001 val agent = createNetworkAgent(initialNc = nc) 1002 agent.register() 1003 agent.markConnected() 1004 1005 val request = NetworkRequest.Builder() 1006 .clearCapabilities() 1007 .addTransportType(TRANSPORT_VPN) 1008 .removeCapability(NET_CAPABILITY_NOT_VPN) 1009 .build() 1010 val callback = TestableNetworkCallback() 1011 registerNetworkCallback(request, callback) 1012 1013 callback.expectAvailableThenValidatedCallbacks(agent.network!!) 1014 1015 var vpnNc = mCM.getNetworkCapabilities(agent.network!!) 1016 assertNotNull(vpnNc) 1017 assertEquals(type, (vpnNc!!.transportInfo as VpnTransportInfo).type) 1018 1019 agent.unregister() 1020 callback.expect<Lost>(agent.network!!) 1021 } 1022 1023 @Test 1024 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testOemVpnTypesnull1025 fun testOemVpnTypes() { 1026 // TODO: why is this necessary given the @IgnoreUpTo above? 1027 assumeTrue(SdkLevel.isAtLeastB()) 1028 doTestOemVpnType(VpnManager.TYPE_VPN_OEM_SERVICE) 1029 doTestOemVpnType(VpnManager.TYPE_VPN_OEM_LEGACY) 1030 } 1031 unregisternull1032 private fun unregister(agent: TestableNetworkAgent) { 1033 agent.unregister() 1034 agent.eventuallyExpect<OnNetworkUnwanted>() 1035 agent.eventuallyExpect<OnNetworkDestroyed>() 1036 } 1037 1038 @Test 1039 @IgnoreUpTo(Build.VERSION_CODES.R) testAgentStartsInConnectingnull1040 fun testAgentStartsInConnecting() { 1041 val mockContext = mock(Context::class.java) 1042 val mockCm = mock(ConnectivityManager::class.java) 1043 val mockedResult = ConnectivityManager.MockHelpers.registerNetworkAgentResult( 1044 mock(Network::class.java), 1045 mock(INetworkAgentRegistry::class.java) 1046 ) 1047 doReturn(SHOULD_CREATE_NETWORKS_IMMEDIATELY).`when`(mockCm) 1048 .isFeatureEnabled( 1049 eq(ConnectivityManager.FEATURE_QUEUE_NETWORK_AGENT_EVENTS_IN_SYSTEM_SERVER) 1050 ) 1051 doReturn(Context.CONNECTIVITY_SERVICE).`when`(mockContext) 1052 .getSystemServiceName(ConnectivityManager::class.java) 1053 doReturn(mockCm).`when`(mockContext).getSystemService(Context.CONNECTIVITY_SERVICE) 1054 doReturn(mockedResult).`when`(mockCm).registerNetworkAgent( 1055 any(), 1056 any(), 1057 any(), 1058 any(), 1059 any(), 1060 any(), 1061 anyInt() 1062 ) 1063 val agent = createNetworkAgent(mockContext) 1064 agent.register() 1065 verify(mockCm).registerNetworkAgent( 1066 any(), 1067 argThat<NetworkInfo> { it.detailedState == NetworkInfo.DetailedState.CONNECTING }, 1068 any(LinkProperties::class.java), 1069 any(NetworkCapabilities::class.java), 1070 any(NetworkScore::class.java), 1071 any(NetworkAgentConfig::class.java), 1072 eq(NetworkProvider.ID_NONE) 1073 ) 1074 } 1075 1076 @Test testSetAcceptUnvalidatednull1077 fun testSetAcceptUnvalidated() { 1078 createNetworkAgentWithFakeCS().let { agent -> 1079 mFakeConnectivityService.agent.onSaveAcceptUnvalidated(true) 1080 agent.expectCallback<OnSaveAcceptUnvalidated>().let { 1081 assertTrue(it.accept) 1082 } 1083 agent.assertNoCallback() 1084 } 1085 } 1086 1087 @Test testSetAcceptUnvalidatedPreventAutomaticReconnectnull1088 fun testSetAcceptUnvalidatedPreventAutomaticReconnect() { 1089 createNetworkAgentWithFakeCS().let { agent -> 1090 mFakeConnectivityService.agent.onSaveAcceptUnvalidated(false) 1091 mFakeConnectivityService.agent.onPreventAutomaticReconnect() 1092 agent.expectCallback<OnSaveAcceptUnvalidated>().let { 1093 assertFalse(it.accept) 1094 } 1095 agent.expectCallback<OnAutomaticReconnectDisabled>() 1096 agent.assertNoCallback() 1097 // When automatic reconnect is turned off, the network is torn down and 1098 // ConnectivityService disconnects. As part of the disconnect, ConnectivityService will 1099 // also send itself a message to unregister the NetworkAgent from its internal 1100 // structure. 1101 mFakeConnectivityService.disconnect() 1102 agent.expectCallback<OnNetworkUnwanted>() 1103 } 1104 } 1105 1106 @Test testPreventAutomaticReconnectnull1107 fun testPreventAutomaticReconnect() { 1108 createNetworkAgentWithFakeCS().let { agent -> 1109 mFakeConnectivityService.agent.onPreventAutomaticReconnect() 1110 agent.expectCallback<OnAutomaticReconnectDisabled>() 1111 agent.assertNoCallback() 1112 mFakeConnectivityService.disconnect() 1113 agent.expectCallback<OnNetworkUnwanted>() 1114 } 1115 } 1116 1117 @Test agentnull1118 fun testValidationStatus() = createNetworkAgentWithFakeCS().let { agent -> 1119 val uri = Uri.parse("http://www.google.com") 1120 mFakeConnectivityService.agent.onValidationStatusChanged( 1121 VALID_NETWORK, 1122 uri.toString() 1123 ) 1124 agent.expectCallback<OnValidationStatus>().let { 1125 assertEquals(it.status, VALID_NETWORK) 1126 assertEquals(it.uri, uri) 1127 } 1128 1129 mFakeConnectivityService.agent.onValidationStatusChanged(INVALID_NETWORK, null) 1130 agent.expectCallback<OnValidationStatus>().let { 1131 assertEquals(it.status, INVALID_NETWORK) 1132 assertNull(it.uri) 1133 } 1134 } 1135 1136 @Test testTemporarilyUnmeteredCapabilitynull1137 fun testTemporarilyUnmeteredCapability() { 1138 // This test will create a networks with/without NET_CAPABILITY_TEMPORARILY_NOT_METERED 1139 // and check that the callback reflects the capability changes. 1140 1141 // Connect the network 1142 val (agent, callback) = createConnectedNetworkAgent() 1143 1144 // Send TEMP_NOT_METERED and check that the callback is called appropriately. 1145 val nc1 = NetworkCapabilities(agent.nc) 1146 .addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 1147 agent.sendNetworkCapabilities(nc1) 1148 callback.expectCaps(agent.network!!) { 1149 it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 1150 } 1151 1152 // Remove TEMP_NOT_METERED and check that the callback is called appropriately. 1153 val nc2 = NetworkCapabilities(agent.nc) 1154 .removeCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 1155 agent.sendNetworkCapabilities(nc2) 1156 callback.expectCaps(agent.network!!) { 1157 !it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 1158 } 1159 1160 // tearDown() will unregister the requests and agents 1161 } 1162 1163 @Test 1164 @IgnoreUpTo(Build.VERSION_CODES.R) testSetLingerDurationnull1165 fun testSetLingerDuration() { 1166 // This test will create two networks and check that the one with the stronger 1167 // score wins out for a request that matches them both. And the weaker agent will 1168 // be disconnected after customized linger duration. 1169 1170 // Request the first Network, with a request that could moved to agentStronger in order to 1171 // make agentWeaker linger later. 1172 val specifierWeaker = UUID.randomUUID().toString() 1173 val specifierStronger = UUID.randomUUID().toString() 1174 val commonCallback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 1175 requestNetwork(makeTestNetworkRequest(), commonCallback) 1176 val agentWeaker = createNetworkAgent(specifier = specifierWeaker) 1177 agentWeaker.register() 1178 agentWeaker.markConnected() 1179 commonCallback.expectAvailableThenValidatedCallbacks(agentWeaker.network!!) 1180 // Downgrade agentWeaker to a worse score so that there is no ambiguity when 1181 // agentStronger connects. 1182 agentWeaker.sendNetworkScore(NetworkScore.Builder().setLegacyInt(WORSE_NETWORK_SCORE) 1183 .setExiting(true).build()) 1184 1185 // Verify invalid linger duration cannot be set. 1186 assertFailsWith<IllegalArgumentException> { 1187 agentWeaker.setLingerDuration(Duration.ofMillis(-1)) 1188 } 1189 assertFailsWith<IllegalArgumentException> { agentWeaker.setLingerDuration(Duration.ZERO) } 1190 assertFailsWith<IllegalArgumentException> { 1191 agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MIN_VALUE.toLong())) 1192 } 1193 assertFailsWith<IllegalArgumentException> { 1194 agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong() + 1)) 1195 } 1196 assertFailsWith<IllegalArgumentException> { 1197 agentWeaker.setLingerDuration(Duration.ofMillis( 1198 NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - 1 1199 )) 1200 } 1201 // Verify valid linger timer can be set, but it should not take effect since the network 1202 // is still needed. 1203 agentWeaker.setLingerDuration(Duration.ofMillis(Integer.MAX_VALUE.toLong())) 1204 commonCallback.assertNoCallback(NO_CALLBACK_TIMEOUT) 1205 // Set to the value we want to verify the functionality. 1206 agentWeaker.setLingerDuration(Duration.ofMillis(NetworkAgent.MIN_LINGER_TIMER_MS.toLong())) 1207 // Make a listener which can observe agentWeaker lost later. 1208 val callbackWeaker = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 1209 registerNetworkCallback( 1210 NetworkRequest.Builder() 1211 .clearCapabilities() 1212 .addTransportType(TRANSPORT_TEST) 1213 .setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifierWeaker)) 1214 .build(), 1215 callbackWeaker 1216 ) 1217 callbackWeaker.expectAvailableCallbacks(agentWeaker.network!!) 1218 1219 // Connect the agentStronger with a score better than agentWeaker. Verify the callback for 1220 // agentWeaker sees the linger expiry while the callback for both sees the winner. 1221 // Record linger start timestamp prior to send score to prevent possible race, the actual 1222 // timestamp should be slightly late than this since the service handles update 1223 // network score asynchronously. 1224 val lingerStart = SystemClock.elapsedRealtime() 1225 val agentStronger = createNetworkAgent(specifier = specifierStronger) 1226 agentStronger.register() 1227 agentStronger.markConnected() 1228 commonCallback.expectAvailableCallbacks(agentStronger.network!!) 1229 callbackWeaker.expect<Losing>(agentWeaker.network!!) 1230 val expectedRemainingLingerDuration = lingerStart + 1231 NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - SystemClock.elapsedRealtime() 1232 // If the available callback is too late. The remaining duration will be reduced. 1233 assertTrue( 1234 expectedRemainingLingerDuration > 0, 1235 "expected remaining linger duration is $expectedRemainingLingerDuration" 1236 ) 1237 callbackWeaker.assertNoCallback(expectedRemainingLingerDuration) 1238 callbackWeaker.expect<Lost>(agentWeaker.network!!) 1239 } 1240 1241 @Test 1242 @IgnoreUpTo(Build.VERSION_CODES.R) testSetSubscriberIdnull1243 fun testSetSubscriberId() { 1244 val imsi = UUID.randomUUID().toString() 1245 val config = NetworkAgentConfig.Builder().setSubscriberId(imsi).build() 1246 1247 val (agent, _) = createConnectedNetworkAgent(initialConfig = config) 1248 val snapshots = runWithShellPermissionIdentity(ThrowingSupplier { 1249 mCM!!.allNetworkStateSnapshots }, NETWORK_SETTINGS) 1250 val testNetworkSnapshot = snapshots.findLast { it.network == agent.network } 1251 assertEquals(imsi, testNetworkSnapshot!!.subscriberId) 1252 } 1253 1254 // TODO: Refactor helper functions to util class and move this test case to 1255 // {@link android.net.cts.ConnectivityManagerTest}. 1256 @Test 1257 @IgnoreUpTo(Build.VERSION_CODES.R) testRegisterBestMatchingNetworkCallbacknull1258 fun testRegisterBestMatchingNetworkCallback() { 1259 // Register best matching network callback with additional condition that will be 1260 // exercised later. This assumes the test network agent has NOT_VCN_MANAGED in it and 1261 // does not have NET_CAPABILITY_TEMPORARILY_NOT_METERED. 1262 val bestMatchingCb = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 1263 registerBestMatchingNetworkCallback( 1264 NetworkRequest.Builder() 1265 .clearCapabilities() 1266 .addTransportType(TRANSPORT_TEST) 1267 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 1268 .build(), 1269 bestMatchingCb, 1270 mHandlerThread.threadHandler 1271 ) 1272 1273 val (agent1, _) = createConnectedNetworkAgent(specifier = "AGENT-1") 1274 bestMatchingCb.expectAvailableThenValidatedCallbacks(agent1.network!!) 1275 // Make agent1 worse so when agent2 shows up, the callback will see that. 1276 agent1.sendNetworkScore(NetworkScore.Builder().setExiting(true).build()) 1277 bestMatchingCb.assertNoCallback(NO_CALLBACK_TIMEOUT) 1278 1279 val (agent2, _) = createConnectedNetworkAgent(specifier = "AGENT-2") 1280 bestMatchingCb.expectAvailableDoubleValidatedCallbacks(agent2.network!!) 1281 1282 // Change something on agent1 to trigger capabilities changed, since the callback 1283 // only cares about the best network, verify it received nothing from agent1. 1284 val ncAgent1 = agent1.nc 1285 ncAgent1.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 1286 agent1.sendNetworkCapabilities(ncAgent1) 1287 bestMatchingCb.assertNoCallback(NO_CALLBACK_TIMEOUT) 1288 1289 // Make agent1 the best network again, verify the callback now tracks agent1. 1290 agent1.sendNetworkScore(NetworkScore.Builder() 1291 .setExiting(false).setTransportPrimary(true).build()) 1292 bestMatchingCb.expectAvailableCallbacks(agent1.network!!) 1293 1294 // Make agent1 temporary vcn managed, which will not satisfying the request. 1295 // Verify the callback switch from/to the other network accordingly. 1296 ncAgent1.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 1297 agent1.sendNetworkCapabilities(ncAgent1) 1298 bestMatchingCb.expectAvailableCallbacks(agent2.network!!) 1299 ncAgent1.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 1300 agent1.sendNetworkCapabilities(ncAgent1) 1301 bestMatchingCb.expectAvailableDoubleValidatedCallbacks(agent1.network!!) 1302 1303 // Verify the callback doesn't care about agent2 disconnect. 1304 agent2.unregister() 1305 agentsToCleanUp.remove(agent2) 1306 bestMatchingCb.assertNoCallback() 1307 agent1.unregister() 1308 agentsToCleanUp.remove(agent1) 1309 bestMatchingCb.expect<Lost>(agent1.network!!) 1310 1311 // tearDown() will unregister the requests and agents 1312 } 1313 1314 private class TestableQosCallback : QosCallback() { 1315 val history = ArrayTrackRecord<CallbackEntry>().newReadHead() 1316 1317 sealed class CallbackEntry { 1318 data class OnQosSessionAvailable(val sess: QosSession, val attr: QosSessionAttributes) : 1319 CallbackEntry() 1320 data class OnQosSessionLost(val sess: QosSession) : CallbackEntry() 1321 data class OnError(val ex: QosCallbackException) : CallbackEntry() 1322 } 1323 onQosSessionAvailablenull1324 override fun onQosSessionAvailable(sess: QosSession, attr: QosSessionAttributes) { 1325 history.add(OnQosSessionAvailable(sess, attr)) 1326 } 1327 onQosSessionLostnull1328 override fun onQosSessionLost(sess: QosSession) { 1329 history.add(OnQosSessionLost(sess)) 1330 } 1331 onErrornull1332 override fun onError(ex: QosCallbackException) { 1333 history.add(OnError(ex)) 1334 } 1335 expectCallbacknull1336 inline fun <reified T : CallbackEntry> expectCallback(): T { 1337 val foundCallback = history.poll(DEFAULT_TIMEOUT_MS) 1338 assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback") 1339 return foundCallback 1340 } 1341 expectCallbacknull1342 inline fun <reified T : CallbackEntry> expectCallback(valid: (T) -> Boolean) { 1343 val foundCallback = history.poll(DEFAULT_TIMEOUT_MS) 1344 assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback") 1345 assertTrue(valid(foundCallback), "Unexpected callback : $foundCallback") 1346 } 1347 assertNoCallbacknull1348 fun assertNoCallback() { 1349 assertNull( 1350 history.poll(NO_CALLBACK_TIMEOUT), 1351 "Callback received" 1352 ) 1353 } 1354 } 1355 setupForQosCallbackTestnull1356 private fun <T : Closeable> setupForQosCallbackTest(creator: (TestableNetworkAgent) -> T) = 1357 createConnectedNetworkAgent().first.let { Pair(it, creator(it)) } 1358 setupForQosSocketnull1359 private fun setupForQosSocket() = setupForQosCallbackTest { 1360 agent: TestableNetworkAgent -> Socket() 1361 .also { assertNotNull(agent.network?.bindSocket(it)) 1362 it.bind(InetSocketAddress(InetAddress.getLoopbackAddress(), 0)) } 1363 } 1364 setupForQosDatagramnull1365 private fun setupForQosDatagram() = setupForQosCallbackTest { 1366 agent: TestableNetworkAgent -> DatagramSocket( 1367 InetSocketAddress(InetAddress.getLoopbackAddress(), 0) 1368 ) 1369 .also { assertNotNull(agent.network?.bindSocket(it)) } 1370 } 1371 1372 @Test testQosCallbackRegisterAndUnregisternull1373 fun testQosCallbackRegisterAndUnregister() { 1374 validateQosCallbackRegisterAndUnregister(IPPROTO_TCP) 1375 } 1376 1377 @Test testQosCallbackRegisterAndUnregisterWithDatagramSocketnull1378 fun testQosCallbackRegisterAndUnregisterWithDatagramSocket() { 1379 validateQosCallbackRegisterAndUnregister(IPPROTO_UDP) 1380 } 1381 validateQosCallbackRegisterAndUnregisternull1382 private fun validateQosCallbackRegisterAndUnregister(proto: Int) { 1383 val (agent, qosTestSocket) = when (proto) { 1384 IPPROTO_TCP -> setupForQosSocket() 1385 IPPROTO_UDP -> setupForQosDatagram() 1386 else -> fail("unsupported protocol") 1387 } 1388 val qosCallback = TestableQosCallback() 1389 var callbackId = -1 1390 Executors.newSingleThreadExecutor().let { executor -> 1391 try { 1392 val info = QosSocketInfo(agent, qosTestSocket) 1393 mCM.registerQosCallback(info, executor, qosCallback) 1394 agent.expectCallback<OnRegisterQosCallback>().let { 1395 callbackId = it.callbackId 1396 assertTrue(it.filter.matchesProtocol(proto)) 1397 } 1398 1399 assertFailsWith<QosCallbackRegistrationException>( 1400 "The same callback cannot be " + 1401 "registered more than once without first being unregistered" 1402 ) { 1403 mCM.registerQosCallback(info, executor, qosCallback) 1404 } 1405 } finally { 1406 qosTestSocket.close() 1407 mCM.unregisterQosCallback(qosCallback) 1408 agent.expectCallback<OnUnregisterQosCallback> { it.callbackId == callbackId } 1409 executor.shutdown() 1410 } 1411 } 1412 } 1413 1414 @Test testQosCallbackOnQosSessionnull1415 fun testQosCallbackOnQosSession() { 1416 validateQosCallbackOnQosSession(IPPROTO_TCP) 1417 } 1418 1419 @Test testQosCallbackOnQosSessionWithDatagramSocketnull1420 fun testQosCallbackOnQosSessionWithDatagramSocket() { 1421 validateQosCallbackOnQosSession(IPPROTO_UDP) 1422 } 1423 QosSocketInfonull1424 fun QosSocketInfo(agent: NetworkAgent, socket: Closeable) = when (socket) { 1425 is Socket -> QosSocketInfo(checkNotNull(agent.network), socket) 1426 is DatagramSocket -> QosSocketInfo(checkNotNull(agent.network), socket) 1427 else -> fail("unexpected socket type") 1428 } 1429 validateQosCallbackOnQosSessionnull1430 private fun validateQosCallbackOnQosSession(proto: Int) { 1431 val (agent, qosTestSocket) = when (proto) { 1432 IPPROTO_TCP -> setupForQosSocket() 1433 IPPROTO_UDP -> setupForQosDatagram() 1434 else -> fail("unsupported protocol") 1435 } 1436 val qosCallback = TestableQosCallback() 1437 Executors.newSingleThreadExecutor().let { executor -> 1438 try { 1439 val info = QosSocketInfo(agent, qosTestSocket) 1440 assertEquals(agent.network, info.getNetwork()) 1441 mCM.registerQosCallback(info, executor, qosCallback) 1442 val callbackId = agent.expectCallback<OnRegisterQosCallback>().callbackId 1443 1444 val uniqueSessionId = 4294967397 1445 val sessId = 101 1446 1447 val attributes = createEpsAttributes(5) 1448 assertEquals(attributes.qosIdentifier, 5) 1449 agent.sendQosSessionAvailable(callbackId, sessId, attributes) 1450 qosCallback.expectCallback<OnQosSessionAvailable> { 1451 it.sess.sessionId == sessId && it.sess.uniqueId == uniqueSessionId && 1452 it.sess.sessionType == QosSession.TYPE_EPS_BEARER 1453 } 1454 1455 agent.sendQosSessionLost(callbackId, sessId, QosSession.TYPE_EPS_BEARER) 1456 qosCallback.expectCallback<OnQosSessionLost> { 1457 it.sess.sessionId == sessId && it.sess.uniqueId == uniqueSessionId && 1458 it.sess.sessionType == QosSession.TYPE_EPS_BEARER 1459 } 1460 1461 // Make sure that we don't get more qos callbacks 1462 mCM.unregisterQosCallback(qosCallback) 1463 agent.expectCallback<OnUnregisterQosCallback>() 1464 1465 agent.sendQosSessionLost(callbackId, sessId, QosSession.TYPE_EPS_BEARER) 1466 qosCallback.assertNoCallback() 1467 } finally { 1468 qosTestSocket.close() 1469 // safety precaution 1470 mCM.unregisterQosCallback(qosCallback) 1471 1472 executor.shutdown() 1473 } 1474 } 1475 } 1476 1477 @Test testQosCallbackOnErrornull1478 fun testQosCallbackOnError() { 1479 val (agent, qosTestSocket) = setupForQosSocket() 1480 val qosCallback = TestableQosCallback() 1481 Executors.newSingleThreadExecutor().let { executor -> 1482 try { 1483 val info = QosSocketInfo(agent.network!!, qosTestSocket) 1484 mCM.registerQosCallback(info, executor, qosCallback) 1485 val callbackId = agent.expectCallback<OnRegisterQosCallback>().callbackId 1486 1487 val sessId = 101 1488 val attributes = createEpsAttributes() 1489 1490 // Double check that this is wired up and ready to go 1491 agent.sendQosSessionAvailable(callbackId, sessId, attributes) 1492 qosCallback.expectCallback<OnQosSessionAvailable>() 1493 1494 // Check that onError is coming through correctly 1495 agent.sendQosCallbackError( 1496 callbackId, 1497 QosCallbackException.EX_TYPE_FILTER_NOT_SUPPORTED 1498 ) 1499 qosCallback.expectCallback<OnError> { 1500 it.ex.cause is UnsupportedOperationException 1501 } 1502 1503 // Ensure that when an error occurs the callback was also unregistered 1504 agent.sendQosSessionLost(callbackId, sessId, QosSession.TYPE_EPS_BEARER) 1505 qosCallback.assertNoCallback() 1506 } finally { 1507 qosTestSocket.close() 1508 1509 // Make sure that the callback is fully unregistered 1510 mCM.unregisterQosCallback(qosCallback) 1511 1512 executor.shutdown() 1513 } 1514 } 1515 } 1516 1517 @Test testQosCallbackIdsAreMappedCorrectlynull1518 fun testQosCallbackIdsAreMappedCorrectly() { 1519 val (agent, qosTestSocket) = setupForQosSocket() 1520 val qosCallback1 = TestableQosCallback() 1521 val qosCallback2 = TestableQosCallback() 1522 Executors.newSingleThreadExecutor().let { executor -> 1523 try { 1524 val info = QosSocketInfo(agent.network!!, qosTestSocket) 1525 mCM.registerQosCallback(info, executor, qosCallback1) 1526 val callbackId1 = agent.expectCallback<OnRegisterQosCallback>().callbackId 1527 1528 mCM.registerQosCallback(info, executor, qosCallback2) 1529 val callbackId2 = agent.expectCallback<OnRegisterQosCallback>().callbackId 1530 1531 val sessId1 = 101 1532 val attributes1 = createEpsAttributes(1) 1533 1534 // Check #1 1535 agent.sendQosSessionAvailable(callbackId1, sessId1, attributes1) 1536 qosCallback1.expectCallback<OnQosSessionAvailable>() 1537 qosCallback2.assertNoCallback() 1538 1539 // Check #2 1540 val sessId2 = 102 1541 val attributes2 = createEpsAttributes(2) 1542 agent.sendQosSessionAvailable(callbackId2, sessId2, attributes2) 1543 qosCallback1.assertNoCallback() 1544 qosCallback2.expectCallback<OnQosSessionAvailable> { sessId2 == it.sess.sessionId } 1545 } finally { 1546 qosTestSocket.close() 1547 1548 // Make sure that the callback is fully unregistered 1549 mCM.unregisterQosCallback(qosCallback1) 1550 mCM.unregisterQosCallback(qosCallback2) 1551 1552 executor.shutdown() 1553 } 1554 } 1555 } 1556 1557 @Test testQosCallbackWhenNetworkReleasednull1558 fun testQosCallbackWhenNetworkReleased() { 1559 val (agent, qosTestSocket) = setupForQosSocket() 1560 Executors.newSingleThreadExecutor().let { executor -> 1561 try { 1562 val qosCallback1 = TestableQosCallback() 1563 val qosCallback2 = TestableQosCallback() 1564 try { 1565 val info = QosSocketInfo(agent.network!!, qosTestSocket) 1566 mCM.registerQosCallback(info, executor, qosCallback1) 1567 mCM.registerQosCallback(info, executor, qosCallback2) 1568 agent.unregister() 1569 1570 qosCallback1.expectCallback<OnError> { 1571 it.ex.cause is NetworkReleasedException 1572 } 1573 1574 qosCallback2.expectCallback<OnError> { 1575 it.ex.cause is NetworkReleasedException 1576 } 1577 } finally { 1578 qosTestSocket.close() 1579 mCM.unregisterQosCallback(qosCallback1) 1580 mCM.unregisterQosCallback(qosCallback2) 1581 } 1582 } finally { 1583 qosTestSocket.close() 1584 executor.shutdown() 1585 } 1586 } 1587 } 1588 createEpsAttributesnull1589 private fun createEpsAttributes(qci: Int = 1): EpsBearerQosSessionAttributes { 1590 val remoteAddresses = ArrayList<InetSocketAddress>() 1591 remoteAddresses.add(InetSocketAddress(REMOTE_ADDRESS, 80)) 1592 return EpsBearerQosSessionAttributes( 1593 qci, 1594 2, 1595 3, 1596 4, 1597 5, 1598 remoteAddresses 1599 ) 1600 } 1601 sendAndExpectUdpPacketnull1602 fun sendAndExpectUdpPacket( 1603 net: Network, 1604 reader: PollPacketReader, 1605 iface: TestNetworkInterface 1606 ) { 1607 val s = Os.socket(AF_INET6, SOCK_DGRAM, 0) 1608 net.bindSocket(s) 1609 val content = ByteArray(16) 1610 Random.nextBytes(content) 1611 Os.sendto(s, ByteBuffer.wrap(content), 0, REMOTE_ADDRESS, 7 /* port */) 1612 val match = reader.poll(DEFAULT_TIMEOUT_MS) { 1613 val udpStart = IPV6_HEADER_LEN + UDP_HEADER_LEN 1614 it.size == udpStart + content.size && 1615 it[0].toInt() and 0xf0 == 0x60 && 1616 it[IPV6_PROTOCOL_OFFSET].toInt() == IPPROTO_UDP && 1617 Arrays.equals(content, it.copyOfRange(udpStart, udpStart + content.size)) 1618 } 1619 assertNotNull( 1620 match, 1621 "Did not receive matching packet on ${iface.interfaceName} " + 1622 " after ${DEFAULT_TIMEOUT_MS}ms" 1623 ) 1624 } 1625 createInterfaceAndReadernull1626 fun createInterfaceAndReader(): Triple<TestNetworkInterface, PollPacketReader, LinkProperties> { 1627 val iface = createTunInterface(listOf(LINK_ADDRESS)) 1628 val handler = Handler(Looper.getMainLooper()) 1629 val reader = PollPacketReader(handler, iface.fileDescriptor.fileDescriptor, ETHER_MTU) 1630 reader.startAsyncForTest() 1631 handler.waitForIdle(DEFAULT_TIMEOUT_MS) 1632 val ifName = iface.interfaceName 1633 val lp = makeTestLinkProperties(ifName) 1634 return Triple(iface, reader, lp) 1635 } 1636 1637 @Test testRegisterAfterUnregisternull1638 fun testRegisterAfterUnregister() { 1639 val (iface, reader, lp) = createInterfaceAndReader() 1640 1641 // File a request that matches and keeps up the best-scoring test network. 1642 val testCallback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 1643 requestNetwork(makeTestNetworkRequest(), testCallback) 1644 1645 // Register and unregister networkagents in a loop, checking that every time an agent 1646 // connects, the native network is correctly configured and packets can be sent. 1647 // Running 10 iterations takes about 1 second on x86 cuttlefish, and detects the race in 1648 // b/286649301 most of the time. 1649 for (i in 1..10) { 1650 val agent1 = createNetworkAgent(realContext, initialLp = lp) 1651 agent1.register() 1652 agent1.unregister() 1653 1654 val agent2 = createNetworkAgent(realContext, initialLp = lp) 1655 agent2.register() 1656 agent2.markConnected() 1657 val network2 = agent2.network!! 1658 1659 testCallback.expectAvailableThenValidatedCallbacks(network2) 1660 sendAndExpectUdpPacket(network2, reader, iface) 1661 agent2.unregister() 1662 testCallback.expect<Lost>(network2) 1663 } 1664 } 1665 1666 @Test testUnregisterAfterReplacementnull1667 fun testUnregisterAfterReplacement() { 1668 val (iface, reader, lp) = createInterfaceAndReader() 1669 1670 // Keeps an eye on all test networks. 1671 val matchAllCallback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 1672 registerNetworkCallback(makeTestNetworkRequest(), matchAllCallback) 1673 1674 // File a request that matches and keeps up the best-scoring test network. 1675 val testCallback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 1676 requestNetwork(makeTestNetworkRequest(), testCallback) 1677 1678 // Connect the first network. This should satisfy the request. 1679 val (agent1, network1) = connectNetwork(lp = lp) 1680 matchAllCallback.expectAvailableThenValidatedCallbacks(network1) 1681 testCallback.expectAvailableThenValidatedCallbacks(network1) 1682 sendAndExpectUdpPacket(network1, reader, iface) 1683 1684 // Connect a second agent. network1 is preferred because it was already registered, so 1685 // testCallback will not see any events. agent2 is torn down because it has no requests. 1686 val (agent2, network2) = connectNetwork() 1687 matchAllCallback.expectAvailableThenValidatedCallbacks(network2) 1688 matchAllCallback.expect<Lost>(network2) 1689 agent2.expectCallback<OnNetworkUnwanted>() 1690 agent2.expectCallback<OnNetworkDestroyed>() 1691 assertNull(mCM.getLinkProperties(network2)) 1692 1693 // Mark the first network as awaiting replacement. This should destroy the underlying 1694 // native network and send onNetworkDestroyed, but will not send any NetworkCallbacks, 1695 // because for callback and scoring purposes network1 is still connected. 1696 agent1.unregisterAfterReplacement(5_000 /* timeoutMillis */) 1697 agent1.expectCallback<OnNetworkDestroyed>() 1698 assertThrows(IOException::class.java) { network1.bindSocket(DatagramSocket()) } 1699 assertNotNull(mCM.getLinkProperties(network1)) 1700 1701 // Calling unregisterAfterReplacement more than once has no effect. 1702 // If it did, this test would fail because the 1ms timeout means that the network would be 1703 // torn down before the replacement arrives. 1704 agent1.unregisterAfterReplacement(1 /* timeoutMillis */) 1705 1706 // Connect a third network. Because network1 is awaiting replacement, network3 is preferred 1707 // as soon as it validates (until then, it is outscored by network1). 1708 // The fact that the first event seen by matchAllCallback is the connection of network3 1709 // implicitly ensures that no callbacks are sent since network1 was lost. 1710 val (agent3, network3) = connectNetwork(lp = lp) 1711 if (SHOULD_CREATE_NETWORKS_IMMEDIATELY) { 1712 // This is the correct sequence of events. 1713 matchAllCallback.expectAvailableCallbacks(network3, validated = false) 1714 matchAllCallback.expect<Lost>(network1, 2_000 /* timeoutMs */) 1715 matchAllCallback.expectCaps(network3) { it.hasCapability(NET_CAPABILITY_VALIDATED) } 1716 sendAndExpectUdpPacket(network3, reader, iface) 1717 testCallback.expectAvailableDoubleValidatedCallbacks(network3) 1718 } else { 1719 // This is incorrect and fixed by the "create networks immediately" feature 1720 matchAllCallback.expectAvailableThenValidatedCallbacks(network3) 1721 testCallback.expectAvailableDoubleValidatedCallbacks(network3) 1722 sendAndExpectUdpPacket(network3, reader, iface) 1723 // As soon as the replacement arrives, network1 is disconnected. 1724 // Check that this happens before the replacement timeout (5 seconds) fires. 1725 matchAllCallback.expect<Lost>(network1, 2_000 /* timeoutMs */) 1726 } 1727 agent1.expectCallback<OnNetworkUnwanted>() 1728 1729 // Test lingering: 1730 // - Connect a higher-scoring network and check that network3 starts lingering. 1731 // - Mark network3 awaiting replacement. 1732 // - Check that network3 is torn down immediately without waiting for the linger timer or 1733 // the replacement timer to fire. This is a regular teardown, so it results in 1734 // onNetworkUnwanted before onNetworkDestroyed. 1735 val (agent4, agent4callback) = createConnectedNetworkAgent() 1736 val network4 = agent4.network!! 1737 matchAllCallback.expectAvailableThenValidatedCallbacks(network4) 1738 agent4.sendNetworkScore(NetworkScore.Builder().setTransportPrimary(true).build()) 1739 matchAllCallback.expect<Losing>(network3) 1740 testCallback.expectAvailableCallbacks(network4, validated = true) 1741 mCM.unregisterNetworkCallback(agent4callback) 1742 sendAndExpectUdpPacket(network3, reader, iface) 1743 agent3.unregisterAfterReplacement(5_000) 1744 agent3.expectCallback<OnNetworkUnwanted>() 1745 matchAllCallback.expect<Lost>(network3, 1000L) 1746 agent3.expectCallback<OnNetworkDestroyed>() 1747 1748 // Now mark network4 awaiting replacement with a low timeout, and check that if no 1749 // replacement arrives, it is torn down. 1750 agent4.unregisterAfterReplacement(100 /* timeoutMillis */) 1751 matchAllCallback.expect<Lost>(network4, 1000L /* timeoutMs */) 1752 testCallback.expect<Lost>(network4, 1000L /* timeoutMs */) 1753 agent4.expectCallback<OnNetworkDestroyed>() 1754 agent4.expectCallback<OnNetworkUnwanted>() 1755 1756 // If a network that is awaiting replacement is unregistered, it disconnects immediately, 1757 // before the replacement timeout fires. 1758 val (agent5, network5) = connectNetwork(lp = lp) 1759 matchAllCallback.expectAvailableThenValidatedCallbacks(network5) 1760 testCallback.expectAvailableThenValidatedCallbacks(network5) 1761 sendAndExpectUdpPacket(network5, reader, iface) 1762 agent5.unregisterAfterReplacement(5_000 /* timeoutMillis */) 1763 agent5.unregister() 1764 matchAllCallback.expect<Lost>(network5, 1000L /* timeoutMs */) 1765 testCallback.expect<Lost>(network5, 1000L /* timeoutMs */) 1766 agent5.expectCallback<OnNetworkDestroyed>() 1767 agent5.expectCallback<OnNetworkUnwanted>() 1768 1769 // If unregisterAfterReplacement is called before markConnected, the network disconnects. 1770 val specifier6 = UUID.randomUUID().toString() 1771 val callback = TestableNetworkCallback() 1772 requestNetwork(makeTestNetworkRequest(specifier = specifier6), callback) 1773 val agent6 = createNetworkAgent(specifier = specifier6) 1774 agent6.register() 1775 if (SHOULD_CREATE_NETWORKS_IMMEDIATELY) { 1776 agent6.expectCallback<OnNetworkCreated>() 1777 } else { 1778 // No callbacks are sent, so check LinkProperties to wait for the network to be created. 1779 assertLinkPropertiesEventuallyNotNull(agent6.network!!) 1780 } 1781 1782 // unregisterAfterReplacement tears down the network immediately. 1783 // Approximately check that this is the case by picking an unregister timeout that's longer 1784 // than the timeout of the expectCallback<OnNetworkUnwanted> below. 1785 // TODO: consider adding configurable timeouts to TestableNetworkAgent expectations. 1786 val timeoutMs = agent6.DEFAULT_TIMEOUT_MS.toInt() + 1_000 1787 agent6.unregisterAfterReplacement(timeoutMs) 1788 agent6.expectCallback<OnNetworkUnwanted>() 1789 if (!SdkLevel.isAtLeastT() || SHOULD_CREATE_NETWORKS_IMMEDIATELY) { 1790 // Before T, onNetworkDestroyed is called even if the network was never created. 1791 // If immediate native network creation is supported, the network was created by 1792 // register(). Destroying it sends onNetworkDestroyed. 1793 agent6.expectCallback<OnNetworkDestroyed>() 1794 } 1795 // Poll for LinkProperties becoming null, because when onNetworkUnwanted is called, the 1796 // network has not yet been removed from the CS data structures. 1797 assertLinkPropertiesEventuallyNull(agent6.network!!) 1798 assertFalse(mCM.getAllNetworks().contains(agent6.network!!)) 1799 1800 // After unregisterAfterReplacement is called, the network is no longer usable and 1801 // markConnected has no effect. 1802 agent6.markConnected() 1803 agent6.assertNoCallback() 1804 assertNull(mCM.getLinkProperties(agent6.network!!)) 1805 matchAllCallback.assertNoCallback(200 /* timeoutMs */) 1806 1807 // If wifi is replaced within the timeout, the device does not switch to cellular. 1808 val (cellAgent, cellNetwork) = connectNetwork(TRANSPORT_CELLULAR) 1809 testCallback.expectAvailableThenValidatedCallbacks(cellNetwork) 1810 matchAllCallback.expectAvailableThenValidatedCallbacks(cellNetwork) 1811 1812 val (wifiAgent, wifiNetwork) = connectNetwork(TRANSPORT_WIFI) 1813 testCallback.expectAvailableCallbacks(wifiNetwork, validated = true) 1814 testCallback.expectCaps(wifiNetwork) { it.hasCapability(NET_CAPABILITY_VALIDATED) } 1815 matchAllCallback.expectAvailableCallbacks(wifiNetwork, validated = false) 1816 matchAllCallback.expect<Losing>(cellNetwork) 1817 matchAllCallback.expectCaps(wifiNetwork) { it.hasCapability(NET_CAPABILITY_VALIDATED) } 1818 1819 wifiAgent.unregisterAfterReplacement(5_000 /* timeoutMillis */) 1820 wifiAgent.expectCallback<OnNetworkDestroyed>() 1821 1822 // Once the network is awaiting replacement, changing LinkProperties, NetworkCapabilities or 1823 // score, or calling reportNetworkConnectivity, have no effect. 1824 val wifiSpecifier = mCM.getNetworkCapabilities(wifiNetwork)!!.networkSpecifier 1825 assertNotNull(wifiSpecifier) 1826 assertTrue(wifiSpecifier is EthernetNetworkSpecifier) 1827 1828 val wifiNc = makeTestNetworkCapabilities( 1829 wifiSpecifier.interfaceName, 1830 intArrayOf(TRANSPORT_WIFI) 1831 ) 1832 wifiAgent.sendNetworkCapabilities(wifiNc) 1833 val wifiLp = mCM.getLinkProperties(wifiNetwork)!! 1834 val newRoute = RouteInfo(IpPrefix("192.0.2.42/24")) 1835 assertFalse(wifiLp.getRoutes().contains(newRoute)) 1836 wifiLp.addRoute(newRoute) 1837 wifiAgent.sendLinkProperties(wifiLp) 1838 mCM.reportNetworkConnectivity(wifiNetwork, false) 1839 // The test implicitly checks that no callbacks are sent here, because the next events seen 1840 // by the callbacks are for the new network connecting. 1841 1842 val (newWifiAgent, newWifiNetwork) = connectNetwork(TRANSPORT_WIFI) 1843 testCallback.expectAvailableCallbacks(newWifiNetwork, validated = true) 1844 if (SHOULD_CREATE_NETWORKS_IMMEDIATELY) { 1845 // This is the correct sequence of events 1846 matchAllCallback.expectAvailableCallbacks(newWifiNetwork, validated = false) 1847 matchAllCallback.expect<Lost>(wifiNetwork) 1848 matchAllCallback.expectCaps(newWifiNetwork) { 1849 it.hasCapability(NET_CAPABILITY_VALIDATED) 1850 } 1851 } else { 1852 // When networks are not created immediately, the sequence is slightly incorrect 1853 // and instead is as follows 1854 matchAllCallback.expectAvailableThenValidatedCallbacks(newWifiNetwork) 1855 matchAllCallback.expect<Lost>(wifiNetwork) 1856 } 1857 wifiAgent.expectCallback<OnNetworkUnwanted>() 1858 testCallback.expect<CapabilitiesChanged>(newWifiNetwork) 1859 1860 cellAgent.unregister() 1861 matchAllCallback.expect<Lost>(cellNetwork) 1862 newWifiAgent.unregister() 1863 matchAllCallback.expect<Lost>(newWifiNetwork) 1864 testCallback.expect<Lost>(newWifiNetwork) 1865 1866 // Calling unregisterAfterReplacement several times in quick succession works. 1867 // These networks are all kept up by testCallback. 1868 val agent10 = createNetworkAgent(realContext, initialLp = lp) 1869 agent10.register() 1870 agent10.unregisterAfterReplacement(5_000) 1871 1872 val agent11 = createNetworkAgent(realContext, initialLp = lp) 1873 agent11.register() 1874 agent11.unregisterAfterReplacement(5_000) 1875 1876 val agent12 = createNetworkAgent(realContext, initialLp = lp) 1877 agent12.register() 1878 agent12.unregisterAfterReplacement(5_000) 1879 1880 val agent13 = createNetworkAgent(realContext, initialLp = lp) 1881 agent13.register() 1882 agent13.markConnected() 1883 testCallback.expectAvailableThenValidatedCallbacks(agent13.network!!) 1884 sendAndExpectUdpPacket(agent13.network!!, reader, iface) 1885 agent13.unregister() 1886 } 1887 1888 @Test testUnregisterAgentBeforeAgentFullyConnectednull1889 fun testUnregisterAgentBeforeAgentFullyConnected() { 1890 val specifier = UUID.randomUUID().toString() 1891 val callback = TestableNetworkCallback() 1892 val transports = intArrayOf(TRANSPORT_CELLULAR) 1893 // Ensure this NetworkAgent is never unneeded by filing a request with its specifier. 1894 requestNetwork(makeTestNetworkRequest(specifier = specifier), callback) 1895 val nc = makeTestNetworkCapabilities(specifier, transports) 1896 val agent = createNetworkAgent(realContext, initialNc = nc) 1897 // Connect the agent 1898 agent.register() 1899 // Mark agent connected then unregister agent immediately. Verify that both available and 1900 // lost callback should be sent still. 1901 agent.markConnected() 1902 agent.unregister() 1903 callback.expect<Available>(agent.network!!) 1904 callback.eventuallyExpect<Lost> { it.network == agent.network } 1905 } 1906 doTestNativeNetworkCreationnull1907 fun doTestNativeNetworkCreation(expectCreatedImmediately: Boolean, transports: IntArray) { 1908 val iface = createTunInterface() 1909 val ifName = iface.interfaceName 1910 val nc = makeTestNetworkCapabilities(ifName, transports).also { 1911 if (transports.contains(TRANSPORT_VPN)) { 1912 val sessionId = "NetworkAgentTest-${Process.myPid()}" 1913 it.setTransportInfo(VpnTransportInfo( 1914 VpnManager.TYPE_VPN_PLATFORM, 1915 sessionId, 1916 /*bypassable=*/ 1917 false, 1918 /*longLivedTcpConnectionsExpensive=*/ 1919 false 1920 )) 1921 it.underlyingNetworks = listOf() 1922 } 1923 } 1924 val lp = makeTestLinkProperties(ifName) 1925 1926 // File a request containing the agent's specifier to receive callbacks and to ensure that 1927 // the agent is not torn down due to being unneeded. 1928 val request = makeTestNetworkRequest(specifier = ifName) 1929 val requestCallback = TestableNetworkCallback() 1930 requestNetwork(request, requestCallback) 1931 1932 val listenCallback = TestableNetworkCallback() 1933 registerNetworkCallback(request, listenCallback) 1934 1935 // Register the NetworkAgent... 1936 val agent = createNetworkAgent(realContext, initialNc = nc, initialLp = lp) 1937 val network = agent.register() 1938 1939 // ... and then change the NetworkCapabilities and LinkProperties. 1940 nc.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED) 1941 agent.sendNetworkCapabilities(nc) 1942 lp.addLinkAddress(LinkAddress("192.0.2.2/25")) 1943 lp.addRoute(RouteInfo(IpPrefix("192.0.2.0/25"), null /* nextHop */, ifName)) 1944 agent.sendLinkProperties(lp) 1945 1946 requestCallback.assertNoCallback() 1947 listenCallback.assertNoCallback() 1948 if (!expectCreatedImmediately) { 1949 agent.assertNoCallback() 1950 agent.markConnected() 1951 agent.expectCallback<OnNetworkCreated>() 1952 } else { 1953 agent.expectCallback<OnNetworkCreated>() 1954 agent.markConnected() 1955 } 1956 agent.expectPostConnectionCallbacks() 1957 1958 // onAvailable must be called only when the network connects, and no other callbacks may be 1959 // called before that happens. The callbacks report the state of the network as it was when 1960 // it connected, so they reflect the NC and LP changes made after registration. 1961 requestCallback.expect<Available>(network) 1962 listenCallback.expect<Available>(network) 1963 1964 requestCallback.expect<CapabilitiesChanged>(network) { it.caps.hasCapability( 1965 NET_CAPABILITY_TEMPORARILY_NOT_METERED 1966 ) } 1967 listenCallback.expect<CapabilitiesChanged>(network) { it.caps.hasCapability( 1968 NET_CAPABILITY_TEMPORARILY_NOT_METERED 1969 ) } 1970 1971 requestCallback.expect<LinkPropertiesChanged>(network) { it.lp.equals(lp) } 1972 listenCallback.expect<LinkPropertiesChanged>(network) { it.lp.equals(lp) } 1973 1974 requestCallback.expect<BlockedStatus>() 1975 listenCallback.expect<BlockedStatus>() 1976 1977 // Except for network validation, ensure no more callbacks are sent. 1978 requestCallback.expectCaps(network) { 1979 it.hasCapability(NET_CAPABILITY_VALIDATED) 1980 } 1981 listenCallback.expectCaps(network) { 1982 it.hasCapability(NET_CAPABILITY_VALIDATED) 1983 } 1984 unregister(agent) 1985 // Lost implicitly checks that no further callbacks happened after connect. 1986 requestCallback.expect<Lost>(network) 1987 listenCallback.expect<Lost>(network) 1988 assertNull(mCM.getLinkProperties(network)) 1989 } 1990 1991 @Test testNativeNetworkCreation_PhysicalNetworknull1992 fun testNativeNetworkCreation_PhysicalNetwork() { 1993 doTestNativeNetworkCreation( 1994 expectCreatedImmediately = SHOULD_CREATE_NETWORKS_IMMEDIATELY, 1995 intArrayOf(TRANSPORT_CELLULAR) 1996 ) 1997 } 1998 1999 @Test testNativeNetworkCreation_Vpnnull2000 fun testNativeNetworkCreation_Vpn() { 2001 // VPN networks are always created as soon as the agent is registered. 2002 doTestNativeNetworkCreation(expectCreatedImmediately = true, intArrayOf(TRANSPORT_VPN)) 2003 } 2004 2005 @Test(expected = IllegalStateException::class) testRegisterAgainnull2006 fun testRegisterAgain() { 2007 val agent = createNetworkAgent() 2008 agent.register() 2009 agent.unregister() 2010 agent.register() 2011 } 2012 2013 @Test testUnregisterBeforeRegisternull2014 fun testUnregisterBeforeRegister() { 2015 // For backward compatibility, this shouldn't crash. 2016 val agent = createNetworkAgent() 2017 agent.unregister() 2018 } 2019 } 2020