1 /*
2 * Copyright (C) 2023 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
17 package com.android.server
18
19 import android.app.AlarmManager
20 import android.app.AppOpsManager
21 import android.content.BroadcastReceiver
22 import android.content.Context
23 import android.content.Intent
24 import android.content.IntentFilter
25 import android.content.pm.PackageManager.PERMISSION_GRANTED
26 import android.content.pm.UserInfo
27 import android.content.res.Resources
28 import android.net.ConnectivityManager
29 import android.net.INetd
30 import android.net.INetd.PERMISSION_INTERNET
31 import android.net.InetAddresses
32 import android.net.LinkProperties
33 import android.net.LocalNetworkConfig
34 import android.net.NetworkAgentConfig
35 import android.net.NetworkCapabilities
36 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
37 import android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH
38 import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
39 import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
40 import android.net.NetworkCapabilities.TRANSPORT_TEST
41 import android.net.NetworkCapabilities.TRANSPORT_VPN
42 import android.net.NetworkCapabilities.TRANSPORT_WIFI
43 import android.net.NetworkPolicyManager
44 import android.net.NetworkProvider
45 import android.net.NetworkScore
46 import android.net.PacProxyManager
47 import android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK
48 import android.net.networkstack.NetworkStackClientBase
49 import android.os.BatteryStatsManager
50 import android.os.Bundle
51 import android.os.Handler
52 import android.os.HandlerThread
53 import android.os.Process
54 import android.os.UserHandle
55 import android.os.UserManager
56 import android.permission.PermissionManager.PermissionResult
57 import android.telephony.SubscriptionManager
58 import android.telephony.TelephonyManager
59 import android.testing.TestableContext
60 import androidx.test.platform.app.InstrumentationRegistry
61 import com.android.internal.app.IBatteryStats
62 import com.android.internal.util.test.BroadcastInterceptingContext
63 import com.android.modules.utils.build.SdkLevel
64 import com.android.net.module.util.ArrayTrackRecord
65 import com.android.networkstack.apishim.common.UnsupportedApiLevelException
66 import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker
67 import com.android.server.connectivity.CarrierPrivilegeAuthenticator
68 import com.android.server.connectivity.ClatCoordinator
69 import com.android.server.connectivity.ConnectivityFlags
70 import com.android.server.connectivity.MulticastRoutingCoordinatorService
71 import com.android.server.connectivity.MultinetworkPolicyTracker
72 import com.android.server.connectivity.MultinetworkPolicyTrackerTestDependencies
73 import com.android.server.connectivity.NetworkRequestStateStatsMetrics
74 import com.android.server.connectivity.ProxyTracker
75 import com.android.server.connectivity.SatelliteAccessController
76 import com.android.testutils.visibleOnHandlerThread
77 import com.android.testutils.waitForIdle
78 import java.util.concurrent.Executors
79 import java.util.concurrent.LinkedBlockingQueue
80 import java.util.concurrent.TimeUnit
81 import java.util.function.BiConsumer
82 import java.util.function.Consumer
83 import kotlin.annotation.AnnotationRetention.RUNTIME
84 import kotlin.annotation.AnnotationTarget.FUNCTION
85 import kotlin.test.assertNotNull
86 import kotlin.test.assertNull
87 import kotlin.test.fail
88 import org.junit.After
89 import org.junit.Before
90 import org.junit.Rule
91 import org.junit.rules.TestName
92 import org.mockito.AdditionalAnswers.delegatesTo
93 import org.mockito.ArgumentMatchers.anyInt
94 import org.mockito.Mockito.doAnswer
95 import org.mockito.Mockito.doReturn
96 import org.mockito.Mockito.mock
97
98 internal const val HANDLER_TIMEOUT_MS = 2_000L
99 internal const val BROADCAST_TIMEOUT_MS = 3_000L
100 internal const val TEST_PACKAGE_NAME = "com.android.test.package"
101 internal const val WIFI_WOL_IFNAME = "test_wlan_wol"
102 internal val LOCAL_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1")
103
104 open class FromS<Type>(val value: Type)
105
106 internal const val VERSION_UNMOCKED = -1
107 internal const val VERSION_R = 1
108 internal const val VERSION_S = 2
109 internal const val VERSION_T = 3
110 internal const val VERSION_U = 4
111 internal const val VERSION_V = 5
112 internal const val VERSION_MAX = VERSION_V
113
114 internal const val CALLING_UID_UNMOCKED = Process.INVALID_UID
115
getLegacyTypenull116 private fun NetworkCapabilities.getLegacyType() =
117 when (transportTypes.getOrElse(0) { TRANSPORT_WIFI }) {
118 TRANSPORT_BLUETOOTH -> ConnectivityManager.TYPE_BLUETOOTH
119 TRANSPORT_CELLULAR -> ConnectivityManager.TYPE_MOBILE
120 TRANSPORT_ETHERNET -> ConnectivityManager.TYPE_ETHERNET
121 TRANSPORT_TEST -> ConnectivityManager.TYPE_TEST
122 TRANSPORT_VPN -> ConnectivityManager.TYPE_VPN
123 TRANSPORT_WIFI -> ConnectivityManager.TYPE_WIFI
124 else -> ConnectivityManager.TYPE_NONE
125 }
126
127 /**
128 * Base class for tests testing ConnectivityService and its satellites.
129 *
130 * This class sets up a ConnectivityService running locally in the test.
131 */
132 // TODO (b/272685721) : make ConnectivityServiceTest smaller and faster by moving the setup
133 // parts into this class and moving the individual tests to multiple separate classes.
134 open class CSTest {
135 @get:Rule
136 val testNameRule = TestName()
137
138 companion object {
139 val CSTestExecutor = Executors.newSingleThreadExecutor()
140 }
141
142 init {
143 if (!SdkLevel.isAtLeastS()) {
144 throw UnsupportedApiLevelException(
145 "CSTest subclasses must be annotated to only " +
146 "run on S+, e.g. @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)"
147 )
148 }
149 }
150
151 val instrumentationContext =
152 TestableContext(InstrumentationRegistry.getInstrumentation().context)
153 val context = CSContext(instrumentationContext)
154
155 // See constructor for default-enabled features. All queried features must be either enabled
156 // or disabled, because the test can't hold READ_DEVICE_CONFIG and device config utils query
157 // permissions using static contexts.
<lambda>null158 val enabledFeatures = HashMap<String, Boolean>().also {
159 it[ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER] = true
160 it[ConnectivityFlags.REQUEST_RESTRICTED_WIFI] = true
161 it[ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION] = true
162 it[ConnectivityService.ALLOW_SYSUI_CONNECTIVITY_REPORTS] = true
163 it[ConnectivityService.ALLOW_SATALLITE_NETWORK_FALLBACK] = true
164 it[ConnectivityFlags.INGRESS_TO_VPN_ADDRESS_FILTERING] = true
165 it[ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN] = true
166 it[ConnectivityFlags.DELAY_DESTROY_SOCKETS] = true
167 it[ConnectivityFlags.USE_DECLARED_METHODS_FOR_CALLBACKS] = true
168 }
setFeatureEnablednull169 fun setFeatureEnabled(flag: String, enabled: Boolean) = enabledFeatures.set(flag, enabled)
170
171 // When adding new members, consider if it's not better to build the object in CSTestHelpers
172 // to keep this file clean of implementation details. Generally, CSTestHelpers should only
173 // need changes when new details of instrumentation are needed.
174 val contentResolver = makeMockContentResolver(context)
175
176 val PRIMARY_USER = 0
177 val PRIMARY_USER_INFO = UserInfo(
178 PRIMARY_USER,
179 "", // name
180 UserInfo.FLAG_PRIMARY
181 )
182 val PRIMARY_USER_HANDLE = UserHandle(PRIMARY_USER)
183 val userManager = makeMockUserManager(PRIMARY_USER_INFO, PRIMARY_USER_HANDLE)
184 val activityManager = makeActivityManager()
185
186 val networkStack = mock<NetworkStackClientBase>()
187 val csHandlerThread = HandlerThread("CSTestHandler")
188 val sysResources = mock<Resources>().also { initMockedResources(it) }
189 val packageManager = makeMockPackageManager(instrumentationContext)
190 val connResources = makeMockConnResources(sysResources, packageManager)
191
192 val netd = mock<INetd>()
<lambda>null193 val bpfNetMaps = mock<BpfNetMaps>().also {
194 doReturn(PERMISSION_INTERNET).`when`(it).getNetPermForUid(anyInt())
195 }
196 val clatCoordinator = mock<ClatCoordinator>()
197 val networkRequestStateStatsMetrics = mock<NetworkRequestStateStatsMetrics>()
198 val proxyTracker = ProxyTracker(
199 context,
200 mock<Handler>(),
201 16 // EVENT_PROXY_HAS_CHANGED
202 )
203 val systemConfigManager = makeMockSystemConfigManager()
204 val batteryStats = mock<IBatteryStats>()
205 val batteryManager = BatteryStatsManager(batteryStats)
206 val appOpsManager = mock<AppOpsManager>()
<lambda>null207 val telephonyManager = mock<TelephonyManager>().also {
208 doReturn(true).`when`(it).isDataCapable()
209 }
210 val subscriptionManager = mock<SubscriptionManager>()
211
212 val multicastRoutingCoordinatorService = mock<MulticastRoutingCoordinatorService>()
213 val satelliteAccessController = mock<SatelliteAccessController>()
214 val destroySocketsWrapper = mock<DestroySocketsWrapper>()
215
216 val deps = CSDeps()
217
218 // Initializations that start threads are done from setUp to avoid thread leak
219 lateinit var alarmHandlerThread: HandlerThread
220 lateinit var alarmManager: AlarmManager
221 lateinit var service: ConnectivityService
222 lateinit var cm: ConnectivityManager
223 lateinit var csHandler: Handler
224
225 // Tests can use this annotation to set flag values before constructing ConnectivityService
226 // e.g. @FeatureFlags([Flag(flagName1, true/false), Flag(flagName2, true/false)])
227 @Retention(RUNTIME)
228 @Target(FUNCTION)
229 annotation class FeatureFlags(val flags: Array<Flag>)
230
231 @Retention(RUNTIME)
232 @Target(FUNCTION)
233 annotation class Flag(val name: String, val enabled: Boolean)
234
235 @Before
setUpnull236 fun setUp() {
237 // Set feature flags before constructing ConnectivityService
238 val testMethodName = testNameRule.methodName
239 try {
240 val testMethod = this::class.java.getMethod(testMethodName)
241 val featureFlags = testMethod.getAnnotation(FeatureFlags::class.java)
242 if (featureFlags != null) {
243 for (flag in featureFlags.flags) {
244 setFeatureEnabled(flag.name, flag.enabled)
245 }
246 }
247 } catch (ignored: NoSuchMethodException) {
248 // This is expected for parameterized tests
249 }
250
251 alarmHandlerThread = HandlerThread("TestAlarmManager").also { it.start() }
252 alarmManager = makeMockAlarmManager(alarmHandlerThread)
253 service = makeConnectivityService(context, netd, deps).also { it.systemReadyInternal() }
254 cm = ConnectivityManager(context, service)
255 // csHandler initialization must be after makeConnectivityService since ConnectivityService
256 // constructor starts csHandlerThread
257 csHandler = Handler(csHandlerThread.looper)
258 }
259
260 @After
tearDownnull261 fun tearDown() {
262 csHandlerThread.quitSafely()
263 csHandlerThread.join()
264 alarmHandlerThread.quitSafely()
265 alarmHandlerThread.join()
266 }
267
268 // Class to be mocked and used to verify destroy sockets methods call
269 open inner class DestroySocketsWrapper {
destroyLiveTcpSocketsByOwnerUidsnull270 open fun destroyLiveTcpSocketsByOwnerUids(ownerUids: Set<Int>) {}
271 }
272
273 inner class CSDeps : ConnectivityService.Dependencies() {
getResourcesnull274 override fun getResources(ctx: Context) = connResources
275 override fun getBpfNetMaps(context: Context, netd: INetd) = this@CSTest.bpfNetMaps
276 override fun getClatCoordinator(netd: INetd?) = this@CSTest.clatCoordinator
277 override fun getNetworkStack() = this@CSTest.networkStack
278
279 override fun makeHandlerThread(tag: String) = csHandlerThread
280 override fun makeProxyTracker(context: Context, connServiceHandler: Handler) = proxyTracker
281 override fun makeMulticastRoutingCoordinatorService(handler: Handler) =
282 this@CSTest.multicastRoutingCoordinatorService
283
284 override fun makeCarrierPrivilegeAuthenticator(
285 context: Context,
286 tm: TelephonyManager,
287 requestRestrictedWifiEnabled: Boolean,
288 listener: BiConsumer<Int, Int>,
289 handler: Handler
290 ) = if (SdkLevel.isAtLeastT()) mock<CarrierPrivilegeAuthenticator>() else null
291
292 var satelliteNetworkFallbackUidUpdate: Consumer<Set<Int>>? = null
293 override fun makeSatelliteAccessController(
294 context: Context,
295 updateSatelliteNetworkFallackUid: Consumer<Set<Int>>?,
296 csHandlerThread: Handler
297 ): SatelliteAccessController? {
298 satelliteNetworkFallbackUidUpdate = updateSatelliteNetworkFallackUid
299 return satelliteAccessController
300 }
301
302 private inner class AOOKTDeps(c: Context) : AutomaticOnOffKeepaliveTracker.Dependencies(c) {
isTetheringFeatureNotChickenedOutnull303 override fun isTetheringFeatureNotChickenedOut(name: String): Boolean {
304 return isFeatureEnabled(context, name)
305 }
306 }
makeAutomaticOnOffKeepaliveTrackernull307 override fun makeAutomaticOnOffKeepaliveTracker(c: Context, h: Handler) =
308 AutomaticOnOffKeepaliveTracker(c, h, AOOKTDeps(c))
309
310 override fun makeMultinetworkPolicyTracker(c: Context, h: Handler, r: Runnable) =
311 MultinetworkPolicyTracker(
312 c,
313 h,
314 r,
315 MultinetworkPolicyTrackerTestDependencies(connResources.get())
316 )
317
318 override fun makeNetworkRequestStateStatsMetrics(c: Context) =
319 this@CSTest.networkRequestStateStatsMetrics
320
321 // All queried features must be mocked, because the test cannot hold the
322 // READ_DEVICE_CONFIG permission and device config utils use static methods for
323 // checking permissions.
324 override fun isFeatureEnabled(context: Context?, name: String?) =
325 enabledFeatures[name] ?: fail("Unmocked feature $name, see CSTest.enabledFeatures")
326 override fun isFeatureNotChickenedOut(context: Context?, name: String?) =
327 enabledFeatures[name] ?: fail("Unmocked feature $name, see CSTest.enabledFeatures")
328
329 // Mocked change IDs
330 private val enabledChangeIds = arrayListOf(ENABLE_MATCH_LOCAL_NETWORK)
331 fun setChangeIdEnabled(enabled: Boolean, changeId: Long) {
332 // enabledChangeIds is read on the handler thread and maybe the test thread, so
333 // make sure both threads see it before continuing.
334 visibleOnHandlerThread(csHandler) {
335 if (enabled) {
336 enabledChangeIds.add(changeId)
337 } else {
338 enabledChangeIds.remove(changeId)
339 }
340 }
341 }
342
isChangeEnablednull343 override fun isChangeEnabled(changeId: Long, pkg: String, user: UserHandle) =
344 changeId in enabledChangeIds
345 override fun isChangeEnabled(changeId: Long, uid: Int) =
346 changeId in enabledChangeIds
347
348 // In AOSP, build version codes can't always distinguish between some versions (e.g. at the
349 // time of this writing U == V). Define custom ones.
350 private var sdkLevel = VERSION_UNMOCKED
351 private val isSdkUnmocked get() = sdkLevel == VERSION_UNMOCKED
352
353 fun setBuildSdk(sdkLevel: Int) {
354 require(sdkLevel <= VERSION_MAX) {
355 "setBuildSdk must not be called with Build.VERSION constants but " +
356 "CsTest.VERSION_* constants"
357 }
358 visibleOnHandlerThread(csHandler) { this.sdkLevel = sdkLevel }
359 }
360
isAtLeastSnull361 override fun isAtLeastS() = if (isSdkUnmocked) super.isAtLeastS() else sdkLevel >= VERSION_S
362 override fun isAtLeastT() = if (isSdkUnmocked) super.isAtLeastT() else sdkLevel >= VERSION_T
363 override fun isAtLeastU() = if (isSdkUnmocked) super.isAtLeastU() else sdkLevel >= VERSION_U
364 override fun isAtLeastV() = if (isSdkUnmocked) super.isAtLeastV() else sdkLevel >= VERSION_V
365
366 private var callingUid = CALLING_UID_UNMOCKED
367
368 fun unmockCallingUid() {
369 setCallingUid(CALLING_UID_UNMOCKED)
370 }
371
setCallingUidnull372 fun setCallingUid(callingUid: Int) {
373 visibleOnHandlerThread(csHandler) { this.callingUid = callingUid }
374 }
375
getCallingUidnull376 override fun getCallingUid() =
377 if (callingUid == CALLING_UID_UNMOCKED) super.getCallingUid() else callingUid
378
379 override fun destroyLiveTcpSocketsByOwnerUids(ownerUids: Set<Int>) {
380 // Call mocked destroyLiveTcpSocketsByOwnerUids so that test can verify this method call
381 destroySocketsWrapper.destroyLiveTcpSocketsByOwnerUids(ownerUids)
382 }
383 }
384
385 inner class CSContext(base: Context) : BroadcastInterceptingContext(base) {
386 val pacProxyManager = mock<PacProxyManager>()
387 val networkPolicyManager = mock<NetworkPolicyManager>()
388
389 // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
390 // For permissions granted across the board, the key is only the permission name.
391 // For permissions only granted to a combination of uid/pid, the key
392 // is "<permission name>,<pid>,<uid>". PID+UID permissions have priority over generic ones.
393 private val mMockedPermissions: HashMap<String, Int> = HashMap()
394 private val mStartedActivities = LinkedBlockingQueue<Intent>()
getPackageManagernull395 override fun getPackageManager() = this@CSTest.packageManager
396 override fun getContentResolver() = this@CSTest.contentResolver
397
398 // If the permission result does not set in the mMockedPermissions, it will be
399 // considered as PERMISSION_GRANTED as existing design to prevent breaking other tests.
400 override fun checkPermission(permission: String, pid: Int, uid: Int) =
401 checkMockedPermission(permission, pid, uid, PERMISSION_GRANTED)
402
403 override fun enforceCallingOrSelfPermission(permission: String, message: String?) {
404 // If the permission result does not set in the mMockedPermissions, it will be
405 // considered as PERMISSION_GRANTED as existing design to prevent breaking other tests.
406 val granted = checkMockedPermission(
407 permission,
408 Process.myPid(),
409 Process.myUid(),
410 PERMISSION_GRANTED
411 )
412 if (!granted.equals(PERMISSION_GRANTED)) {
413 throw SecurityException("[Test] permission denied: " + permission)
414 }
415 }
416
417 // If the permission result does not set in the mMockedPermissions, it will be
418 // considered as PERMISSION_GRANTED as existing design to prevent breaking other tests.
checkCallingOrSelfPermissionnull419 override fun checkCallingOrSelfPermission(permission: String) =
420 checkMockedPermission(permission, Process.myPid(), Process.myUid(), PERMISSION_GRANTED)
421
422 private fun checkMockedPermission(
423 permission: String,
424 pid: Int,
425 uid: Int,
426 default: Int
427 ): Int {
428 val processSpecificKey = "$permission,$pid,$uid"
429 return mMockedPermissions[processSpecificKey]
430 ?: mMockedPermissions[permission] ?: default
431 }
432
433 /**
434 * Mock checks for the specified permission, and have them behave as per `granted` or
435 * `denied`.
436 *
437 * This will apply to all calls no matter what the checked UID and PID are.
438 *
439 * @param granted One of {@link PackageManager#PermissionResult}.
440 */
setPermissionnull441 fun setPermission(permission: String, @PermissionResult granted: Int) {
442 mMockedPermissions.put(permission, granted)
443 }
444
445 /**
446 * Mock checks for the specified permission, and have them behave as per `granted` or
447 * `denied`.
448 *
449 * This will only apply to the passed UID and PID.
450 *
451 * @param granted One of {@link PackageManager#PermissionResult}.
452 */
setPermissionnull453 fun setPermission(permission: String, pid: Int, uid: Int, @PermissionResult granted: Int) {
454 mMockedPermissions.put("$permission,$pid,$uid", granted)
455 }
456
457 // Necessary for MultinetworkPolicyTracker, which tries to register a receiver for
458 // all users. The test can't do that since it doesn't hold INTERACT_ACROSS_USERS.
459 // TODO : ensure MultinetworkPolicyTracker's BroadcastReceiver is tested ; ideally,
460 // just returning null should not have tests pass
registerReceiverForAllUsersnull461 override fun registerReceiverForAllUsers(
462 receiver: BroadcastReceiver?,
463 filter: IntentFilter,
464 broadcastPermission: String?,
465 scheduler: Handler?
466 ): Intent? = null
467
468 // Create and cache user managers on the fly as necessary.
469 val userManagers = HashMap<UserHandle, UserManager>()
470 override fun createContextAsUser(user: UserHandle, flags: Int): Context {
471 val asUser = mock(Context::class.java, delegatesTo<Any>(this))
472 doReturn(user).`when`(asUser).getUser()
473 doAnswer { userManagers.computeIfAbsent(user) {
474 mock(UserManager::class.java, delegatesTo<Any>(userManager)) }
475 }.`when`(asUser).getSystemService(Context.USER_SERVICE)
476 return asUser
477 }
478
479 // List of mocked services. Add additional services here or in subclasses.
getSystemServicenull480 override fun getSystemService(serviceName: String) = when (serviceName) {
481 Context.CONNECTIVITY_SERVICE -> cm
482 Context.PAC_PROXY_SERVICE -> pacProxyManager
483 Context.NETWORK_POLICY_SERVICE -> networkPolicyManager
484 Context.ALARM_SERVICE -> alarmManager
485 Context.USER_SERVICE -> userManager
486 Context.ACTIVITY_SERVICE -> activityManager
487 Context.SYSTEM_CONFIG_SERVICE -> systemConfigManager
488 Context.TELEPHONY_SERVICE -> telephonyManager
489 Context.TELEPHONY_SUBSCRIPTION_SERVICE -> subscriptionManager
490 Context.BATTERY_STATS_SERVICE -> batteryManager
491 Context.STATS_MANAGER -> null // Stats manager is final and can't be mocked
492 Context.APP_OPS_SERVICE -> appOpsManager
493 else -> super.getSystemService(serviceName)
494 }
495
496 internal val orderedBroadcastAsUserHistory = ArrayTrackRecord<Intent>().newReadHead()
497
expectNoDataActivityBroadcastnull498 fun expectNoDataActivityBroadcast(timeoutMs: Int) {
499 assertNull(orderedBroadcastAsUserHistory.poll(timeoutMs.toLong()))
500 }
501
sendOrderedBroadcastAsUsernull502 override fun sendOrderedBroadcastAsUser(
503 intent: Intent,
504 user: UserHandle,
505 receiverPermission: String?,
506 resultReceiver: BroadcastReceiver?,
507 scheduler: Handler?,
508 initialCode: Int,
509 initialData: String?,
510 initialExtras: Bundle?
511 ) {
512 orderedBroadcastAsUserHistory.add(intent)
513 }
514
startActivityAsUsernull515 override fun startActivityAsUser(intent: Intent, handle: UserHandle) {
516 mStartedActivities.put(intent)
517 }
518
expectStartActivityIntentnull519 fun expectStartActivityIntent(timeoutMs: Long = HANDLER_TIMEOUT_MS): Intent {
520 val intent = mStartedActivities.poll(timeoutMs, TimeUnit.MILLISECONDS)
521 assertNotNull(intent, "Did not receive sign-in intent after " + timeoutMs + "ms")
522 return intent
523 }
524 }
525
526 // Utility methods for subclasses to use
waitForIdlenull527 fun waitForIdle() = csHandlerThread.waitForIdle(HANDLER_TIMEOUT_MS)
528
529 // Network agents. See CSAgentWrapper. This class contains utility methods to simplify
530 // creation.
531 fun Agent(
532 nc: NetworkCapabilities = defaultNc(),
533 nac: NetworkAgentConfig = emptyAgentConfig(nc.getLegacyType()),
534 lp: LinkProperties = defaultLp(),
535 lnc: FromS<LocalNetworkConfig>? = null,
536 score: FromS<NetworkScore> = defaultScore(),
537 provider: NetworkProvider? = null
538 ) = CSAgentWrapper(context, deps, csHandlerThread, networkStack,
539 nac, nc, lp, lnc, score, provider)
540 fun Agent(vararg transports: Int, lp: LinkProperties = defaultLp()): CSAgentWrapper {
541 val nc = NetworkCapabilities.Builder().apply {
542 transports.forEach {
543 addTransportType(it)
544 }
545 }.addCapability(NET_CAPABILITY_NOT_SUSPENDED)
546 .build()
547 return Agent(nc = nc, lp = lp)
548 }
549 }
550