blob: 82cb1932d2c1ea1d5512c2a345c2e3d338aadf6a [file] [log] [blame]
Hugo Benichia43a0952016-08-30 10:01:15 +09001/*
2 * Copyright (C) 2016, 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
17package com.android.server.connectivity;
18
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090019import static org.junit.Assert.assertFalse;
20import static org.junit.Assert.assertTrue;
Hugo Benichia43a0952016-08-30 10:01:15 +090021import static org.mockito.Mockito.any;
22import static org.mockito.Mockito.anyBoolean;
23import static org.mockito.Mockito.anyInt;
24import static org.mockito.Mockito.eq;
25import static org.mockito.Mockito.never;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090026import static org.mockito.Mockito.reset;
Hugo Benichia43a0952016-08-30 10:01:15 +090027import static org.mockito.Mockito.times;
28import static org.mockito.Mockito.verify;
29import static org.mockito.Mockito.when;
30
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090031import android.app.PendingIntent;
32import android.content.Context;
33import android.content.res.Resources;
34import android.net.ConnectivityManager;
Luke Huang65914772019-03-16 00:31:46 +080035import android.net.IDnsResolver;
Lorenzo Colitti9307ca22019-01-12 01:54:23 +090036import android.net.INetd;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090037import android.net.Network;
38import android.net.NetworkCapabilities;
39import android.net.NetworkInfo;
40import android.net.NetworkMisc;
Lorenzo Colitti6654b082020-01-10 00:40:28 +090041import android.net.NetworkProvider;
lucaslinc2bac512019-11-07 16:47:56 +080042import android.net.NetworkScore;
Lorenzo Colitti9307ca22019-01-12 01:54:23 +090043import android.os.INetworkManagementService;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090044import android.text.format.DateUtils;
45
Brett Chabot1ae2aa62019-03-04 14:14:56 -080046import androidx.test.filters.SmallTest;
47import androidx.test.runner.AndroidJUnit4;
48
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090049import com.android.internal.R;
50import com.android.server.ConnectivityService;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090051import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
52
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090053import org.junit.Before;
54import org.junit.Test;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090055import org.junit.runner.RunWith;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090056import org.mockito.Mock;
57import org.mockito.MockitoAnnotations;
58
59@RunWith(AndroidJUnit4.class)
60@SmallTest
61public class LingerMonitorTest {
Hugo Benichia43a0952016-08-30 10:01:15 +090062 static final String CELLULAR = "CELLULAR";
63 static final String WIFI = "WIFI";
64
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +090065 static final long LOW_RATE_LIMIT = DateUtils.MINUTE_IN_MILLIS;
66 static final long HIGH_RATE_LIMIT = 0;
67
68 static final int LOW_DAILY_LIMIT = 2;
69 static final int HIGH_DAILY_LIMIT = 1000;
70
Hugo Benichia43a0952016-08-30 10:01:15 +090071 LingerMonitor mMonitor;
72
73 @Mock ConnectivityService mConnService;
Luke Huang65914772019-03-16 00:31:46 +080074 @Mock IDnsResolver mDnsResolver;
Lorenzo Colitti9307ca22019-01-12 01:54:23 +090075 @Mock INetd mNetd;
76 @Mock INetworkManagementService mNMS;
Hugo Benichia43a0952016-08-30 10:01:15 +090077 @Mock Context mCtx;
78 @Mock NetworkMisc mMisc;
79 @Mock NetworkNotificationManager mNotifier;
80 @Mock Resources mResources;
81
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090082 @Before
Hugo Benichia43a0952016-08-30 10:01:15 +090083 public void setUp() {
84 MockitoAnnotations.initMocks(this);
85 when(mCtx.getResources()).thenReturn(mResources);
86 when(mCtx.getPackageName()).thenReturn("com.android.server.connectivity");
Hugo Benichia43a0952016-08-30 10:01:15 +090087
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +090088 mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT);
Hugo Benichia43a0952016-08-30 10:01:15 +090089 }
90
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090091 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +090092 public void testTransitions() {
93 setNotificationSwitch(transition(WIFI, CELLULAR));
94 NetworkAgentInfo nai1 = wifiNai(100);
95 NetworkAgentInfo nai2 = cellNai(101);
96
97 assertTrue(mMonitor.isNotificationEnabled(nai1, nai2));
98 assertFalse(mMonitor.isNotificationEnabled(nai2, nai1));
99 }
100
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900101 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +0900102 public void testNotificationOnLinger() {
103 setNotificationSwitch(transition(WIFI, CELLULAR));
104 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
105 NetworkAgentInfo from = wifiNai(100);
106 NetworkAgentInfo to = cellNai(101);
107
108 mMonitor.noteLingerDefaultNetwork(from, to);
109 verifyNotification(from, to);
110 }
111
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900112 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +0900113 public void testToastOnLinger() {
114 setNotificationSwitch(transition(WIFI, CELLULAR));
115 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
116 NetworkAgentInfo from = wifiNai(100);
117 NetworkAgentInfo to = cellNai(101);
118
119 mMonitor.noteLingerDefaultNetwork(from, to);
120 verifyToast(from, to);
121 }
122
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900123 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +0900124 public void testNotificationClearedAfterDisconnect() {
125 setNotificationSwitch(transition(WIFI, CELLULAR));
126 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
127 NetworkAgentInfo from = wifiNai(100);
128 NetworkAgentInfo to = cellNai(101);
129
130 mMonitor.noteLingerDefaultNetwork(from, to);
131 verifyNotification(from, to);
132
133 mMonitor.noteDisconnect(to);
134 verify(mNotifier, times(1)).clearNotification(100);
135 }
136
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900137 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +0900138 public void testNotificationClearedAfterSwitchingBack() {
139 setNotificationSwitch(transition(WIFI, CELLULAR));
140 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
141 NetworkAgentInfo from = wifiNai(100);
142 NetworkAgentInfo to = cellNai(101);
143
144 mMonitor.noteLingerDefaultNetwork(from, to);
145 verifyNotification(from, to);
146
147 mMonitor.noteLingerDefaultNetwork(to, from);
148 verify(mNotifier, times(1)).clearNotification(100);
149 }
150
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900151 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +0900152 public void testUniqueToast() {
153 setNotificationSwitch(transition(WIFI, CELLULAR));
154 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
155 NetworkAgentInfo from = wifiNai(100);
156 NetworkAgentInfo to = cellNai(101);
157
158 mMonitor.noteLingerDefaultNetwork(from, to);
159 verifyToast(from, to);
160
161 mMonitor.noteLingerDefaultNetwork(to, from);
162 verify(mNotifier, times(1)).clearNotification(100);
163
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +0900164 reset(mNotifier);
Hugo Benichia43a0952016-08-30 10:01:15 +0900165 mMonitor.noteLingerDefaultNetwork(from, to);
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +0900166 verifyNoNotifications();
167 }
168
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900169 @Test
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +0900170 public void testMultipleNotifications() {
171 setNotificationSwitch(transition(WIFI, CELLULAR));
172 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
173 NetworkAgentInfo wifi1 = wifiNai(100);
174 NetworkAgentInfo wifi2 = wifiNai(101);
175 NetworkAgentInfo cell = cellNai(102);
176
177 mMonitor.noteLingerDefaultNetwork(wifi1, cell);
178 verifyNotification(wifi1, cell);
179
180 mMonitor.noteLingerDefaultNetwork(cell, wifi2);
181 verify(mNotifier, times(1)).clearNotification(100);
182
183 reset(mNotifier);
184 mMonitor.noteLingerDefaultNetwork(wifi2, cell);
185 verifyNotification(wifi2, cell);
186 }
187
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900188 @Test
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +0900189 public void testRateLimiting() throws InterruptedException {
190 mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, LOW_RATE_LIMIT);
191
192 setNotificationSwitch(transition(WIFI, CELLULAR));
193 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
194 NetworkAgentInfo wifi1 = wifiNai(100);
195 NetworkAgentInfo wifi2 = wifiNai(101);
196 NetworkAgentInfo wifi3 = wifiNai(102);
197 NetworkAgentInfo cell = cellNai(103);
198
199 mMonitor.noteLingerDefaultNetwork(wifi1, cell);
200 verifyNotification(wifi1, cell);
201 reset(mNotifier);
202
203 Thread.sleep(50);
204 mMonitor.noteLingerDefaultNetwork(cell, wifi2);
205 mMonitor.noteLingerDefaultNetwork(wifi2, cell);
206 verifyNoNotifications();
207
208 Thread.sleep(50);
209 mMonitor.noteLingerDefaultNetwork(cell, wifi3);
210 mMonitor.noteLingerDefaultNetwork(wifi3, cell);
211 verifyNoNotifications();
212 }
213
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900214 @Test
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +0900215 public void testDailyLimiting() throws InterruptedException {
216 mMonitor = new TestableLingerMonitor(mCtx, mNotifier, LOW_DAILY_LIMIT, HIGH_RATE_LIMIT);
217
218 setNotificationSwitch(transition(WIFI, CELLULAR));
219 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
220 NetworkAgentInfo wifi1 = wifiNai(100);
221 NetworkAgentInfo wifi2 = wifiNai(101);
222 NetworkAgentInfo wifi3 = wifiNai(102);
223 NetworkAgentInfo cell = cellNai(103);
224
225 mMonitor.noteLingerDefaultNetwork(wifi1, cell);
226 verifyNotification(wifi1, cell);
227 reset(mNotifier);
228
229 Thread.sleep(50);
230 mMonitor.noteLingerDefaultNetwork(cell, wifi2);
231 mMonitor.noteLingerDefaultNetwork(wifi2, cell);
232 verifyNotification(wifi2, cell);
233 reset(mNotifier);
234
235 Thread.sleep(50);
236 mMonitor.noteLingerDefaultNetwork(cell, wifi3);
237 mMonitor.noteLingerDefaultNetwork(wifi3, cell);
238 verifyNoNotifications();
Hugo Benichia43a0952016-08-30 10:01:15 +0900239 }
240
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900241 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +0900242 public void testUniqueNotification() {
243 setNotificationSwitch(transition(WIFI, CELLULAR));
244 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
245 NetworkAgentInfo from = wifiNai(100);
246 NetworkAgentInfo to = cellNai(101);
247
248 mMonitor.noteLingerDefaultNetwork(from, to);
249 verifyNotification(from, to);
250
251 mMonitor.noteLingerDefaultNetwork(to, from);
252 verify(mNotifier, times(1)).clearNotification(100);
253
254 mMonitor.noteLingerDefaultNetwork(from, to);
255 verifyNotification(from, to);
256 }
257
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900258 @Test
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +0900259 public void testIgnoreNeverValidatedNetworks() {
Hugo Benichia43a0952016-08-30 10:01:15 +0900260 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
261 setNotificationSwitch(transition(WIFI, CELLULAR));
262 NetworkAgentInfo from = wifiNai(100);
263 NetworkAgentInfo to = cellNai(101);
264 from.everValidated = false;
265
266 mMonitor.noteLingerDefaultNetwork(from, to);
267 verifyNoNotifications();
268 }
269
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900270 @Test
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +0900271 public void testIgnoreCurrentlyValidatedNetworks() {
272 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
273 setNotificationSwitch(transition(WIFI, CELLULAR));
274 NetworkAgentInfo from = wifiNai(100);
275 NetworkAgentInfo to = cellNai(101);
276 from.lastValidated = true;
277
278 mMonitor.noteLingerDefaultNetwork(from, to);
279 verifyNoNotifications();
280 }
281
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900282 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +0900283 public void testNoNotificationType() {
284 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
285 setNotificationSwitch();
286 NetworkAgentInfo from = wifiNai(100);
287 NetworkAgentInfo to = cellNai(101);
288
289 mMonitor.noteLingerDefaultNetwork(from, to);
290 verifyNoNotifications();
291 }
292
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900293 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +0900294 public void testNoTransitionToNotify() {
295 setNotificationType(LingerMonitor.NOTIFY_TYPE_NONE);
296 setNotificationSwitch(transition(WIFI, CELLULAR));
297 NetworkAgentInfo from = wifiNai(100);
298 NetworkAgentInfo to = cellNai(101);
299
300 mMonitor.noteLingerDefaultNetwork(from, to);
301 verifyNoNotifications();
302 }
303
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900304 @Test
Hugo Benichia43a0952016-08-30 10:01:15 +0900305 public void testDifferentTransitionToNotify() {
306 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
307 setNotificationSwitch(transition(CELLULAR, WIFI));
308 NetworkAgentInfo from = wifiNai(100);
309 NetworkAgentInfo to = cellNai(101);
310
311 mMonitor.noteLingerDefaultNetwork(from, to);
312 verifyNoNotifications();
313 }
314
315 void setNotificationSwitch(String... transitions) {
316 when(mResources.getStringArray(R.array.config_networkNotifySwitches))
317 .thenReturn(transitions);
318 }
319
320 String transition(String from, String to) {
321 return from + "-" + to;
322 }
323
324 void setNotificationType(int type) {
325 when(mResources.getInteger(R.integer.config_networkNotifySwitchType)).thenReturn(type);
326 }
327
328 void verifyNoToast() {
329 verify(mNotifier, never()).showToast(any(), any());
330 }
331
332 void verifyNoNotification() {
333 verify(mNotifier, never())
334 .showNotification(anyInt(), any(), any(), any(), any(), anyBoolean());
335 }
336
337 void verifyNoNotifications() {
338 verifyNoToast();
339 verifyNoNotification();
Hugo Benichia43a0952016-08-30 10:01:15 +0900340 }
341
342 void verifyToast(NetworkAgentInfo from, NetworkAgentInfo to) {
343 verifyNoNotification();
344 verify(mNotifier, times(1)).showToast(from, to);
345 }
346
347 void verifyNotification(NetworkAgentInfo from, NetworkAgentInfo to) {
348 verifyNoToast();
349 verify(mNotifier, times(1)).showNotification(eq(from.network.netId),
350 eq(NotificationType.NETWORK_SWITCH), eq(from), eq(to), any(), eq(true));
351 }
352
353 NetworkAgentInfo nai(int netId, int transport, int networkType, String networkTypeName) {
354 NetworkInfo info = new NetworkInfo(networkType, 0, networkTypeName, "");
355 NetworkCapabilities caps = new NetworkCapabilities();
356 caps.addCapability(0);
357 caps.addTransportType(transport);
lucaslinc2bac512019-11-07 16:47:56 +0800358 NetworkScore ns = new NetworkScore();
359 ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50);
Hugo Benichia43a0952016-08-30 10:01:15 +0900360 NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
lucaslinc2bac512019-11-07 16:47:56 +0800361 caps, ns, mCtx, null, mMisc, mConnService, mNetd, mDnsResolver, mNMS,
Lorenzo Colitti6654b082020-01-10 00:40:28 +0900362 NetworkProvider.ID_NONE);
Hugo Benichia43a0952016-08-30 10:01:15 +0900363 nai.everValidated = true;
364 return nai;
365 }
366
367 NetworkAgentInfo wifiNai(int netId) {
368 return nai(netId, NetworkCapabilities.TRANSPORT_WIFI,
369 ConnectivityManager.TYPE_WIFI, WIFI);
370 }
371
372 NetworkAgentInfo cellNai(int netId) {
373 return nai(netId, NetworkCapabilities.TRANSPORT_CELLULAR,
374 ConnectivityManager.TYPE_MOBILE, CELLULAR);
375 }
376
377 public static class TestableLingerMonitor extends LingerMonitor {
Lorenzo Colitti84e6f1232016-08-29 14:03:11 +0900378 public TestableLingerMonitor(Context c, NetworkNotificationManager n, int l, long r) {
379 super(c, n, l, r);
Hugo Benichia43a0952016-08-30 10:01:15 +0900380 }
381 @Override protected PendingIntent createNotificationIntent() {
382 return null;
383 }
384 }
385}