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