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