• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.server
18 
19 import android.net.ConnectivityManager
20 import android.net.ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE
21 import android.net.ConnectivityManager.EXTRA_DEVICE_TYPE
22 import android.net.ConnectivityManager.EXTRA_IS_ACTIVE
23 import android.net.ConnectivityManager.EXTRA_REALTIME_NS
24 import android.net.ConnectivitySettingsManager
25 import android.net.LinkProperties
26 import android.net.NetworkCapabilities
27 import android.net.NetworkCapabilities.NET_CAPABILITY_IMS
28 import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
29 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
30 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
31 import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
32 import android.net.NetworkCapabilities.TRANSPORT_WIFI
33 import android.net.NetworkRequest
34 import android.os.Build
35 import android.os.ConditionVariable
36 import android.telephony.DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
37 import android.telephony.DataConnectionRealTimeInfo.DC_POWER_STATE_LOW
38 import androidx.test.filters.SmallTest
39 import com.android.net.module.util.BaseNetdUnsolicitedEventListener
40 import com.android.server.CSTest.CSContext
41 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
42 import com.android.testutils.DevSdkIgnoreRunner
43 import com.android.testutils.RecorderCallback.CallbackEntry.Lost
44 import com.android.testutils.TestableNetworkCallback
45 import java.time.Duration
46 import kotlin.test.assertNotNull
47 import org.junit.Assert.assertFalse
48 import org.junit.Assert.assertTrue
49 import org.junit.Test
50 import org.junit.runner.RunWith
51 import org.mockito.ArgumentCaptor
52 import org.mockito.ArgumentMatchers.anyString
53 import org.mockito.ArgumentMatchers.eq
54 import org.mockito.Mockito.anyInt
55 import org.mockito.Mockito.anyLong
56 import org.mockito.Mockito.inOrder
57 import org.mockito.Mockito.never
58 import org.mockito.Mockito.timeout
59 import org.mockito.Mockito.verify
60 
61 private const val DATA_CELL_IFNAME = "rmnet_data"
62 private const val IMS_CELL_IFNAME = "rmnet_ims"
63 private const val WIFI_IFNAME = "wlan0"
64 private const val TIMESTAMP = 1234L
65 private const val NETWORK_ACTIVITY_NO_UID = -1
66 private const val PACKAGE_UID = 123
67 private const val TIMEOUT_MS = 250L
68 
69 @DevSdkIgnoreRunner.MonitorThreadLeak
70 @RunWith(DevSdkIgnoreRunner::class)
71 @SmallTest
72 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
73 class CSNetworkActivityTest : CSTest() {
74 
75     private fun setMobileDataActivityTimeout(timeoutSeconds: Int) {
76         ConnectivitySettingsManager.setMobileDataActivityTimeout(
77             context, Duration.ofSeconds(timeoutSeconds.toLong())
78         )
79     }
80 
81     private fun setWifiDataActivityTimeout(timeoutSeconds: Int) {
82         ConnectivitySettingsManager.setWifiDataActivityTimeout(
83             context, Duration.ofSeconds(timeoutSeconds.toLong())
84         )
85     }
86 
87     private fun getRegisteredNetdUnsolicitedEventListener(): BaseNetdUnsolicitedEventListener {
88         val captor = ArgumentCaptor.forClass(BaseNetdUnsolicitedEventListener::class.java)
89         verify(netd).registerUnsolicitedEventListener(captor.capture())
90         return captor.value
91     }
92 
93     @Test
94     fun testInterfaceClassActivityChanged_NonDefaultNetwork() {
95         val netdUnsolicitedEventListener = getRegisteredNetdUnsolicitedEventListener()
96         val batteryStatsInorder = inOrder(batteryStats)
97 
98         val cellNr = NetworkRequest.Builder()
99                 .clearCapabilities()
100                 .addTransportType(TRANSPORT_CELLULAR)
101                 .addCapability(NET_CAPABILITY_INTERNET)
102                 .build()
103         val cellCb = TestableNetworkCallback()
104         // Request cell network to keep cell network up
105         cm.requestNetwork(cellNr, cellCb)
106 
107         val defaultCb = TestableNetworkCallback()
108         cm.registerDefaultNetworkCallback(defaultCb)
109 
110         val cellNc = NetworkCapabilities.Builder()
111                 .addTransportType(TRANSPORT_CELLULAR)
112                 .addCapability(NET_CAPABILITY_INTERNET)
113                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
114                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
115                 .build()
116         val cellLp = LinkProperties().apply {
117             interfaceName = DATA_CELL_IFNAME
118         }
119         // Connect Cellular network
120         val cellAgent = Agent(nc = cellNc, lp = cellLp)
121         cellAgent.connect()
122         defaultCb.expectAvailableCallbacks(cellAgent.network, validated = false)
123 
124         val wifiNc = NetworkCapabilities.Builder()
125                 .addTransportType(TRANSPORT_WIFI)
126                 .addCapability(NET_CAPABILITY_INTERNET)
127                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
128                 .build()
129         val wifiLp = LinkProperties().apply {
130             interfaceName = WIFI_IFNAME
131         }
132         // Connect Wi-Fi network, Wi-Fi network should be the default network.
133         val wifiAgent = Agent(nc = wifiNc, lp = wifiLp)
134         wifiAgent.connect()
135         defaultCb.expectAvailableCallbacks(wifiAgent.network, validated = false)
136         batteryStatsInorder.verify(batteryStats).noteWifiRadioPowerState(eq(DC_POWER_STATE_HIGH),
137                 anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID))
138 
139         val onNetworkActiveCv = ConditionVariable()
140         val listener = ConnectivityManager.OnNetworkActiveListener { onNetworkActiveCv::open }
141         cm.addDefaultNetworkActiveListener(listener)
142 
143         // Cellular network (non default network) goes to inactive state.
144         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
145                 cellAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
146         // Non-default network activity change does not change default network activity
147         // But cellular radio power state is updated
148         assertFalse(onNetworkActiveCv.block(TIMEOUT_MS))
149         context.expectNoDataActivityBroadcast(0 /* timeoutMs */)
150         assertTrue(cm.isDefaultNetworkActive)
151         batteryStatsInorder.verify(batteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_LOW),
152                 anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID))
153 
154         // Cellular network (non default network) goes to active state.
155         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
156                 cellAgent.network.netId, TIMESTAMP, PACKAGE_UID)
157         // Non-default network activity change does not change default network activity
158         // But cellular radio power state is updated
159         assertFalse(onNetworkActiveCv.block(TIMEOUT_MS))
160         context.expectNoDataActivityBroadcast(0 /* timeoutMs */)
161         assertTrue(cm.isDefaultNetworkActive)
162         batteryStatsInorder.verify(batteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_HIGH),
163                 anyLong() /* timestampNs */, eq(PACKAGE_UID))
164 
165         cm.unregisterNetworkCallback(cellCb)
166         cm.unregisterNetworkCallback(defaultCb)
167         cm.removeDefaultNetworkActiveListener(listener)
168     }
169 
170     @Test
171     fun testDataActivityTracking_MultiCellNetwork() {
172         val netdUnsolicitedEventListener = getRegisteredNetdUnsolicitedEventListener()
173         val batteryStatsInorder = inOrder(batteryStats)
174 
175         val dataNetworkNc = NetworkCapabilities.Builder()
176                 .addTransportType(TRANSPORT_CELLULAR)
177                 .addCapability(NET_CAPABILITY_INTERNET)
178                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
179                 .build()
180         val dataNetworkNr = NetworkRequest.Builder()
181                 .clearCapabilities()
182                 .addTransportType(TRANSPORT_CELLULAR)
183                 .addCapability(NET_CAPABILITY_INTERNET)
184                 .build()
185         val dataNetworkLp = LinkProperties().apply {
186             interfaceName = DATA_CELL_IFNAME
187         }
188         val dataNetworkCb = TestableNetworkCallback()
189         cm.requestNetwork(dataNetworkNr, dataNetworkCb)
190         val dataNetworkAgent = Agent(nc = dataNetworkNc, lp = dataNetworkLp)
191         val dataNetworkNetId = dataNetworkAgent.network.netId.toString()
192 
193         val imsNetworkNc = NetworkCapabilities.Builder()
194                 .addTransportType(TRANSPORT_CELLULAR)
195                 .addCapability(NET_CAPABILITY_IMS)
196                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
197                 .build()
198         val imsNetworkNr = NetworkRequest.Builder()
199                 .clearCapabilities()
200                 .addTransportType(TRANSPORT_CELLULAR)
201                 .addCapability(NET_CAPABILITY_IMS)
202                 .build()
203         val imsNetworkLp = LinkProperties().apply {
204             interfaceName = IMS_CELL_IFNAME
205         }
206         val imsNetworkCb = TestableNetworkCallback()
207         cm.requestNetwork(imsNetworkNr, imsNetworkCb)
208         val imsNetworkAgent = Agent(nc = imsNetworkNc, lp = imsNetworkLp)
209         val imsNetworkNetId = imsNetworkAgent.network.netId.toString()
210 
211         dataNetworkAgent.connect()
212         dataNetworkCb.expectAvailableCallbacks(dataNetworkAgent.network, validated = false)
213 
214         imsNetworkAgent.connect()
215         imsNetworkCb.expectAvailableCallbacks(imsNetworkAgent.network, validated = false)
216 
217         // Both cell networks have idleTimers
218         verify(netd).idletimerAddInterface(eq(DATA_CELL_IFNAME), anyInt(), eq(dataNetworkNetId))
219         verify(netd).idletimerAddInterface(eq(IMS_CELL_IFNAME), anyInt(), eq(imsNetworkNetId))
220         verify(netd, never()).idletimerRemoveInterface(eq(DATA_CELL_IFNAME), anyInt(),
221                 eq(dataNetworkNetId))
222         verify(netd, never()).idletimerRemoveInterface(eq(IMS_CELL_IFNAME), anyInt(),
223                 eq(imsNetworkNetId))
224 
225         // Both cell networks go to inactive state
226         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
227                 imsNetworkAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
228         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
229                 dataNetworkAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
230 
231         // Data cell network goes to active state. This should update the cellular radio power state
232         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
233                 dataNetworkAgent.network.netId, TIMESTAMP, PACKAGE_UID)
234         batteryStatsInorder.verify(batteryStats, timeout(TIMEOUT_MS)).noteMobileRadioPowerState(
235                 eq(DC_POWER_STATE_HIGH), anyLong() /* timestampNs */, eq(PACKAGE_UID))
236         // Ims cell network goes to active state. But this should not update the cellular radio
237         // power state since cellular radio power state is already high
238         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
239                 imsNetworkAgent.network.netId, TIMESTAMP, PACKAGE_UID)
240         waitForIdle()
241         batteryStatsInorder.verify(batteryStats, never()).noteMobileRadioPowerState(anyInt(),
242                 anyLong() /* timestampNs */, anyInt())
243 
244         // Data cell network goes to inactive state. But this should not update the cellular radio
245         // power state ims cell network is still active state
246         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
247                 dataNetworkAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
248         waitForIdle()
249         batteryStatsInorder.verify(batteryStats, never()).noteMobileRadioPowerState(anyInt(),
250                 anyLong() /* timestampNs */, anyInt())
251 
252         // Ims cell network goes to inactive state.
253         // This should update the cellular radio power state
254         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
255                 imsNetworkAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
256         batteryStatsInorder.verify(batteryStats, timeout(TIMEOUT_MS)).noteMobileRadioPowerState(
257                 eq(DC_POWER_STATE_LOW), anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID))
258 
259         dataNetworkAgent.disconnect()
260         dataNetworkCb.expect<Lost>(dataNetworkAgent.network)
261         verify(netd).idletimerRemoveInterface(eq(DATA_CELL_IFNAME), anyInt(), eq(dataNetworkNetId))
262 
263         imsNetworkAgent.disconnect()
264         imsNetworkCb.expect<Lost>(imsNetworkAgent.network)
265         verify(netd).idletimerRemoveInterface(eq(IMS_CELL_IFNAME), anyInt(), eq(imsNetworkNetId))
266 
267         cm.unregisterNetworkCallback(dataNetworkCb)
268         cm.unregisterNetworkCallback(imsNetworkCb)
269     }
270 
271     @Test
272     fun testCellularIdleTimerSettingsTimeout() {
273         val cellNc = NetworkCapabilities.Builder()
274             .addTransportType(TRANSPORT_CELLULAR)
275             .addCapability(NET_CAPABILITY_INTERNET)
276             .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
277             .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
278             .build()
279         val cellLp = LinkProperties().apply {
280             interfaceName = DATA_CELL_IFNAME
281         }
282 
283         val settingsTimeout: Int = deps.defaultCellDataInactivityTimeoutForTest + 432
284         // DATA_ACTIVITY_TIMEOUT_MOBILE is set, so the default should be ignored.
285         setMobileDataActivityTimeout(settingsTimeout)
286         val cellAgent = Agent(nc = cellNc, lp = cellLp)
287         cellAgent.connect()
288 
289         verify(netd).idletimerAddInterface(eq(DATA_CELL_IFNAME), eq(settingsTimeout), anyString())
290     }
291 
292     @Test
293     fun testCellularIdleTimerDefaultTimeout() {
294         val cellNc = NetworkCapabilities.Builder()
295             .addTransportType(TRANSPORT_CELLULAR)
296             .addCapability(NET_CAPABILITY_INTERNET)
297             .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
298             .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
299             .build()
300         val cellLp = LinkProperties().apply {
301             interfaceName = DATA_CELL_IFNAME
302         }
303 
304         val testTimeout: Int = deps.defaultCellDataInactivityTimeoutForTest
305         // DATA_ACTIVITY_TIMEOUT_MOBILE is not set, so the default should be used.
306         val cellAgent = Agent(nc = cellNc, lp = cellLp)
307         cellAgent.connect()
308 
309         verify(netd).idletimerAddInterface(eq(DATA_CELL_IFNAME), eq(testTimeout), anyString())
310     }
311 
312     @Test
313     fun testCellularIdleTimerDisabled() {
314         val cellNc = NetworkCapabilities.Builder()
315             .addTransportType(TRANSPORT_CELLULAR)
316             .addCapability(NET_CAPABILITY_INTERNET)
317             .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
318             .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
319             .build()
320         val cellLp = LinkProperties().apply {
321             interfaceName = DATA_CELL_IFNAME
322         }
323         setMobileDataActivityTimeout(0)
324         val cellAgent = Agent(nc = cellNc, lp = cellLp)
325         cellAgent.connect()
326 
327         verify(netd, never()).idletimerAddInterface(eq(DATA_CELL_IFNAME), anyInt(), anyString())
328     }
329 
330     @Test
331     fun testWifiIdleTimerSettingsTimeout() {
332         val wifiNc = NetworkCapabilities.Builder()
333             .addTransportType(TRANSPORT_WIFI)
334             .addCapability(NET_CAPABILITY_INTERNET)
335             .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
336             .build()
337         val wifiLp = LinkProperties().apply {
338             interfaceName = WIFI_IFNAME
339         }
340         val settingsTimeout: Int = deps.defaultWifiDataInactivityTimeout + 435
341         setWifiDataActivityTimeout(settingsTimeout)
342         // DATA_ACTIVITY_TIMEOUT_MOBILE is set, so the default should be ignored.
343         val wifiAgent = Agent(nc = wifiNc, lp = wifiLp)
344         wifiAgent.connect()
345 
346         verify(netd).idletimerAddInterface(eq(WIFI_IFNAME), eq(settingsTimeout), anyString())
347     }
348 
349     @Test
350     fun testWifiIdleTimerDefaultTimeout() {
351         val wifiNc = NetworkCapabilities.Builder()
352             .addTransportType(TRANSPORT_WIFI)
353             .addCapability(NET_CAPABILITY_INTERNET)
354             .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
355             .build()
356         val wifiLp = LinkProperties().apply {
357             interfaceName = WIFI_IFNAME
358         }
359         val testTimeout: Int = deps.defaultWifiDataInactivityTimeoutForTest
360         // DATA_ACTIVITY_TIMEOUT_WIFI is not set, so the default should be used.
361         val wifiAgent = Agent(nc = wifiNc, lp = wifiLp)
362         wifiAgent.connect()
363 
364         verify(netd).idletimerAddInterface(eq(WIFI_IFNAME), eq(testTimeout), anyString())
365     }
366 
367     @Test
368     fun testWifiIdleTimerDisabled() {
369         val wifiNc = NetworkCapabilities.Builder()
370             .addTransportType(TRANSPORT_WIFI)
371             .addCapability(NET_CAPABILITY_INTERNET)
372             .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
373             .build()
374         val wifiLp = LinkProperties().apply {
375             interfaceName = WIFI_IFNAME
376         }
377         setWifiDataActivityTimeout(0)
378         val wifiAgent = Agent(nc = wifiNc, lp = wifiLp)
379         wifiAgent.connect()
380 
381         verify(netd, never()).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(), anyString())
382     }
383 }
384 
385 
expectDataActivityBroadcastnull386 internal fun CSContext.expectDataActivityBroadcast(
387         deviceType: Int,
388         isActive: Boolean,
389         tsNanos: Long
390 ) {
391     assertNotNull(orderedBroadcastAsUserHistory.poll(BROADCAST_TIMEOUT_MS) {
392         intent -> intent.action.equals(ACTION_DATA_ACTIVITY_CHANGE) &&
393             intent.getIntExtra(EXTRA_DEVICE_TYPE, -1) == deviceType &&
394             intent.getBooleanExtra(EXTRA_IS_ACTIVE, !isActive) == isActive &&
395             intent.getLongExtra(EXTRA_REALTIME_NS, -1) == tsNanos
396     })
397 }
398