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