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