1 /* 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 17 package com.android.server.connectivity; 18 19 import android.app.PendingIntent; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.net.ConnectivityManager; 23 import android.net.Network; 24 import android.net.NetworkCapabilities; 25 import android.net.NetworkInfo; 26 import android.net.NetworkMisc; 27 import android.test.suitebuilder.annotation.SmallTest; 28 import android.text.format.DateUtils; 29 import com.android.internal.R; 30 import com.android.server.ConnectivityService; 31 import com.android.server.connectivity.NetworkNotificationManager; 32 import com.android.server.connectivity.NetworkNotificationManager.NotificationType; 33 import junit.framework.TestCase; 34 import org.mockito.Mock; 35 import org.mockito.MockitoAnnotations; 36 37 import static org.mockito.Mockito.any; 38 import static org.mockito.Mockito.anyBoolean; 39 import static org.mockito.Mockito.anyInt; 40 import static org.mockito.Mockito.eq; 41 import static org.mockito.Mockito.never; 42 import static org.mockito.Mockito.times; 43 import static org.mockito.Mockito.verify; 44 import static org.mockito.Mockito.when; 45 import static org.mockito.Mockito.reset; 46 47 public class LingerMonitorTest extends TestCase { 48 static final String CELLULAR = "CELLULAR"; 49 static final String WIFI = "WIFI"; 50 51 static final long LOW_RATE_LIMIT = DateUtils.MINUTE_IN_MILLIS; 52 static final long HIGH_RATE_LIMIT = 0; 53 54 static final int LOW_DAILY_LIMIT = 2; 55 static final int HIGH_DAILY_LIMIT = 1000; 56 57 LingerMonitor mMonitor; 58 59 @Mock ConnectivityService mConnService; 60 @Mock Context mCtx; 61 @Mock NetworkMisc mMisc; 62 @Mock NetworkNotificationManager mNotifier; 63 @Mock Resources mResources; 64 65 public void setUp() { 66 MockitoAnnotations.initMocks(this); 67 when(mCtx.getResources()).thenReturn(mResources); 68 when(mCtx.getPackageName()).thenReturn("com.android.server.connectivity"); 69 when(mConnService.createNetworkMonitor(any(), any(), any(), any())).thenReturn(null); 70 71 mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT); 72 } 73 74 @SmallTest 75 public void testTransitions() { 76 setNotificationSwitch(transition(WIFI, CELLULAR)); 77 NetworkAgentInfo nai1 = wifiNai(100); 78 NetworkAgentInfo nai2 = cellNai(101); 79 80 assertTrue(mMonitor.isNotificationEnabled(nai1, nai2)); 81 assertFalse(mMonitor.isNotificationEnabled(nai2, nai1)); 82 } 83 84 @SmallTest 85 public void testNotificationOnLinger() { 86 setNotificationSwitch(transition(WIFI, CELLULAR)); 87 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); 88 NetworkAgentInfo from = wifiNai(100); 89 NetworkAgentInfo to = cellNai(101); 90 91 mMonitor.noteLingerDefaultNetwork(from, to); 92 verifyNotification(from, to); 93 } 94 95 @SmallTest 96 public void testToastOnLinger() { 97 setNotificationSwitch(transition(WIFI, CELLULAR)); 98 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); 99 NetworkAgentInfo from = wifiNai(100); 100 NetworkAgentInfo to = cellNai(101); 101 102 mMonitor.noteLingerDefaultNetwork(from, to); 103 verifyToast(from, to); 104 } 105 106 @SmallTest 107 public void testNotificationClearedAfterDisconnect() { 108 setNotificationSwitch(transition(WIFI, CELLULAR)); 109 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); 110 NetworkAgentInfo from = wifiNai(100); 111 NetworkAgentInfo to = cellNai(101); 112 113 mMonitor.noteLingerDefaultNetwork(from, to); 114 verifyNotification(from, to); 115 116 mMonitor.noteDisconnect(to); 117 verify(mNotifier, times(1)).clearNotification(100); 118 } 119 120 @SmallTest 121 public void testNotificationClearedAfterSwitchingBack() { 122 setNotificationSwitch(transition(WIFI, CELLULAR)); 123 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); 124 NetworkAgentInfo from = wifiNai(100); 125 NetworkAgentInfo to = cellNai(101); 126 127 mMonitor.noteLingerDefaultNetwork(from, to); 128 verifyNotification(from, to); 129 130 mMonitor.noteLingerDefaultNetwork(to, from); 131 verify(mNotifier, times(1)).clearNotification(100); 132 } 133 134 @SmallTest 135 public void testUniqueToast() { 136 setNotificationSwitch(transition(WIFI, CELLULAR)); 137 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); 138 NetworkAgentInfo from = wifiNai(100); 139 NetworkAgentInfo to = cellNai(101); 140 141 mMonitor.noteLingerDefaultNetwork(from, to); 142 verifyToast(from, to); 143 144 mMonitor.noteLingerDefaultNetwork(to, from); 145 verify(mNotifier, times(1)).clearNotification(100); 146 147 reset(mNotifier); 148 mMonitor.noteLingerDefaultNetwork(from, to); 149 verifyNoNotifications(); 150 } 151 152 @SmallTest 153 public void testMultipleNotifications() { 154 setNotificationSwitch(transition(WIFI, CELLULAR)); 155 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); 156 NetworkAgentInfo wifi1 = wifiNai(100); 157 NetworkAgentInfo wifi2 = wifiNai(101); 158 NetworkAgentInfo cell = cellNai(102); 159 160 mMonitor.noteLingerDefaultNetwork(wifi1, cell); 161 verifyNotification(wifi1, cell); 162 163 mMonitor.noteLingerDefaultNetwork(cell, wifi2); 164 verify(mNotifier, times(1)).clearNotification(100); 165 166 reset(mNotifier); 167 mMonitor.noteLingerDefaultNetwork(wifi2, cell); 168 verifyNotification(wifi2, cell); 169 } 170 171 @SmallTest 172 public void testRateLimiting() throws InterruptedException { 173 mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, LOW_RATE_LIMIT); 174 175 setNotificationSwitch(transition(WIFI, CELLULAR)); 176 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); 177 NetworkAgentInfo wifi1 = wifiNai(100); 178 NetworkAgentInfo wifi2 = wifiNai(101); 179 NetworkAgentInfo wifi3 = wifiNai(102); 180 NetworkAgentInfo cell = cellNai(103); 181 182 mMonitor.noteLingerDefaultNetwork(wifi1, cell); 183 verifyNotification(wifi1, cell); 184 reset(mNotifier); 185 186 Thread.sleep(50); 187 mMonitor.noteLingerDefaultNetwork(cell, wifi2); 188 mMonitor.noteLingerDefaultNetwork(wifi2, cell); 189 verifyNoNotifications(); 190 191 Thread.sleep(50); 192 mMonitor.noteLingerDefaultNetwork(cell, wifi3); 193 mMonitor.noteLingerDefaultNetwork(wifi3, cell); 194 verifyNoNotifications(); 195 } 196 197 @SmallTest 198 public void testDailyLimiting() throws InterruptedException { 199 mMonitor = new TestableLingerMonitor(mCtx, mNotifier, LOW_DAILY_LIMIT, HIGH_RATE_LIMIT); 200 201 setNotificationSwitch(transition(WIFI, CELLULAR)); 202 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); 203 NetworkAgentInfo wifi1 = wifiNai(100); 204 NetworkAgentInfo wifi2 = wifiNai(101); 205 NetworkAgentInfo wifi3 = wifiNai(102); 206 NetworkAgentInfo cell = cellNai(103); 207 208 mMonitor.noteLingerDefaultNetwork(wifi1, cell); 209 verifyNotification(wifi1, cell); 210 reset(mNotifier); 211 212 Thread.sleep(50); 213 mMonitor.noteLingerDefaultNetwork(cell, wifi2); 214 mMonitor.noteLingerDefaultNetwork(wifi2, cell); 215 verifyNotification(wifi2, cell); 216 reset(mNotifier); 217 218 Thread.sleep(50); 219 mMonitor.noteLingerDefaultNetwork(cell, wifi3); 220 mMonitor.noteLingerDefaultNetwork(wifi3, cell); 221 verifyNoNotifications(); 222 } 223 224 @SmallTest 225 public void testUniqueNotification() { 226 setNotificationSwitch(transition(WIFI, CELLULAR)); 227 setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION); 228 NetworkAgentInfo from = wifiNai(100); 229 NetworkAgentInfo to = cellNai(101); 230 231 mMonitor.noteLingerDefaultNetwork(from, to); 232 verifyNotification(from, to); 233 234 mMonitor.noteLingerDefaultNetwork(to, from); 235 verify(mNotifier, times(1)).clearNotification(100); 236 237 mMonitor.noteLingerDefaultNetwork(from, to); 238 verifyNotification(from, to); 239 } 240 241 @SmallTest 242 public void testIgnoreNeverValidatedNetworks() { 243 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); 244 setNotificationSwitch(transition(WIFI, CELLULAR)); 245 NetworkAgentInfo from = wifiNai(100); 246 NetworkAgentInfo to = cellNai(101); 247 from.everValidated = false; 248 249 mMonitor.noteLingerDefaultNetwork(from, to); 250 verifyNoNotifications(); 251 } 252 253 @SmallTest 254 public void testIgnoreCurrentlyValidatedNetworks() { 255 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); 256 setNotificationSwitch(transition(WIFI, CELLULAR)); 257 NetworkAgentInfo from = wifiNai(100); 258 NetworkAgentInfo to = cellNai(101); 259 from.lastValidated = true; 260 261 mMonitor.noteLingerDefaultNetwork(from, to); 262 verifyNoNotifications(); 263 } 264 265 @SmallTest 266 public void testNoNotificationType() { 267 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); 268 setNotificationSwitch(); 269 NetworkAgentInfo from = wifiNai(100); 270 NetworkAgentInfo to = cellNai(101); 271 272 mMonitor.noteLingerDefaultNetwork(from, to); 273 verifyNoNotifications(); 274 } 275 276 @SmallTest 277 public void testNoTransitionToNotify() { 278 setNotificationType(LingerMonitor.NOTIFY_TYPE_NONE); 279 setNotificationSwitch(transition(WIFI, CELLULAR)); 280 NetworkAgentInfo from = wifiNai(100); 281 NetworkAgentInfo to = cellNai(101); 282 283 mMonitor.noteLingerDefaultNetwork(from, to); 284 verifyNoNotifications(); 285 } 286 287 @SmallTest 288 public void testDifferentTransitionToNotify() { 289 setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST); 290 setNotificationSwitch(transition(CELLULAR, WIFI)); 291 NetworkAgentInfo from = wifiNai(100); 292 NetworkAgentInfo to = cellNai(101); 293 294 mMonitor.noteLingerDefaultNetwork(from, to); 295 verifyNoNotifications(); 296 } 297 298 void setNotificationSwitch(String... transitions) { 299 when(mResources.getStringArray(R.array.config_networkNotifySwitches)) 300 .thenReturn(transitions); 301 } 302 303 String transition(String from, String to) { 304 return from + "-" + to; 305 } 306 307 void setNotificationType(int type) { 308 when(mResources.getInteger(R.integer.config_networkNotifySwitchType)).thenReturn(type); 309 } 310 311 void verifyNoToast() { 312 verify(mNotifier, never()).showToast(any(), any()); 313 } 314 315 void verifyNoNotification() { 316 verify(mNotifier, never()) 317 .showNotification(anyInt(), any(), any(), any(), any(), anyBoolean()); 318 } 319 320 void verifyNoNotifications() { 321 verifyNoToast(); 322 verifyNoNotification(); 323 } 324 325 void verifyToast(NetworkAgentInfo from, NetworkAgentInfo to) { 326 verifyNoNotification(); 327 verify(mNotifier, times(1)).showToast(from, to); 328 } 329 330 void verifyNotification(NetworkAgentInfo from, NetworkAgentInfo to) { 331 verifyNoToast(); 332 verify(mNotifier, times(1)).showNotification(eq(from.network.netId), 333 eq(NotificationType.NETWORK_SWITCH), eq(from), eq(to), any(), eq(true)); 334 } 335 336 NetworkAgentInfo nai(int netId, int transport, int networkType, String networkTypeName) { 337 NetworkInfo info = new NetworkInfo(networkType, 0, networkTypeName, ""); 338 NetworkCapabilities caps = new NetworkCapabilities(); 339 caps.addCapability(0); 340 caps.addTransportType(transport); 341 NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, 342 caps, 50, mCtx, null, mMisc, null, mConnService); 343 nai.everValidated = true; 344 return nai; 345 } 346 347 NetworkAgentInfo wifiNai(int netId) { 348 return nai(netId, NetworkCapabilities.TRANSPORT_WIFI, 349 ConnectivityManager.TYPE_WIFI, WIFI); 350 } 351 352 NetworkAgentInfo cellNai(int netId) { 353 return nai(netId, NetworkCapabilities.TRANSPORT_CELLULAR, 354 ConnectivityManager.TYPE_MOBILE, CELLULAR); 355 } 356 357 public static class TestableLingerMonitor extends LingerMonitor { 358 public TestableLingerMonitor(Context c, NetworkNotificationManager n, int l, long r) { 359 super(c, n, l, r); 360 } 361 @Override protected PendingIntent createNotificationIntent() { 362 return null; 363 } 364 } 365 } 366