1 /*
<lambda>null2 * 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 @file:JvmName("CsTestHelpers")
18
19 package com.android.server
20
21 import android.app.ActivityManager
22 import android.app.AlarmManager
23 import android.content.Context
24 import android.content.pm.PackageManager
25 import android.content.pm.PackageManager.FEATURE_BLUETOOTH
26 import android.content.pm.PackageManager.FEATURE_ETHERNET
27 import android.content.pm.PackageManager.FEATURE_WIFI
28 import android.content.pm.PackageManager.FEATURE_WIFI_DIRECT
29 import android.content.pm.UserInfo
30 import android.content.res.Resources
31 import android.net.IDnsResolver
32 import android.net.INetd
33 import android.net.IpPrefix
34 import android.net.LinkAddress
35 import android.net.LinkProperties
36 import android.net.NetworkAgentConfig
37 import android.net.NetworkCapabilities
38 import android.net.NetworkScore
39 import android.net.RouteInfo
40 import android.net.metrics.IpConnectivityLog
41 import android.os.Binder
42 import android.os.Handler
43 import android.os.HandlerThread
44 import android.os.SystemClock
45 import android.os.SystemConfigManager
46 import android.os.UserHandle
47 import android.os.UserManager
48 import android.provider.Settings
49 import android.test.mock.MockContentResolver
50 import com.android.connectivity.resources.R
51 import com.android.internal.util.WakeupMessage
52 import com.android.internal.util.test.FakeSettingsProvider
53 import com.android.modules.utils.build.SdkLevel
54 import com.android.server.ConnectivityService.Dependencies
55 import com.android.server.connectivity.ConnectivityResources
56 import kotlin.test.fail
57 import org.mockito.ArgumentMatchers
58 import org.mockito.ArgumentMatchers.any
59 import org.mockito.ArgumentMatchers.anyInt
60 import org.mockito.ArgumentMatchers.anyLong
61 import org.mockito.ArgumentMatchers.anyString
62 import org.mockito.ArgumentMatchers.argThat
63 import org.mockito.ArgumentMatchers.eq
64 import org.mockito.Mockito
65 import org.mockito.Mockito.doAnswer
66 import org.mockito.Mockito.doNothing
67 import org.mockito.Mockito.doReturn
68
69 internal inline fun <reified T> mock() = Mockito.mock(T::class.java)
70 internal inline fun <reified T> any() = any(T::class.java)
71
72 internal fun emptyAgentConfig(legacyType: Int) = NetworkAgentConfig.Builder()
73 .setLegacyType(legacyType)
74 .build()
75
76 internal fun defaultNc() = NetworkCapabilities.Builder()
77 // Add sensible defaults for agents that don't want to care
78 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
79 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
80 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
81 .build()
82
83 internal fun defaultScore() = FromS(NetworkScore.Builder().build())
84
85 internal fun defaultLp() = LinkProperties().apply {
86 addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32))
87 addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
88 }
89
<lambda>null90 internal fun makeMockContentResolver(context: Context) = MockContentResolver(context).apply {
91 addProvider(Settings.AUTHORITY, FakeSettingsProvider())
92 }
93
<lambda>null94 internal fun makeMockUserManager(info: UserInfo, handle: UserHandle) = mock<UserManager>().also {
95 doReturn(listOf(info)).`when`(it).getAliveUsers()
96 doReturn(listOf(handle)).`when`(it).getUserHandles(ArgumentMatchers.anyBoolean())
97 }
98
<lambda>null99 internal fun makeActivityManager() = mock<ActivityManager>().also {
100 if (SdkLevel.isAtLeastU()) {
101 doNothing().`when`(it).registerUidFrozenStateChangedCallback(any(), any())
102 }
103 }
104
makeMockPackageManagernull105 internal fun makeMockPackageManager(realContext: Context) = mock<PackageManager>().also { pm ->
106 val supported = listOf(FEATURE_WIFI, FEATURE_WIFI_DIRECT, FEATURE_BLUETOOTH, FEATURE_ETHERNET)
107 doReturn(true).`when`(pm).hasSystemFeature(argThat { supported.contains(it) })
108 val myPackageName = realContext.packageName
109 val myPackageInfo = realContext.packageManager.getPackageInfo(myPackageName,
110 PackageManager.GET_PERMISSIONS)
111 // Very high version code so that the checks for the module version will always
112 // say that it is recent enough. This is the most sensible default, but if some
113 // test needs to test with different version codes they can re-mock this with a
114 // different value.
115 myPackageInfo.longVersionCode = 9999999L
116 doReturn(arrayOf(myPackageName)).`when`(pm).getPackagesForUid(Binder.getCallingUid())
117 doReturn(myPackageInfo).`when`(pm).getPackageInfoAsUser(
118 eq(myPackageName), anyInt(), eq(UserHandle.getCallingUserId()))
119 doReturn(listOf(myPackageInfo)).`when`(pm)
120 .getInstalledPackagesAsUser(eq(PackageManager.GET_PERMISSIONS), anyInt())
121 }
122
<lambda>null123 internal fun makeMockConnResources(resources: Resources, pm: PackageManager) = mock<Context>().let {
124 doReturn(resources).`when`(it).resources
125 doReturn(pm).`when`(it).packageManager
126 ConnectivityResources.setResourcesContextForTest(it)
127 ConnectivityResources(it)
128 }
129
130 private val UNREASONABLY_LONG_ALARM_WAIT_MS = 1000
makeMockAlarmManagernull131 internal fun makeMockAlarmManager(handlerThread: HandlerThread) = mock<AlarmManager>().also { am ->
132 val alrmHdlr = handlerThread.threadHandler
133 doAnswer {
134 val (_, date, _, wakeupMsg, handler) = it.arguments
135 wakeupMsg as WakeupMessage
136 handler as Handler
137 val delayMs = ((date as Long) - SystemClock.elapsedRealtime()).coerceAtLeast(0)
138 if (delayMs > UNREASONABLY_LONG_ALARM_WAIT_MS) {
139 fail("Attempting to send msg more than $UNREASONABLY_LONG_ALARM_WAIT_MS" +
140 "ms into the future : $delayMs")
141 }
142 alrmHdlr.postDelayed({ handler.post(wakeupMsg::onAlarm) }, wakeupMsg, delayMs)
143 }.`when`(am).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), anyLong(), anyString(),
144 any<WakeupMessage>(), any())
145 doAnswer {
146 alrmHdlr.removeCallbacksAndMessages(it.getArgument<WakeupMessage>(0))
147 }.`when`(am).cancel(any<WakeupMessage>())
148 }
149
<lambda>null150 internal fun makeMockSystemConfigManager() = mock<SystemConfigManager>().also {
151 doReturn(intArrayOf(0)).`when`(it).getSystemPermissionUids(anyString())
152 }
153
154 // Mocking resources used by ConnectivityService. Note these can't be defined to return the
155 // value returned by the mocking, because a non-null method would mean the helper would also
156 // return non-null and the compiler would check that, but mockito has no qualms returning null
157 // from a @NonNull method when stubbing. Hence, mock() = doReturn().getString() would crash
158 // at runtime, because getString() returns non-null String, therefore mock returns non-null String,
159 // and kotlinc adds an intrinsics check for that, which crashes at runtime when mockito actually
160 // returns null.
mocknull161 private fun Resources.mock(r: Int, v: Boolean) { doReturn(v).`when`(this).getBoolean(r) }
mocknull162 private fun Resources.mock(r: Int, v: Int) { doReturn(v).`when`(this).getInteger(r) }
mocknull163 private fun Resources.mock(r: Int, v: String) { doReturn(v).`when`(this).getString(r) }
mocknull164 private fun Resources.mock(r: Int, v: Array<String?>) { doReturn(v).`when`(this).getStringArray(r) }
mocknull165 private fun Resources.mock(r: Int, v: IntArray) { doReturn(v).`when`(this).getIntArray(r) }
166
initMockedResourcesnull167 internal fun initMockedResources(res: Resources) {
168 // Resources accessed through reflection need to return the id
169 doReturn(R.array.config_networkSupportedKeepaliveCount).`when`(res)
170 .getIdentifier(eq("config_networkSupportedKeepaliveCount"), eq("array"), any())
171 doReturn(R.array.network_switch_type_name).`when`(res)
172 .getIdentifier(eq("network_switch_type_name"), eq("array"), any())
173 // Mock the values themselves
174 res.mock(R.integer.config_networkTransitionTimeout, 60_000)
175 res.mock(R.string.config_networkCaptivePortalServerUrl, "")
176 res.mock(R.array.config_wakeonlan_supported_interfaces, arrayOf(WIFI_WOL_IFNAME))
177 res.mock(R.array.config_networkSupportedKeepaliveCount, arrayOf("0,1", "1,3"))
178 res.mock(R.array.config_networkNotifySwitches, arrayOfNulls<String>(size = 0))
179 res.mock(R.array.config_protectedNetworks, intArrayOf(10, 11, 12, 14, 15))
180 res.mock(R.array.network_switch_type_name, arrayOfNulls<String>(size = 0))
181 res.mock(R.integer.config_networkAvoidBadWifi, 1)
182 res.mock(R.integer.config_activelyPreferBadWifi, 0)
183 res.mock(R.bool.config_cellular_radio_timesharing_capable, true)
184 }
185
186 private val TEST_LINGER_DELAY_MS = 400
187 private val TEST_NASCENT_DELAY_MS = 300
makeConnectivityServicenull188 internal fun makeConnectivityService(context: Context, netd: INetd, deps: Dependencies) =
189 ConnectivityService(
190 context,
191 mock<IDnsResolver>(),
192 mock<IpConnectivityLog>(),
193 netd,
194 deps).also {
195 it.mLingerDelayMs = TEST_LINGER_DELAY_MS
196 it.mNascentDelayMs = TEST_NASCENT_DELAY_MS
197 }
198