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.app.Instrumentation 19 import android.content.Context 20 import android.net.ConnectivityManager 21 import android.net.KeepalivePacketData 22 import android.net.LinkAddress 23 import android.net.LinkProperties 24 import android.net.Network 25 import android.net.NetworkAgent 26 import android.net.NetworkAgent.CMD_ADD_KEEPALIVE_PACKET_FILTER 27 import android.net.NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT 28 import android.net.NetworkAgent.CMD_REMOVE_KEEPALIVE_PACKET_FILTER 29 import android.net.NetworkAgent.CMD_REPORT_NETWORK_STATUS 30 import android.net.NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED 31 import android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE 32 import android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE 33 import android.net.NetworkAgent.INVALID_NETWORK 34 import android.net.NetworkAgent.VALID_NETWORK 35 import android.net.NetworkAgentConfig 36 import android.net.NetworkCapabilities 37 import android.net.NetworkProvider 38 import android.net.NetworkRequest 39 import android.net.SocketKeepalive 40 import android.net.StringNetworkSpecifier 41 import android.net.Uri 42 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnAddKeepalivePacketFilter 43 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnAutomaticReconnectDisabled 44 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnBandwidthUpdateRequested 45 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnNetworkUnwanted 46 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnRemoveKeepalivePacketFilter 47 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnSaveAcceptUnvalidated 48 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnSignalStrengthThresholdsUpdated 49 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnStartSocketKeepalive 50 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnStopSocketKeepalive 51 import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnValidationStatus 52 import android.os.Build 53 import android.os.Bundle 54 import android.os.Handler 55 import android.os.HandlerThread 56 import android.os.Looper 57 import android.os.Message 58 import android.os.Messenger 59 import androidx.test.InstrumentationRegistry 60 import androidx.test.runner.AndroidJUnit4 61 import com.android.internal.util.AsyncChannel 62 import com.android.net.module.util.ArrayTrackRecord 63 import com.android.testutils.DevSdkIgnoreRule 64 import com.android.testutils.RecorderCallback.CallbackEntry.Available 65 import com.android.testutils.RecorderCallback.CallbackEntry.Lost 66 import com.android.testutils.TestableNetworkCallback 67 import org.junit.After 68 import org.junit.Assert.assertArrayEquals 69 import org.junit.Assert.fail 70 import org.junit.Before 71 import org.junit.Rule 72 import org.junit.Test 73 import org.junit.runner.RunWith 74 import java.net.InetAddress 75 import java.time.Duration 76 import java.util.UUID 77 import kotlin.test.assertEquals 78 import kotlin.test.assertFailsWith 79 import kotlin.test.assertFalse 80 import kotlin.test.assertNotNull 81 import kotlin.test.assertNull 82 import kotlin.test.assertTrue 83 84 // This test doesn't really have a constraint on how fast the methods should return. If it's 85 // going to fail, it will simply wait forever, so setting a high timeout lowers the flake ratio 86 // without affecting the run time of successful runs. Thus, set a very high timeout. 87 private const val DEFAULT_TIMEOUT_MS = 5000L 88 // When waiting for a NetworkCallback to determine there was no timeout, waiting is the 89 // only possible thing (the relevant handler is the one in the real ConnectivityService, 90 // and then there is the Binder call), so have a short timeout for this as it will be 91 // exhausted every time. 92 private const val NO_CALLBACK_TIMEOUT = 200L 93 // Any legal score (0~99) for the test network would do, as it is going to be kept up by the 94 // requests filed by the test and should never match normal internet requests. 70 is the default 95 // score of Ethernet networks, it's as good a value as any other. 96 private const val TEST_NETWORK_SCORE = 70 97 private const val BETTER_NETWORK_SCORE = 75 98 private const val FAKE_NET_ID = 1098 99 private val instrumentation: Instrumentation 100 get() = InstrumentationRegistry.getInstrumentation() 101 private val context: Context 102 get() = InstrumentationRegistry.getContext() 103 private fun Message(what: Int, arg1: Int, arg2: Int, obj: Any?) = Message.obtain().also { 104 it.what = what 105 it.arg1 = arg1 106 it.arg2 = arg2 107 it.obj = obj 108 } 109 110 @RunWith(AndroidJUnit4::class) 111 class NetworkAgentTest { 112 @Rule @JvmField 113 val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.Q) 114 115 private val LOCAL_IPV4_ADDRESS = InetAddress.parseNumericAddress("192.0.2.1") 116 private val REMOTE_IPV4_ADDRESS = InetAddress.parseNumericAddress("192.0.2.2") 117 118 private val mCM = context.getSystemService(ConnectivityManager::class.java) 119 private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread") <lambda>null120 private val mFakeConnectivityService by lazy { FakeConnectivityService(mHandlerThread.looper) } 121 122 private class Provider(context: Context, looper: Looper) : 123 NetworkProvider(context, looper, "NetworkAgentTest NetworkProvider") 124 125 private val agentsToCleanUp = mutableListOf<NetworkAgent>() 126 private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>() 127 128 @Before setUpnull129 fun setUp() { 130 instrumentation.getUiAutomation().adoptShellPermissionIdentity() 131 mHandlerThread.start() 132 } 133 134 @After tearDownnull135 fun tearDown() { 136 agentsToCleanUp.forEach { it.unregister() } 137 callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) } 138 mHandlerThread.quitSafely() 139 instrumentation.getUiAutomation().dropShellPermissionIdentity() 140 } 141 142 /** 143 * A fake that helps simulating ConnectivityService talking to a harnessed agent. 144 * This fake only supports speaking to one harnessed agent at a time because it 145 * only keeps track of one async channel. 146 */ 147 private class FakeConnectivityService(looper: Looper) { 148 private val CMD_EXPECT_DISCONNECT = 1 149 private var disconnectExpected = false 150 private val msgHistory = ArrayTrackRecord<Message>().newReadHead() 151 private val asyncChannel = AsyncChannel() 152 private val handler = object : Handler(looper) { handleMessagenull153 override fun handleMessage(msg: Message) { 154 msgHistory.add(Message.obtain(msg)) // make a copy as the original will be recycled 155 when (msg.what) { 156 CMD_EXPECT_DISCONNECT -> disconnectExpected = true 157 AsyncChannel.CMD_CHANNEL_HALF_CONNECTED -> 158 asyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION) 159 AsyncChannel.CMD_CHANNEL_DISCONNECTED -> 160 if (!disconnectExpected) { 161 fail("Agent unexpectedly disconnected") 162 } else { 163 disconnectExpected = false 164 } 165 } 166 } 167 } 168 connectnull169 fun connect(agentMsngr: Messenger) = asyncChannel.connect(context, handler, agentMsngr) 170 171 fun disconnect() = asyncChannel.disconnect() 172 173 fun sendMessage(what: Int, arg1: Int = 0, arg2: Int = 0, obj: Any? = null) = 174 asyncChannel.sendMessage(Message(what, arg1, arg2, obj)) 175 176 fun expectMessage(what: Int) = 177 assertNotNull(msgHistory.poll(DEFAULT_TIMEOUT_MS) { it.what == what }) 178 willExpectDisconnectOncenull179 fun willExpectDisconnectOnce() = handler.sendEmptyMessage(CMD_EXPECT_DISCONNECT) 180 } 181 182 private open class TestableNetworkAgent( 183 looper: Looper, 184 val nc: NetworkCapabilities, 185 val lp: LinkProperties, 186 conf: NetworkAgentConfig 187 ) : NetworkAgent(context, looper, TestableNetworkAgent::class.java.simpleName /* tag */, 188 nc, lp, TEST_NETWORK_SCORE, conf, Provider(context, looper)) { 189 private val history = ArrayTrackRecord<CallbackEntry>().newReadHead() 190 191 sealed class CallbackEntry { 192 object OnBandwidthUpdateRequested : CallbackEntry() 193 object OnNetworkUnwanted : CallbackEntry() 194 data class OnAddKeepalivePacketFilter( 195 val slot: Int, 196 val packet: KeepalivePacketData 197 ) : CallbackEntry() 198 data class OnRemoveKeepalivePacketFilter(val slot: Int) : CallbackEntry() 199 data class OnStartSocketKeepalive( 200 val slot: Int, 201 val interval: Int, 202 val packet: KeepalivePacketData 203 ) : CallbackEntry() 204 data class OnStopSocketKeepalive(val slot: Int) : CallbackEntry() 205 data class OnSaveAcceptUnvalidated(val accept: Boolean) : CallbackEntry() 206 object OnAutomaticReconnectDisabled : CallbackEntry() 207 data class OnValidationStatus(val status: Int, val uri: Uri?) : CallbackEntry() 208 data class OnSignalStrengthThresholdsUpdated(val thresholds: IntArray) : CallbackEntry() 209 } 210 211 fun getName(): String? = (nc.getNetworkSpecifier() as? StringNetworkSpecifier)?.specifier 212 213 override fun onBandwidthUpdateRequested() { 214 history.add(OnBandwidthUpdateRequested) 215 } 216 217 override fun onNetworkUnwanted() { 218 history.add(OnNetworkUnwanted) 219 } 220 221 override fun onAddKeepalivePacketFilter(slot: Int, packet: KeepalivePacketData) { 222 history.add(OnAddKeepalivePacketFilter(slot, packet)) 223 } 224 225 override fun onRemoveKeepalivePacketFilter(slot: Int) { 226 history.add(OnRemoveKeepalivePacketFilter(slot)) 227 } 228 229 override fun onStartSocketKeepalive( 230 slot: Int, 231 interval: Duration, 232 packet: KeepalivePacketData 233 ) { 234 history.add(OnStartSocketKeepalive(slot, interval.seconds.toInt(), packet)) 235 } 236 237 override fun onStopSocketKeepalive(slot: Int) { 238 history.add(OnStopSocketKeepalive(slot)) 239 } 240 241 override fun onSaveAcceptUnvalidated(accept: Boolean) { 242 history.add(OnSaveAcceptUnvalidated(accept)) 243 } 244 245 override fun onAutomaticReconnectDisabled() { 246 history.add(OnAutomaticReconnectDisabled) 247 } 248 249 override fun onSignalStrengthThresholdsUpdated(thresholds: IntArray) { 250 history.add(OnSignalStrengthThresholdsUpdated(thresholds)) 251 } 252 253 fun expectEmptySignalStrengths() { 254 expectCallback<OnSignalStrengthThresholdsUpdated>().let { 255 // intArrayOf() without arguments makes an empty array 256 assertArrayEquals(intArrayOf(), it.thresholds) 257 } 258 } 259 260 override fun onValidationStatus(status: Int, uri: Uri?) { 261 history.add(OnValidationStatus(status, uri)) 262 } 263 264 // Expects the initial validation event that always occurs immediately after registering 265 // a NetworkAgent whose network does not require validation (which test networks do 266 // not, since they lack the INTERNET capability). It always contains the default argument 267 // for the URI. 268 fun expectNoInternetValidationStatus() = expectCallback<OnValidationStatus>().let { 269 assertEquals(it.status, VALID_NETWORK) 270 // The returned Uri is parsed from the empty string, which means it's an 271 // instance of the (private) Uri.StringUri. There are no real good ways 272 // to check this, the least bad is to just convert it to a string and 273 // make sure it's empty. 274 assertEquals("", it.uri.toString()) 275 } 276 277 inline fun <reified T : CallbackEntry> expectCallback(): T { 278 val foundCallback = history.poll(DEFAULT_TIMEOUT_MS) 279 assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback") 280 return foundCallback 281 } 282 283 fun assertNoCallback() { 284 assertTrue(waitForIdle(DEFAULT_TIMEOUT_MS), 285 "Handler didn't became idle after ${DEFAULT_TIMEOUT_MS}ms") 286 assertNull(history.peek()) 287 } 288 } 289 requestNetworknull290 private fun requestNetwork(request: NetworkRequest, callback: TestableNetworkCallback) { 291 mCM.requestNetwork(request, callback) 292 callbacksToCleanUp.add(callback) 293 } 294 registerNetworkCallbacknull295 private fun registerNetworkCallback( 296 request: NetworkRequest, 297 callback: TestableNetworkCallback 298 ) { 299 mCM.registerNetworkCallback(request, callback) 300 callbacksToCleanUp.add(callback) 301 } 302 createNetworkAgentnull303 private fun createNetworkAgent(name: String? = null): TestableNetworkAgent { 304 val nc = NetworkCapabilities().apply { 305 addTransportType(NetworkCapabilities.TRANSPORT_TEST) 306 removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 307 removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 308 addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) 309 addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) 310 addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 311 if (null != name) { 312 setNetworkSpecifier(StringNetworkSpecifier(name)) 313 } 314 } 315 val lp = LinkProperties().apply { 316 addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 0)) 317 } 318 val config = NetworkAgentConfig.Builder().build() 319 return TestableNetworkAgent(mHandlerThread.looper, nc, lp, config).also { 320 agentsToCleanUp.add(it) 321 } 322 } 323 createConnectedNetworkAgentnull324 private fun createConnectedNetworkAgent(name: String? = null): 325 Pair<TestableNetworkAgent, TestableNetworkCallback> { 326 val request: NetworkRequest = NetworkRequest.Builder() 327 .clearCapabilities() 328 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 329 .build() 330 val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 331 requestNetwork(request, callback) 332 val agent = createNetworkAgent(name) 333 agent.register() 334 agent.markConnected() 335 return agent to callback 336 } 337 <lambda>null338 private fun createNetworkAgentWithFakeCS() = createNetworkAgent().also { 339 mFakeConnectivityService.connect(it.registerForTest(Network(FAKE_NET_ID))) 340 } 341 342 @Test testConnectAndUnregisternull343 fun testConnectAndUnregister() { 344 val (agent, callback) = createConnectedNetworkAgent() 345 callback.expectAvailableThenValidatedCallbacks(agent.network) 346 agent.expectEmptySignalStrengths() 347 agent.expectNoInternetValidationStatus() 348 agent.unregister() 349 callback.expectCallback<Lost>(agent.network) 350 agent.expectCallback<OnNetworkUnwanted>() 351 assertFailsWith<IllegalStateException>("Must not be able to register an agent twice") { 352 agent.register() 353 } 354 } 355 356 @Test testOnBandwidthUpdateRequestednull357 fun testOnBandwidthUpdateRequested() { 358 val (agent, callback) = createConnectedNetworkAgent() 359 callback.expectAvailableThenValidatedCallbacks(agent.network) 360 agent.expectEmptySignalStrengths() 361 agent.expectNoInternetValidationStatus() 362 mCM.requestBandwidthUpdate(agent.network) 363 agent.expectCallback<OnBandwidthUpdateRequested>() 364 agent.unregister() 365 } 366 367 @Test testSignalStrengthThresholdsnull368 fun testSignalStrengthThresholds() { 369 val thresholds = intArrayOf(30, 50, 65) 370 val callbacks = thresholds.map { strength -> 371 val request = NetworkRequest.Builder() 372 .clearCapabilities() 373 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 374 .setSignalStrength(strength) 375 .build() 376 TestableNetworkCallback(DEFAULT_TIMEOUT_MS).also { 377 registerNetworkCallback(request, it) 378 } 379 } 380 createConnectedNetworkAgent().let { (agent, callback) -> 381 callback.expectAvailableThenValidatedCallbacks(agent.network) 382 agent.expectCallback<OnSignalStrengthThresholdsUpdated>().let { 383 assertArrayEquals(it.thresholds, thresholds) 384 } 385 agent.expectNoInternetValidationStatus() 386 387 // Send signal strength and check that the callbacks are called appropriately. 388 val nc = NetworkCapabilities(agent.nc) 389 nc.setSignalStrength(20) 390 agent.sendNetworkCapabilities(nc) 391 callbacks.forEach { it.assertNoCallback(NO_CALLBACK_TIMEOUT) } 392 393 nc.setSignalStrength(40) 394 agent.sendNetworkCapabilities(nc) 395 callbacks[0].expectAvailableCallbacks(agent.network) 396 callbacks[1].assertNoCallback(NO_CALLBACK_TIMEOUT) 397 callbacks[2].assertNoCallback(NO_CALLBACK_TIMEOUT) 398 399 nc.setSignalStrength(80) 400 agent.sendNetworkCapabilities(nc) 401 callbacks[0].expectCapabilitiesThat(agent.network) { it.signalStrength == 80 } 402 callbacks[1].expectAvailableCallbacks(agent.network) 403 callbacks[2].expectAvailableCallbacks(agent.network) 404 405 nc.setSignalStrength(55) 406 agent.sendNetworkCapabilities(nc) 407 callbacks[0].expectCapabilitiesThat(agent.network) { it.signalStrength == 55 } 408 callbacks[1].expectCapabilitiesThat(agent.network) { it.signalStrength == 55 } 409 callbacks[2].expectCallback<Lost>(agent.network) 410 } 411 callbacks.forEach { 412 mCM.unregisterNetworkCallback(it) 413 } 414 } 415 416 @Test agentnull417 fun testSocketKeepalive(): Unit = createNetworkAgentWithFakeCS().let { agent -> 418 val packet = object : KeepalivePacketData( 419 LOCAL_IPV4_ADDRESS /* srcAddress */, 1234 /* srcPort */, 420 REMOTE_IPV4_ADDRESS /* dstAddress */, 4567 /* dstPort */, 421 ByteArray(100 /* size */) { it.toByte() /* init */ }) {} 422 val slot = 4 423 val interval = 37 424 425 mFakeConnectivityService.sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, 426 arg1 = slot, obj = packet) 427 mFakeConnectivityService.sendMessage(CMD_START_SOCKET_KEEPALIVE, 428 arg1 = slot, arg2 = interval, obj = packet) 429 430 agent.expectCallback<OnAddKeepalivePacketFilter>().let { 431 assertEquals(it.slot, slot) 432 assertEquals(it.packet, packet) 433 } 434 agent.expectCallback<OnStartSocketKeepalive>().let { 435 assertEquals(it.slot, slot) 436 assertEquals(it.interval, interval) 437 assertEquals(it.packet, packet) 438 } 439 440 agent.assertNoCallback() 441 442 // Check that when the agent sends a keepalive event, ConnectivityService receives the 443 // expected message. 444 agent.sendSocketKeepaliveEvent(slot, SocketKeepalive.ERROR_UNSUPPORTED) 445 mFakeConnectivityService.expectMessage(NetworkAgent.EVENT_SOCKET_KEEPALIVE).let() { 446 assertEquals(slot, it.arg1) 447 assertEquals(SocketKeepalive.ERROR_UNSUPPORTED, it.arg2) 448 } 449 450 mFakeConnectivityService.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, arg1 = slot) 451 mFakeConnectivityService.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, arg1 = slot) 452 agent.expectCallback<OnStopSocketKeepalive>().let { 453 assertEquals(it.slot, slot) 454 } 455 agent.expectCallback<OnRemoveKeepalivePacketFilter>().let { 456 assertEquals(it.slot, slot) 457 } 458 } 459 460 @Test agentnull461 fun testSendUpdates(): Unit = createConnectedNetworkAgent().let { (agent, callback) -> 462 callback.expectAvailableThenValidatedCallbacks(agent.network) 463 agent.expectEmptySignalStrengths() 464 agent.expectNoInternetValidationStatus() 465 val ifaceName = "adhocIface" 466 val lp = LinkProperties(agent.lp) 467 lp.setInterfaceName(ifaceName) 468 agent.sendLinkProperties(lp) 469 callback.expectLinkPropertiesThat(agent.network) { 470 it.getInterfaceName() == ifaceName 471 } 472 val nc = NetworkCapabilities(agent.nc) 473 nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) 474 agent.sendNetworkCapabilities(nc) 475 callback.expectCapabilitiesThat(agent.network) { 476 it.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) 477 } 478 } 479 480 @Test testSendScorenull481 fun testSendScore() { 482 // This test will create two networks and check that the one with the stronger 483 // score wins out for a request that matches them both. 484 // First create requests to make sure both networks are kept up, using the 485 // specifier so they are specific to each network 486 val name1 = UUID.randomUUID().toString() 487 val name2 = UUID.randomUUID().toString() 488 val request1 = NetworkRequest.Builder() 489 .clearCapabilities() 490 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 491 .setNetworkSpecifier(StringNetworkSpecifier(name1)) 492 .build() 493 val request2 = NetworkRequest.Builder() 494 .clearCapabilities() 495 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 496 .setNetworkSpecifier(StringNetworkSpecifier(name2)) 497 .build() 498 val callback1 = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 499 val callback2 = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 500 requestNetwork(request1, callback1) 501 requestNetwork(request2, callback2) 502 503 // Then file the interesting request 504 val request = NetworkRequest.Builder() 505 .clearCapabilities() 506 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 507 .build() 508 val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 509 requestNetwork(request, callback) 510 511 // Connect the first Network 512 createConnectedNetworkAgent(name1).let { (agent1, _) -> 513 callback.expectAvailableThenValidatedCallbacks(agent1.network) 514 // Upgrade agent1 to a better score so that there is no ambiguity when 515 // agent2 connects that agent1 is still better 516 agent1.sendNetworkScore(BETTER_NETWORK_SCORE - 1) 517 // Connect the second agent 518 createConnectedNetworkAgent(name2).let { (agent2, _) -> 519 agent2.markConnected() 520 // The callback should not see anything yet 521 callback.assertNoCallback(NO_CALLBACK_TIMEOUT) 522 // Now update the score and expect the callback now prefers agent2 523 agent2.sendNetworkScore(BETTER_NETWORK_SCORE) 524 callback.expectCallback<Available>(agent2.network) 525 } 526 } 527 528 // tearDown() will unregister the requests and agents 529 } 530 531 @Test testSetAcceptUnvalidatednull532 fun testSetAcceptUnvalidated() { 533 createNetworkAgentWithFakeCS().let { agent -> 534 mFakeConnectivityService.sendMessage(CMD_SAVE_ACCEPT_UNVALIDATED, 1) 535 agent.expectCallback<OnSaveAcceptUnvalidated>().let { 536 assertTrue(it.accept) 537 } 538 agent.assertNoCallback() 539 } 540 } 541 542 @Test testSetAcceptUnvalidatedPreventAutomaticReconnectnull543 fun testSetAcceptUnvalidatedPreventAutomaticReconnect() { 544 createNetworkAgentWithFakeCS().let { agent -> 545 mFakeConnectivityService.sendMessage(CMD_SAVE_ACCEPT_UNVALIDATED, 0) 546 mFakeConnectivityService.sendMessage(CMD_PREVENT_AUTOMATIC_RECONNECT) 547 agent.expectCallback<OnSaveAcceptUnvalidated>().let { 548 assertFalse(it.accept) 549 } 550 agent.expectCallback<OnAutomaticReconnectDisabled>() 551 agent.assertNoCallback() 552 // When automatic reconnect is turned off, the network is torn down and 553 // ConnectivityService sends a disconnect. This in turn causes the agent 554 // to send a DISCONNECTED message to CS. 555 mFakeConnectivityService.willExpectDisconnectOnce() 556 mFakeConnectivityService.disconnect() 557 mFakeConnectivityService.expectMessage(AsyncChannel.CMD_CHANNEL_DISCONNECTED) 558 agent.expectCallback<OnNetworkUnwanted>() 559 } 560 } 561 562 @Test testPreventAutomaticReconnectnull563 fun testPreventAutomaticReconnect() { 564 createNetworkAgentWithFakeCS().let { agent -> 565 mFakeConnectivityService.sendMessage(CMD_PREVENT_AUTOMATIC_RECONNECT) 566 agent.expectCallback<OnAutomaticReconnectDisabled>() 567 agent.assertNoCallback() 568 mFakeConnectivityService.willExpectDisconnectOnce() 569 mFakeConnectivityService.disconnect() 570 mFakeConnectivityService.expectMessage(AsyncChannel.CMD_CHANNEL_DISCONNECTED) 571 agent.expectCallback<OnNetworkUnwanted>() 572 } 573 } 574 575 @Test agentnull576 fun testValidationStatus() = createNetworkAgentWithFakeCS().let { agent -> 577 val uri = Uri.parse("http://www.google.com") 578 val bundle = Bundle().apply { 579 putString(NetworkAgent.REDIRECT_URL_KEY, uri.toString()) 580 } 581 mFakeConnectivityService.sendMessage(CMD_REPORT_NETWORK_STATUS, 582 arg1 = VALID_NETWORK, obj = bundle) 583 agent.expectCallback<OnValidationStatus>().let { 584 assertEquals(it.status, VALID_NETWORK) 585 assertEquals(it.uri, uri) 586 } 587 588 mFakeConnectivityService.sendMessage(CMD_REPORT_NETWORK_STATUS, 589 arg1 = INVALID_NETWORK, obj = Bundle()) 590 agent.expectCallback<OnValidationStatus>().let { 591 assertEquals(it.status, INVALID_NETWORK) 592 assertNull(it.uri) 593 } 594 } 595 596 @Test testTemporarilyUnmeteredCapabilitynull597 fun testTemporarilyUnmeteredCapability() { 598 // This test will create a networks with/without NET_CAPABILITY_TEMPORARILY_NOT_METERED 599 // and check that the callback reflects the capability changes. 600 // First create a request to make sure the network is kept up 601 val request1 = NetworkRequest.Builder() 602 .clearCapabilities() 603 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 604 .build() 605 val callback1 = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS).also { 606 registerNetworkCallback(request1, it) 607 } 608 requestNetwork(request1, callback1) 609 610 // Then file the interesting request 611 val request = NetworkRequest.Builder() 612 .clearCapabilities() 613 .addTransportType(NetworkCapabilities.TRANSPORT_TEST) 614 .build() 615 val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) 616 requestNetwork(request, callback) 617 618 // Connect the network 619 createConnectedNetworkAgent().let { (agent, _) -> 620 callback.expectAvailableThenValidatedCallbacks(agent.network) 621 622 // Send TEMP_NOT_METERED and check that the callback is called appropriately. 623 val nc1 = NetworkCapabilities(agent.nc) 624 .addCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED) 625 agent.sendNetworkCapabilities(nc1) 626 callback.expectCapabilitiesThat(agent.network) { 627 it.hasCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED) 628 } 629 630 // Remove TEMP_NOT_METERED and check that the callback is called appropriately. 631 val nc2 = NetworkCapabilities(agent.nc) 632 .removeCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED) 633 agent.sendNetworkCapabilities(nc2) 634 callback.expectCapabilitiesThat(agent.network) { 635 !it.hasCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED) 636 } 637 } 638 639 // tearDown() will unregister the requests and agents 640 } 641 } 642