NetworkPolicyManagerServiceTest.java revision 4ef40087be75b2125ee72f1347099c556d533d42
1/* 2 * Copyright (C) 2011 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; 18 19import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 20import static android.net.ConnectivityManager.TYPE_WIFI; 21import static android.net.NetworkPolicy.LIMIT_DISABLED; 22import static android.net.NetworkPolicy.WARNING_DISABLED; 23import static android.net.NetworkPolicyManager.POLICY_NONE; 24import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; 25import static android.net.NetworkPolicyManager.computeLastCycleBoundary; 26import static android.net.NetworkPolicyManager.computeNextCycleBoundary; 27import static android.net.TrafficStats.KB_IN_BYTES; 28import static android.net.TrafficStats.MB_IN_BYTES; 29import static android.text.format.DateUtils.DAY_IN_MILLIS; 30import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 31import static android.text.format.Time.TIMEZONE_UTC; 32 33import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT; 34import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED; 35import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING; 36 37import static org.mockito.Matchers.any; 38import static org.mockito.Matchers.anyBoolean; 39import static org.mockito.Matchers.anyInt; 40import static org.mockito.Matchers.anyLong; 41import static org.mockito.Matchers.anyString; 42import static org.mockito.Matchers.eq; 43import static org.mockito.Matchers.isA; 44import static org.mockito.Mockito.atLeastOnce; 45import static org.mockito.Mockito.doAnswer; 46import static org.mockito.Mockito.mock; 47import static org.mockito.Mockito.verify; 48import static org.mockito.Mockito.when; 49 50import android.app.ActivityManager; 51import android.app.IActivityManager; 52import android.app.INotificationManager; 53import android.app.IUidObserver; 54import android.app.Notification; 55import android.app.usage.UsageStatsManagerInternal; 56import android.content.Context; 57import android.content.Intent; 58import android.content.pm.ApplicationInfo; 59import android.content.pm.PackageInfo; 60import android.content.pm.PackageManager; 61import android.content.pm.Signature; 62import android.net.IConnectivityManager; 63import android.net.INetworkManagementEventObserver; 64import android.net.INetworkPolicyListener; 65import android.net.INetworkStatsService; 66import android.net.LinkProperties; 67import android.net.NetworkInfo; 68import android.net.NetworkInfo.DetailedState; 69import android.net.NetworkPolicy; 70import android.net.NetworkState; 71import android.net.NetworkStats; 72import android.net.NetworkTemplate; 73import android.os.Binder; 74import android.os.INetworkManagementService; 75import android.os.PowerManagerInternal; 76import android.os.UserHandle; 77import android.test.AndroidTestCase; 78import android.text.format.Time; 79import android.util.Log; 80import android.util.TrustedTime; 81 82import com.android.internal.util.test.BroadcastInterceptingContext; 83import com.android.server.net.NetworkPolicyManagerInternal; 84import com.android.server.net.NetworkPolicyManagerService; 85 86import libcore.io.IoUtils; 87 88import com.google.common.util.concurrent.AbstractFuture; 89 90import org.mockito.ArgumentCaptor; 91import org.mockito.Mock; 92import org.mockito.MockitoAnnotations; 93import org.mockito.invocation.InvocationOnMock; 94import org.mockito.stubbing.Answer; 95 96import java.io.File; 97import java.util.ArrayList; 98import java.util.LinkedHashSet; 99import java.util.List; 100import java.util.concurrent.CountDownLatch; 101import java.util.concurrent.ExecutionException; 102import java.util.concurrent.Future; 103import java.util.concurrent.TimeUnit; 104import java.util.concurrent.TimeoutException; 105 106/** 107 * Tests for {@link NetworkPolicyManagerService}. 108 */ 109public class NetworkPolicyManagerServiceTest extends AndroidTestCase { 110 private static final String TAG = "NetworkPolicyManagerServiceTest"; 111 112 private static final long TEST_START = 1194220800000L; 113 private static final String TEST_IFACE = "test0"; 114 private static final String TEST_SSID = "AndroidAP"; 115 116 private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi(TEST_SSID); 117 118 private BroadcastInterceptingContext mServiceContext; 119 private File mPolicyDir; 120 private List<Class<?>> mLocalServices = new ArrayList<>(); 121 122 private @Mock IActivityManager mActivityManager; 123 private @Mock INetworkStatsService mStatsService; 124 private @Mock INetworkManagementService mNetworkManager; 125 private @Mock TrustedTime mTime; 126 private @Mock IConnectivityManager mConnManager; 127 private @Mock INotificationManager mNotifManager; 128 private @Mock UsageStatsManagerInternal mUsageStats; 129 private @Mock PackageManager mPackageManager; 130 131 private IUidObserver mUidObserver; 132 private INetworkManagementEventObserver mNetworkObserver; 133 134 private NetworkPolicyListenerAnswer mPolicyListener; 135 private NetworkPolicyManagerService mService; 136 137 private long mStartTime; 138 private long mElapsedRealtime; 139 140 private static final int USER_ID = 0; 141 142 private static final int APP_ID_A = android.os.Process.FIRST_APPLICATION_UID + 800; 143 private static final int APP_ID_B = android.os.Process.FIRST_APPLICATION_UID + 801; 144 145 private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A); 146 private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B); 147 148 private static final String PKG_NAME_A = "name.is.A,pkg.A"; 149 150 public void setUp() throws Exception { 151 super.setUp(); 152 153 MockitoAnnotations.initMocks(this); 154 155 final Context context = getContext(); 156 157 setCurrentTimeMillis(TEST_START); 158 159 // intercept various broadcasts, and pretend that uids have packages 160 mServiceContext = new BroadcastInterceptingContext(context) { 161 @Override 162 public PackageManager getPackageManager() { 163 return mPackageManager; 164 } 165 166 @Override 167 public void startActivity(Intent intent) { 168 // ignored 169 } 170 }; 171 172 mPolicyDir = context.getFilesDir(); 173 if (mPolicyDir.exists()) { 174 IoUtils.deleteContents(mPolicyDir); 175 } 176 177 doAnswer(new Answer<Void>() { 178 179 @Override 180 public Void answer(InvocationOnMock invocation) throws Throwable { 181 mUidObserver = (IUidObserver) invocation.getArguments()[0]; 182 Log.d(TAG, "set mUidObserver to " + mUidObserver); 183 return null; 184 } 185 }).when(mActivityManager).registerUidObserver(any(), anyInt()); 186 187 addLocalServiceMock(PowerManagerInternal.class); 188 addLocalServiceMock(DeviceIdleController.LocalService.class); 189 addLocalServiceMock(UsageStatsManagerInternal.class, mUsageStats); 190 191 mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService, 192 mNetworkManager, mTime, mPolicyDir, true); 193 mService.bindConnectivityManager(mConnManager); 194 mService.bindNotificationManager(mNotifManager); 195 mPolicyListener = new NetworkPolicyListenerAnswer(mService); 196 197 // Sets some common expectations. 198 when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer( 199 new Answer<PackageInfo>() { 200 201 @Override 202 public PackageInfo answer(InvocationOnMock invocation) throws Throwable { 203 final String packageName = (String) invocation.getArguments()[0]; 204 final PackageInfo info = new PackageInfo(); 205 final Signature signature; 206 if ("android".equals(packageName)) { 207 signature = new Signature("F00D"); 208 } else { 209 signature = new Signature("DEAD"); 210 } 211 info.signatures = new Signature[] { 212 signature 213 }; 214 return info; 215 } 216 }); 217 when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) 218 .thenReturn(new ApplicationInfo()); 219 when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A}); 220 when(mUsageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{}); 221 when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true); 222 expectCurrentTime(); 223 224 // Prepare NPMS. 225 mService.systemReady(); 226 227 // catch INetworkManagementEventObserver during systemReady() 228 ArgumentCaptor<INetworkManagementEventObserver> networkObserver = 229 ArgumentCaptor.forClass(INetworkManagementEventObserver.class); 230 verify(mNetworkManager).registerObserver(networkObserver.capture()); 231 mNetworkObserver = networkObserver.getValue(); 232 } 233 234 public void tearDown() throws Exception { 235 for (File file : mPolicyDir.listFiles()) { 236 file.delete(); 237 } 238 239 mServiceContext = null; 240 mPolicyDir = null; 241 242 mActivityManager = null; 243 mStatsService = null; 244 mTime = null; 245 246 mService = null; 247 248 // TODO: must remove services, otherwise next test will fail. 249 // JUnit4 would avoid that hack by using a static setup. 250 removeLocalServiceMocks(); 251 252 // Added by NetworkPolicyManagerService's constructor. 253 LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class); 254 255 super.tearDown(); 256 } 257 258 // NOTE: testPolicyChangeTriggersListener() and testUidForeground() are too superficial, they 259 // don't check for side-effects (like calls to NetworkManagementService) neither cover all 260 // different modes (Data Saver, Battery Saver, Doze, App idle, etc...). 261 // These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests. 262 263 public void testPolicyChangeTriggersListener() throws Exception { 264 mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean()); 265 266 mService.setUidPolicy(APP_ID_A, POLICY_NONE); 267 mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND); 268 269 mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true); 270 } 271 272 public void testUidForeground() throws Exception { 273 // push all uids into background 274 mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE); 275 mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE); 276 assertFalse(mService.isUidForeground(UID_A)); 277 assertFalse(mService.isUidForeground(UID_B)); 278 279 // push one of the uids into foreground 280 mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP); 281 assertTrue(mService.isUidForeground(UID_A)); 282 assertFalse(mService.isUidForeground(UID_B)); 283 284 // and swap another uid into foreground 285 mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE); 286 mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP); 287 assertFalse(mService.isUidForeground(UID_A)); 288 assertTrue(mService.isUidForeground(UID_B)); 289 } 290 291 public void testLastCycleBoundaryThisMonth() throws Exception { 292 // assume cycle day of "5th", which should be in same month 293 final long currentTime = parseTime("2007-11-14T00:00:00.000Z"); 294 final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z"); 295 296 final NetworkPolicy policy = new NetworkPolicy( 297 sTemplateWifi, 5, TIMEZONE_UTC, 1024L, 1024L, false); 298 final long actualCycle = computeLastCycleBoundary(currentTime, policy); 299 assertTimeEquals(expectedCycle, actualCycle); 300 } 301 302 public void testLastCycleBoundaryLastMonth() throws Exception { 303 // assume cycle day of "20th", which should be in last month 304 final long currentTime = parseTime("2007-11-14T00:00:00.000Z"); 305 final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z"); 306 307 final NetworkPolicy policy = new NetworkPolicy( 308 sTemplateWifi, 20, TIMEZONE_UTC, 1024L, 1024L, false); 309 final long actualCycle = computeLastCycleBoundary(currentTime, policy); 310 assertTimeEquals(expectedCycle, actualCycle); 311 } 312 313 public void testLastCycleBoundaryThisMonthFebruary() throws Exception { 314 // assume cycle day of "30th" in february; should go to january 315 final long currentTime = parseTime("2007-02-14T00:00:00.000Z"); 316 final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z"); 317 318 final NetworkPolicy policy = new NetworkPolicy( 319 sTemplateWifi, 30, TIMEZONE_UTC, 1024L, 1024L, false); 320 final long actualCycle = computeLastCycleBoundary(currentTime, policy); 321 assertTimeEquals(expectedCycle, actualCycle); 322 } 323 324 public void testLastCycleBoundaryLastMonthFebruary() throws Exception { 325 // assume cycle day of "30th" in february, which should clamp 326 final long currentTime = parseTime("2007-03-14T00:00:00.000Z"); 327 final long expectedCycle = parseTime("2007-02-28T23:59:59.000Z"); 328 329 final NetworkPolicy policy = new NetworkPolicy( 330 sTemplateWifi, 30, TIMEZONE_UTC, 1024L, 1024L, false); 331 final long actualCycle = computeLastCycleBoundary(currentTime, policy); 332 assertTimeEquals(expectedCycle, actualCycle); 333 } 334 335 public void testCycleBoundaryLeapYear() throws Exception { 336 final NetworkPolicy policy = new NetworkPolicy( 337 sTemplateWifi, 29, TIMEZONE_UTC, 1024L, 1024L, false); 338 339 assertTimeEquals(parseTime("2012-01-29T00:00:00.000Z"), 340 computeNextCycleBoundary(parseTime("2012-01-14T00:00:00.000Z"), policy)); 341 assertTimeEquals(parseTime("2012-02-29T00:00:00.000Z"), 342 computeNextCycleBoundary(parseTime("2012-02-14T00:00:00.000Z"), policy)); 343 assertTimeEquals(parseTime("2012-02-29T00:00:00.000Z"), 344 computeLastCycleBoundary(parseTime("2012-03-14T00:00:00.000Z"), policy)); 345 assertTimeEquals(parseTime("2012-03-29T00:00:00.000Z"), 346 computeNextCycleBoundary(parseTime("2012-03-14T00:00:00.000Z"), policy)); 347 348 assertTimeEquals(parseTime("2007-01-29T00:00:00.000Z"), 349 computeNextCycleBoundary(parseTime("2007-01-14T00:00:00.000Z"), policy)); 350 assertTimeEquals(parseTime("2007-02-28T23:59:59.000Z"), 351 computeNextCycleBoundary(parseTime("2007-02-14T00:00:00.000Z"), policy)); 352 assertTimeEquals(parseTime("2007-02-28T23:59:59.000Z"), 353 computeLastCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy)); 354 assertTimeEquals(parseTime("2007-03-29T00:00:00.000Z"), 355 computeNextCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy)); 356 } 357 358 public void testNextCycleTimezoneAfterUtc() throws Exception { 359 // US/Central is UTC-6 360 final NetworkPolicy policy = new NetworkPolicy( 361 sTemplateWifi, 10, "US/Central", 1024L, 1024L, false); 362 assertTimeEquals(parseTime("2012-01-10T06:00:00.000Z"), 363 computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy)); 364 } 365 366 public void testNextCycleTimezoneBeforeUtc() throws Exception { 367 // Israel is UTC+2 368 final NetworkPolicy policy = new NetworkPolicy( 369 sTemplateWifi, 10, "Israel", 1024L, 1024L, false); 370 assertTimeEquals(parseTime("2012-01-09T22:00:00.000Z"), 371 computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy)); 372 } 373 374 public void testNextCycleSane() throws Exception { 375 final NetworkPolicy policy = new NetworkPolicy( 376 sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false); 377 final LinkedHashSet<Long> seen = new LinkedHashSet<Long>(); 378 379 // walk forwards, ensuring that cycle boundaries don't get stuck 380 long currentCycle = computeNextCycleBoundary(parseTime("2011-08-01T00:00:00.000Z"), policy); 381 for (int i = 0; i < 128; i++) { 382 long nextCycle = computeNextCycleBoundary(currentCycle, policy); 383 assertEqualsFuzzy(DAY_IN_MILLIS * 30, nextCycle - currentCycle, DAY_IN_MILLIS * 3); 384 assertUnique(seen, nextCycle); 385 currentCycle = nextCycle; 386 } 387 } 388 389 public void testLastCycleSane() throws Exception { 390 final NetworkPolicy policy = new NetworkPolicy( 391 sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false); 392 final LinkedHashSet<Long> seen = new LinkedHashSet<Long>(); 393 394 // walk backwards, ensuring that cycle boundaries look sane 395 long currentCycle = computeLastCycleBoundary(parseTime("2011-08-04T00:00:00.000Z"), policy); 396 for (int i = 0; i < 128; i++) { 397 long lastCycle = computeLastCycleBoundary(currentCycle, policy); 398 assertEqualsFuzzy(DAY_IN_MILLIS * 30, currentCycle - lastCycle, DAY_IN_MILLIS * 3); 399 assertUnique(seen, lastCycle); 400 currentCycle = lastCycle; 401 } 402 } 403 404 public void testCycleTodayJanuary() throws Exception { 405 final NetworkPolicy policy = new NetworkPolicy( 406 sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false); 407 408 assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"), 409 computeNextCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy)); 410 assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"), 411 computeNextCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy)); 412 assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"), 413 computeNextCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy)); 414 415 assertTimeEquals(parseTime("2012-12-14T00:00:00.000-08:00"), 416 computeLastCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy)); 417 assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"), 418 computeLastCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy)); 419 assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"), 420 computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy)); 421 } 422 423 public void testLastCycleBoundaryDST() throws Exception { 424 final long currentTime = parseTime("1989-01-02T07:30:00.000"); 425 final long expectedCycle = parseTime("1988-12-03T02:00:00.000Z"); 426 427 final NetworkPolicy policy = new NetworkPolicy( 428 sTemplateWifi, 3, "America/Argentina/Buenos_Aires", 1024L, 1024L, false); 429 final long actualCycle = computeLastCycleBoundary(currentTime, policy); 430 assertTimeEquals(expectedCycle, actualCycle); 431 } 432 433 public void testNetworkPolicyAppliedCycleLastMonth() throws Exception { 434 NetworkState[] state = null; 435 NetworkStats stats = null; 436 437 final long TIME_FEB_15 = 1171497600000L; 438 final long TIME_MAR_10 = 1173484800000L; 439 final int CYCLE_DAY = 15; 440 441 setCurrentTimeMillis(TIME_MAR_10); 442 443 // first, pretend that wifi network comes online. no policy active, 444 // which means we shouldn't push limit to interface. 445 state = new NetworkState[] { buildWifi() }; 446 when(mConnManager.getAllNetworkState()).thenReturn(state); 447 expectCurrentTime(); 448 449 mPolicyListener.expect().onMeteredIfacesChanged(any()); 450 mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); 451 mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any()); 452 453 // now change cycle to be on 15th, and test in early march, to verify we 454 // pick cycle day in previous month. 455 when(mConnManager.getAllNetworkState()).thenReturn(state); 456 expectCurrentTime(); 457 458 // pretend that 512 bytes total have happened 459 stats = new NetworkStats(getElapsedRealtime(), 1) 460 .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L); 461 when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10)) 462 .thenReturn(stats.getTotalBytes()); 463 464 mPolicyListener.expect().onMeteredIfacesChanged(any()); 465 setNetworkPolicies(new NetworkPolicy( 466 sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false)); 467 mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE})); 468 469 // TODO: consider making strongly ordered mock 470 verifyPolicyDataEnable(TYPE_WIFI, true); 471 verifyRemoveInterfaceQuota(TEST_IFACE); 472 verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512); 473 } 474 475 public void testOverWarningLimitNotification() throws Exception { 476 NetworkState[] state = null; 477 NetworkStats stats = null; 478 Future<String> tagFuture = null; 479 480 final long TIME_FEB_15 = 1171497600000L; 481 final long TIME_MAR_10 = 1173484800000L; 482 final int CYCLE_DAY = 15; 483 484 setCurrentTimeMillis(TIME_MAR_10); 485 486 // assign wifi policy 487 state = new NetworkState[] {}; 488 stats = new NetworkStats(getElapsedRealtime(), 1) 489 .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L); 490 491 { 492 expectCurrentTime(); 493 when(mConnManager.getAllNetworkState()).thenReturn(state); 494 when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, 495 currentTimeMillis())).thenReturn(stats.getTotalBytes()); 496 497 mPolicyListener.expect().onMeteredIfacesChanged(any()); 498 setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 499 * MB_IN_BYTES, 2 * MB_IN_BYTES, false)); 500 mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any()); 501 verifyPolicyDataEnable(TYPE_WIFI, true); 502 } 503 504 // bring up wifi network 505 incrementCurrentTime(MINUTE_IN_MILLIS); 506 state = new NetworkState[] { buildWifi() }; 507 stats = new NetworkStats(getElapsedRealtime(), 1) 508 .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L); 509 510 { 511 expectCurrentTime(); 512 when(mConnManager.getAllNetworkState()).thenReturn(state); 513 when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, 514 currentTimeMillis())).thenReturn(stats.getTotalBytes()); 515 516 mPolicyListener.expect().onMeteredIfacesChanged(any()); 517 mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); 518 mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE})); 519 520 verifyPolicyDataEnable(TYPE_WIFI, true); 521 verifyRemoveInterfaceQuota(TEST_IFACE); 522 verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES); 523 } 524 525 // go over warning, which should kick notification 526 incrementCurrentTime(MINUTE_IN_MILLIS); 527 stats = new NetworkStats(getElapsedRealtime(), 1) 528 .addIfaceValues(TEST_IFACE, 1536 * KB_IN_BYTES, 15L, 0L, 0L); 529 530 { 531 expectCurrentTime(); 532 when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, 533 currentTimeMillis())).thenReturn(stats.getTotalBytes()); 534 tagFuture = expectEnqueueNotification(); 535 536 mNetworkObserver.limitReached(null, TEST_IFACE); 537 538 assertNotificationType(TYPE_WARNING, tagFuture.get()); 539 verifyPolicyDataEnable(TYPE_WIFI, true); 540 541 } 542 543 // go over limit, which should kick notification and dialog 544 incrementCurrentTime(MINUTE_IN_MILLIS); 545 stats = new NetworkStats(getElapsedRealtime(), 1) 546 .addIfaceValues(TEST_IFACE, 5 * MB_IN_BYTES, 512L, 0L, 0L); 547 548 { 549 expectCurrentTime(); 550 when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, 551 currentTimeMillis())).thenReturn(stats.getTotalBytes()); 552 tagFuture = expectEnqueueNotification(); 553 554 mNetworkObserver.limitReached(null, TEST_IFACE); 555 556 assertNotificationType(TYPE_LIMIT, tagFuture.get()); 557 verifyPolicyDataEnable(TYPE_WIFI, false); 558 } 559 560 // now snooze policy, which should remove quota 561 incrementCurrentTime(MINUTE_IN_MILLIS); 562 563 { 564 expectCurrentTime(); 565 when(mConnManager.getAllNetworkState()).thenReturn(state); 566 when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, 567 currentTimeMillis())).thenReturn(stats.getTotalBytes()); 568 tagFuture = expectEnqueueNotification(); 569 570 mPolicyListener.expect().onMeteredIfacesChanged(any()); 571 mService.snoozeLimit(sTemplateWifi); 572 mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE})); 573 574 assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get()); 575 // snoozed interface still has high quota so background data is 576 // still restricted. 577 verifyRemoveInterfaceQuota(TEST_IFACE); 578 verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE); 579 verifyPolicyDataEnable(TYPE_WIFI, true); 580 } 581 } 582 583 public void testMeteredNetworkWithoutLimit() throws Exception { 584 NetworkState[] state = null; 585 NetworkStats stats = null; 586 587 final long TIME_FEB_15 = 1171497600000L; 588 final long TIME_MAR_10 = 1173484800000L; 589 final int CYCLE_DAY = 15; 590 591 setCurrentTimeMillis(TIME_MAR_10); 592 593 // bring up wifi network with metered policy 594 state = new NetworkState[] { buildWifi() }; 595 stats = new NetworkStats(getElapsedRealtime(), 1) 596 .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L); 597 598 { 599 expectCurrentTime(); 600 when(mConnManager.getAllNetworkState()).thenReturn(state); 601 when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, 602 currentTimeMillis())).thenReturn(stats.getTotalBytes()); 603 604 mPolicyListener.expect().onMeteredIfacesChanged(any()); 605 setNetworkPolicies(new NetworkPolicy( 606 sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, 607 true)); 608 mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE})); 609 610 verifyPolicyDataEnable(TYPE_WIFI, true); 611 verifyRemoveInterfaceQuota(TEST_IFACE); 612 verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE); 613 } 614 } 615 616 private static long parseTime(String time) { 617 final Time result = new Time(); 618 result.parse3339(time); 619 return result.toMillis(true); 620 } 621 622 private void setNetworkPolicies(NetworkPolicy... policies) { 623 mService.setNetworkPolicies(policies); 624 } 625 626 private static NetworkState buildWifi() { 627 final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null); 628 info.setDetailedState(DetailedState.CONNECTED, null, null); 629 final LinkProperties prop = new LinkProperties(); 630 prop.setInterfaceName(TEST_IFACE); 631 return new NetworkState(info, prop, null, null, null, TEST_SSID); 632 } 633 634 private void expectCurrentTime() throws Exception { 635 when(mTime.forceRefresh()).thenReturn(false); 636 when(mTime.hasCache()).thenReturn(true); 637 when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis()); 638 when(mTime.getCacheAge()).thenReturn(0L); 639 when(mTime.getCacheCertainty()).thenReturn(0L); 640 } 641 642 private Future<String> expectEnqueueNotification() throws Exception { 643 final FutureAnswer<String> futureAnswer = new FutureAnswer<String>(2); 644 doAnswer(futureAnswer).when(mNotifManager).enqueueNotificationWithTag( 645 anyString(), anyString(), anyString() /* capture here (index 2)*/, 646 anyInt(), isA(Notification.class), isA(int[].class), anyInt()); 647 return futureAnswer; 648 } 649 650 private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception { 651 verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes); 652 } 653 654 private void verifyRemoveInterfaceQuota(String iface) throws Exception { 655 verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface); 656 } 657 658 private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception { 659 // TODO: bring back this test 660 return null; 661 } 662 663 private void verifyAdvisePersistThreshold() throws Exception { 664 verify(mStatsService).advisePersistThreshold(anyLong()); 665 } 666 667 private static class TestAbstractFuture<T> extends AbstractFuture<T> { 668 @Override 669 public T get() throws InterruptedException, ExecutionException { 670 try { 671 return get(5, TimeUnit.SECONDS); 672 } catch (TimeoutException e) { 673 throw new RuntimeException(e); 674 } 675 } 676 } 677 678 private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> { 679 private final int index; 680 681 FutureAnswer(int index) { 682 this.index = index; 683 } 684 @Override 685 public Void answer(InvocationOnMock invocation) throws Throwable { 686 @SuppressWarnings("unchecked") 687 T captured = (T) invocation.getArguments()[index]; 688 set(captured); 689 return null; 690 } 691 } 692 693 private static void assertTimeEquals(long expected, long actual) { 694 if (expected != actual) { 695 fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual)); 696 } 697 } 698 699 private static String formatTime(long millis) { 700 final Time time = new Time(Time.TIMEZONE_UTC); 701 time.set(millis); 702 return time.format3339(false); 703 } 704 705 private static void assertEqualsFuzzy(long expected, long actual, long fuzzy) { 706 final long low = expected - fuzzy; 707 final long high = expected + fuzzy; 708 if (actual < low || actual > high) { 709 fail("value " + actual + " is outside [" + low + "," + high + "]"); 710 } 711 } 712 713 private static void assertUnique(LinkedHashSet<Long> seen, Long value) { 714 if (!seen.add(value)) { 715 fail("found duplicate time " + value + " in series " + seen.toString()); 716 } 717 } 718 719 private static void assertNotificationType(int expected, String actualTag) { 720 assertEquals("notification type mismatch for '" + actualTag +"'", 721 Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1)); 722 } 723 724 private long getElapsedRealtime() { 725 return mElapsedRealtime; 726 } 727 728 private void setCurrentTimeMillis(long currentTimeMillis) { 729 mStartTime = currentTimeMillis; 730 mElapsedRealtime = 0L; 731 } 732 733 private long currentTimeMillis() { 734 return mStartTime + mElapsedRealtime; 735 } 736 737 private void incrementCurrentTime(long duration) { 738 mElapsedRealtime += duration; 739 } 740 741 /** 742 * Creates a mock and registers it to {@link LocalServices}. 743 */ 744 private <T> T addLocalServiceMock(Class<T> clazz) { 745 final T mock = mock(clazz); 746 return addLocalServiceMock(clazz, mock); 747 } 748 749 /** 750 * Registers a mock to {@link LocalServices}. 751 */ 752 private <T> T addLocalServiceMock(Class<T> clazz, T mock) { 753 LocalServices.addService(clazz, mock); 754 mLocalServices.add(clazz); 755 return mock; 756 } 757 758 /** 759 * Unregisters all mocks from {@link LocalServices}. 760 */ 761 private void removeLocalServiceMocks() { 762 for (Class<?> clazz : mLocalServices) { 763 Log.d(TAG, "removeLocalServiceMock(): " + clazz.getName()); 764 LocalServices.removeServiceForTest(clazz); 765 } 766 mLocalServices.clear(); 767 } 768 769 /** 770 * Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls. 771 * 772 * <p>Typical usage: 773 * <pre><code> 774 * mPolicyListener.expect().someCallback(any()); 775 * // do something on objects under test 776 * mPolicyListener.waitAndVerify().someCallback(eq(expectedValue)); 777 * </code></pre> 778 */ 779 final class NetworkPolicyListenerAnswer implements Answer<Void> { 780 private CountDownLatch latch; 781 private final INetworkPolicyListener listener; 782 783 NetworkPolicyListenerAnswer(NetworkPolicyManagerService service) { 784 this.listener = mock(INetworkPolicyListener.class); 785 // RemoteCallbackList needs a binder to use as key 786 when(listener.asBinder()).thenReturn(new Binder()); 787 service.registerListener(listener); 788 } 789 790 @Override 791 public Void answer(InvocationOnMock invocation) throws Throwable { 792 Log.d(TAG,"counting down on answer: " + invocation); 793 latch.countDown(); 794 return null; 795 } 796 797 INetworkPolicyListener expect() { 798 assertNull("expect() called before waitAndVerify()", latch); 799 latch = new CountDownLatch(1); 800 return doAnswer(this).when(listener); 801 } 802 803 INetworkPolicyListener waitAndVerify() { 804 assertNotNull("waitAndVerify() called before expect()", latch); 805 try { 806 assertTrue("callback not called in 5 seconds", latch.await(5, TimeUnit.SECONDS)); 807 } catch (InterruptedException e) { 808 fail("Thread interrupted before callback called"); 809 } finally { 810 latch = null; 811 } 812 return verify(listener, atLeastOnce()); 813 } 814 } 815} 816