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