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.LinkProperties
25 import android.net.NetworkCapabilities
26 import android.net.NetworkCapabilities.NET_CAPABILITY_IMS
27 import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
28 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
29 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
30 import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
31 import android.net.NetworkCapabilities.TRANSPORT_WIFI
32 import android.net.NetworkRequest
33 import android.os.Build
34 import android.os.ConditionVariable
35 import android.telephony.DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
36 import android.telephony.DataConnectionRealTimeInfo.DC_POWER_STATE_LOW
37 import androidx.test.filters.SmallTest
38 import com.android.net.module.util.BaseNetdUnsolicitedEventListener
39 import com.android.server.CSTest.CSContext
40 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
41 import com.android.testutils.DevSdkIgnoreRunner
42 import com.android.testutils.RecorderCallback.CallbackEntry.Lost
43 import com.android.testutils.TestableNetworkCallback
44 import kotlin.test.assertNotNull
45 import org.junit.Assert.assertFalse
46 import org.junit.Assert.assertTrue
47 import org.junit.Test
48 import org.junit.runner.RunWith
49 import org.mockito.ArgumentCaptor
50 import org.mockito.ArgumentMatchers.eq
51 import org.mockito.Mockito.anyInt
52 import org.mockito.Mockito.anyLong
53 import org.mockito.Mockito.inOrder
54 import org.mockito.Mockito.never
55 import org.mockito.Mockito.timeout
56 import org.mockito.Mockito.verify
57 
58 private const val DATA_CELL_IFNAME = "rmnet_data"
59 private const val IMS_CELL_IFNAME = "rmnet_ims"
60 private const val WIFI_IFNAME = "wlan0"
61 private const val TIMESTAMP = 1234L
62 private const val NETWORK_ACTIVITY_NO_UID = -1
63 private const val PACKAGE_UID = 123
64 private const val TIMEOUT_MS = 250L
65 
66 @DevSdkIgnoreRunner.MonitorThreadLeak
67 @RunWith(DevSdkIgnoreRunner::class)
68 @SmallTest
69 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
70 class CSNetworkActivityTest : CSTest() {
71 
72     private fun getRegisteredNetdUnsolicitedEventListener(): BaseNetdUnsolicitedEventListener {
73         val captor = ArgumentCaptor.forClass(BaseNetdUnsolicitedEventListener::class.java)
74         verify(netd).registerUnsolicitedEventListener(captor.capture())
75         return captor.value
76     }
77 
78     @Test
79     fun testInterfaceClassActivityChanged_NonDefaultNetwork() {
80         val netdUnsolicitedEventListener = getRegisteredNetdUnsolicitedEventListener()
81         val batteryStatsInorder = inOrder(batteryStats)
82 
83         val cellNr = NetworkRequest.Builder()
84                 .clearCapabilities()
85                 .addTransportType(TRANSPORT_CELLULAR)
86                 .addCapability(NET_CAPABILITY_INTERNET)
87                 .build()
88         val cellCb = TestableNetworkCallback()
89         // Request cell network to keep cell network up
90         cm.requestNetwork(cellNr, cellCb)
91 
92         val defaultCb = TestableNetworkCallback()
93         cm.registerDefaultNetworkCallback(defaultCb)
94 
95         val cellNc = NetworkCapabilities.Builder()
96                 .addTransportType(TRANSPORT_CELLULAR)
97                 .addCapability(NET_CAPABILITY_INTERNET)
98                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
99                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
100                 .build()
101         val cellLp = LinkProperties().apply {
102             interfaceName = DATA_CELL_IFNAME
103         }
104         // Connect Cellular network
105         val cellAgent = Agent(nc = cellNc, lp = cellLp)
106         cellAgent.connect()
107         defaultCb.expectAvailableCallbacks(cellAgent.network, validated = false)
108 
109         val wifiNc = NetworkCapabilities.Builder()
110                 .addTransportType(TRANSPORT_WIFI)
111                 .addCapability(NET_CAPABILITY_INTERNET)
112                 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
113                 .build()
114         val wifiLp = LinkProperties().apply {
115             interfaceName = WIFI_IFNAME
116         }
117         // Connect Wi-Fi network, Wi-Fi network should be the default network.
118         val wifiAgent = Agent(nc = wifiNc, lp = wifiLp)
119         wifiAgent.connect()
120         defaultCb.expectAvailableCallbacks(wifiAgent.network, validated = false)
121         batteryStatsInorder.verify(batteryStats).noteWifiRadioPowerState(eq(DC_POWER_STATE_HIGH),
122                 anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID))
123 
124         val onNetworkActiveCv = ConditionVariable()
125         val listener = ConnectivityManager.OnNetworkActiveListener { onNetworkActiveCv::open }
126         cm.addDefaultNetworkActiveListener(listener)
127 
128         // Cellular network (non default network) goes to inactive state.
129         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
130                 cellAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
131         // Non-default network activity change does not change default network activity
132         // But cellular radio power state is updated
133         assertFalse(onNetworkActiveCv.block(TIMEOUT_MS))
134         context.expectNoDataActivityBroadcast(0 /* timeoutMs */)
135         assertTrue(cm.isDefaultNetworkActive)
136         batteryStatsInorder.verify(batteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_LOW),
137                 anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID))
138 
139         // Cellular network (non default network) goes to active state.
140         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
141                 cellAgent.network.netId, TIMESTAMP, PACKAGE_UID)
142         // Non-default network activity change does not change default network activity
143         // But cellular radio power state is updated
144         assertFalse(onNetworkActiveCv.block(TIMEOUT_MS))
145         context.expectNoDataActivityBroadcast(0 /* timeoutMs */)
146         assertTrue(cm.isDefaultNetworkActive)
147         batteryStatsInorder.verify(batteryStats).noteMobileRadioPowerState(eq(DC_POWER_STATE_HIGH),
148                 anyLong() /* timestampNs */, eq(PACKAGE_UID))
149 
150         cm.unregisterNetworkCallback(cellCb)
151         cm.unregisterNetworkCallback(defaultCb)
152         cm.removeDefaultNetworkActiveListener(listener)
153     }
154 
155     @Test
156     fun testDataActivityTracking_MultiCellNetwork() {
157         val netdUnsolicitedEventListener = getRegisteredNetdUnsolicitedEventListener()
158         val batteryStatsInorder = inOrder(batteryStats)
159 
160         val dataNetworkNc = NetworkCapabilities.Builder()
161                 .addTransportType(TRANSPORT_CELLULAR)
162                 .addCapability(NET_CAPABILITY_INTERNET)
163                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
164                 .build()
165         val dataNetworkNr = NetworkRequest.Builder()
166                 .clearCapabilities()
167                 .addTransportType(TRANSPORT_CELLULAR)
168                 .addCapability(NET_CAPABILITY_INTERNET)
169                 .build()
170         val dataNetworkLp = LinkProperties().apply {
171             interfaceName = DATA_CELL_IFNAME
172         }
173         val dataNetworkCb = TestableNetworkCallback()
174         cm.requestNetwork(dataNetworkNr, dataNetworkCb)
175         val dataNetworkAgent = Agent(nc = dataNetworkNc, lp = dataNetworkLp)
176         val dataNetworkNetId = dataNetworkAgent.network.netId.toString()
177 
178         val imsNetworkNc = NetworkCapabilities.Builder()
179                 .addTransportType(TRANSPORT_CELLULAR)
180                 .addCapability(NET_CAPABILITY_IMS)
181                 .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
182                 .build()
183         val imsNetworkNr = NetworkRequest.Builder()
184                 .clearCapabilities()
185                 .addTransportType(TRANSPORT_CELLULAR)
186                 .addCapability(NET_CAPABILITY_IMS)
187                 .build()
188         val imsNetworkLp = LinkProperties().apply {
189             interfaceName = IMS_CELL_IFNAME
190         }
191         val imsNetworkCb = TestableNetworkCallback()
192         cm.requestNetwork(imsNetworkNr, imsNetworkCb)
193         val imsNetworkAgent = Agent(nc = imsNetworkNc, lp = imsNetworkLp)
194         val imsNetworkNetId = imsNetworkAgent.network.netId.toString()
195 
196         dataNetworkAgent.connect()
197         dataNetworkCb.expectAvailableCallbacks(dataNetworkAgent.network, validated = false)
198 
199         imsNetworkAgent.connect()
200         imsNetworkCb.expectAvailableCallbacks(imsNetworkAgent.network, validated = false)
201 
202         // Both cell networks have idleTimers
203         verify(netd).idletimerAddInterface(eq(DATA_CELL_IFNAME), anyInt(), eq(dataNetworkNetId))
204         verify(netd).idletimerAddInterface(eq(IMS_CELL_IFNAME), anyInt(), eq(imsNetworkNetId))
205         verify(netd, never()).idletimerRemoveInterface(eq(DATA_CELL_IFNAME), anyInt(),
206                 eq(dataNetworkNetId))
207         verify(netd, never()).idletimerRemoveInterface(eq(IMS_CELL_IFNAME), anyInt(),
208                 eq(imsNetworkNetId))
209 
210         // Both cell networks go to inactive state
211         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
212                 imsNetworkAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
213         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
214                 dataNetworkAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
215 
216         // Data cell network goes to active state. This should update the cellular radio power state
217         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
218                 dataNetworkAgent.network.netId, TIMESTAMP, PACKAGE_UID)
219         batteryStatsInorder.verify(batteryStats, timeout(TIMEOUT_MS)).noteMobileRadioPowerState(
220                 eq(DC_POWER_STATE_HIGH), anyLong() /* timestampNs */, eq(PACKAGE_UID))
221         // Ims cell network goes to active state. But this should not update the cellular radio
222         // power state since cellular radio power state is already high
223         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(true /* isActive */,
224                 imsNetworkAgent.network.netId, TIMESTAMP, PACKAGE_UID)
225         waitForIdle()
226         batteryStatsInorder.verify(batteryStats, never()).noteMobileRadioPowerState(anyInt(),
227                 anyLong() /* timestampNs */, anyInt())
228 
229         // Data cell network goes to inactive state. But this should not update the cellular radio
230         // power state ims cell network is still active state
231         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
232                 dataNetworkAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
233         waitForIdle()
234         batteryStatsInorder.verify(batteryStats, never()).noteMobileRadioPowerState(anyInt(),
235                 anyLong() /* timestampNs */, anyInt())
236 
237         // Ims cell network goes to inactive state.
238         // This should update the cellular radio power state
239         netdUnsolicitedEventListener.onInterfaceClassActivityChanged(false /* isActive */,
240                 imsNetworkAgent.network.netId, TIMESTAMP, NETWORK_ACTIVITY_NO_UID)
241         batteryStatsInorder.verify(batteryStats, timeout(TIMEOUT_MS)).noteMobileRadioPowerState(
242                 eq(DC_POWER_STATE_LOW), anyLong() /* timestampNs */, eq(NETWORK_ACTIVITY_NO_UID))
243 
244         dataNetworkAgent.disconnect()
245         dataNetworkCb.expect<Lost>(dataNetworkAgent.network)
246         verify(netd).idletimerRemoveInterface(eq(DATA_CELL_IFNAME), anyInt(), eq(dataNetworkNetId))
247 
248         imsNetworkAgent.disconnect()
249         imsNetworkCb.expect<Lost>(imsNetworkAgent.network)
250         verify(netd).idletimerRemoveInterface(eq(IMS_CELL_IFNAME), anyInt(), eq(imsNetworkNetId))
251 
252         cm.unregisterNetworkCallback(dataNetworkCb)
253         cm.unregisterNetworkCallback(imsNetworkCb)
254     }
255 }
256 
expectDataActivityBroadcastnull257 internal fun CSContext.expectDataActivityBroadcast(
258         deviceType: Int,
259         isActive: Boolean,
260         tsNanos: Long
261 ) {
262     assertNotNull(orderedBroadcastAsUserHistory.poll(BROADCAST_TIMEOUT_MS) {
263         intent -> intent.action.equals(ACTION_DATA_ACTIVITY_CHANGE) &&
264             intent.getIntExtra(EXTRA_DEVICE_TYPE, -1) == deviceType &&
265             intent.getBooleanExtra(EXTRA_IS_ACTIVE, !isActive) == isActive &&
266             intent.getLongExtra(EXTRA_REALTIME_NS, -1) == tsNanos
267     })
268 }
269