NetworkPolicyManagerServiceTest.java revision 84d156bc1a2de8d02a8d1a635d2b61b1783caef6
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_METERED_BACKGROUND;
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.never;
56import static org.mockito.Mockito.verify;
57import static org.mockito.Mockito.when;
58
59import android.Manifest;
60import android.app.ActivityManager;
61import android.app.IActivityManager;
62import android.app.INotificationManager;
63import android.app.IUidObserver;
64import android.app.Notification;
65import android.app.usage.UsageStatsManagerInternal;
66import android.content.Context;
67import android.content.Intent;
68import android.content.pm.ApplicationInfo;
69import android.content.pm.IPackageManager;
70import android.content.pm.PackageInfo;
71import android.content.pm.PackageManager;
72import android.content.pm.Signature;
73import android.net.ConnectivityManager;
74import android.net.IConnectivityManager;
75import android.net.INetworkManagementEventObserver;
76import android.net.INetworkPolicyListener;
77import android.net.INetworkStatsService;
78import android.net.LinkProperties;
79import android.net.NetworkInfo;
80import android.net.NetworkPolicyManager;
81import android.net.NetworkInfo.DetailedState;
82import android.net.NetworkPolicy;
83import android.net.NetworkState;
84import android.net.NetworkStats;
85import android.net.NetworkTemplate;
86import android.os.Binder;
87import android.os.INetworkManagementService;
88import android.os.PowerManagerInternal;
89import android.os.UserHandle;
90import android.support.test.InstrumentationRegistry;
91import android.support.test.filters.MediumTest;
92import android.support.test.runner.AndroidJUnit4;
93import android.text.TextUtils;
94import android.text.format.Time;
95import android.util.Log;
96import android.util.TrustedTime;
97
98import com.android.server.BroadcastInterceptingContext.FutureIntent;
99import com.android.server.net.NetworkPolicyManagerInternal;
100import com.android.server.net.NetworkPolicyManagerService;
101
102import libcore.io.IoUtils;
103import libcore.io.Streams;
104
105import com.google.common.util.concurrent.AbstractFuture;
106
107import org.junit.After;
108import org.junit.Before;
109import org.junit.BeforeClass;
110import org.junit.Rule;
111import org.junit.Test;
112import org.junit.rules.MethodRule;
113import org.junit.runner.RunWith;
114import org.junit.runners.model.FrameworkMethod;
115import org.junit.runners.model.Statement;
116import org.mockito.ArgumentCaptor;
117import org.mockito.Mock;
118import org.mockito.MockitoAnnotations;
119import org.mockito.invocation.InvocationOnMock;
120import org.mockito.stubbing.Answer;
121
122import java.io.File;
123import java.io.FileOutputStream;
124import java.io.InputStream;
125import java.io.OutputStream;
126import java.lang.annotation.Annotation;
127import java.lang.annotation.ElementType;
128import java.lang.annotation.Retention;
129import java.lang.annotation.RetentionPolicy;
130import java.lang.annotation.Target;
131import java.util.Arrays;
132import java.util.LinkedHashSet;
133import java.util.List;
134import java.util.concurrent.CountDownLatch;
135import java.util.concurrent.ExecutionException;
136import java.util.concurrent.Future;
137import java.util.concurrent.TimeUnit;
138import java.util.concurrent.TimeoutException;
139import java.util.stream.Collectors;
140
141/**
142 * Tests for {@link NetworkPolicyManagerService}.
143 */
144@RunWith(AndroidJUnit4.class)
145@MediumTest
146public class NetworkPolicyManagerServiceTest {
147    private static final String TAG = "NetworkPolicyManagerServiceTest";
148
149    private static final long TEST_START = 1194220800000L;
150    private static final String TEST_IFACE = "test0";
151    private static final String TEST_SSID = "AndroidAP";
152
153    private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi(TEST_SSID);
154
155    /**
156     * Path on assets where files used by {@link NetPolicyXml} are located.
157     */
158    private static final String NETPOLICY_DIR = "NetworkPolicyManagerServiceTest/netpolicy";
159
160    private BroadcastInterceptingContext mServiceContext;
161    private File mPolicyDir;
162
163    /**
164     * Relative path of the XML file that will be used as {@code netpolicy.xml}.
165     *
166     * <p>Typically set through a {@link NetPolicyXml} annotation in the test method.
167     */
168    private String mNetpolicyXml;
169
170    private @Mock IActivityManager mActivityManager;
171    private @Mock INetworkStatsService mStatsService;
172    private @Mock INetworkManagementService mNetworkManager;
173    private @Mock TrustedTime mTime;
174    private @Mock IConnectivityManager mConnManager;
175    private @Mock INotificationManager mNotifManager;
176    private @Mock PackageManager mPackageManager;
177    private @Mock IPackageManager mIpm;
178
179    private IUidObserver mUidObserver;
180    private INetworkManagementEventObserver mNetworkObserver;
181
182    private NetworkPolicyListenerAnswer mPolicyListener;
183    private NetworkPolicyManagerService mService;
184
185    private long mStartTime;
186    private long mElapsedRealtime;
187
188    private static final int USER_ID = 0;
189
190    private static final int APP_ID_A = android.os.Process.FIRST_APPLICATION_UID + 4;
191    private static final int APP_ID_B = android.os.Process.FIRST_APPLICATION_UID + 8;
192    private static final int APP_ID_C = android.os.Process.FIRST_APPLICATION_UID + 15;
193    private static final int APP_ID_D = android.os.Process.FIRST_APPLICATION_UID + 16;
194    private static final int APP_ID_E = android.os.Process.FIRST_APPLICATION_UID + 23;
195    private static final int APP_ID_F = android.os.Process.FIRST_APPLICATION_UID + 42;
196
197    private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A);
198    private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B);
199    private static final int UID_C = UserHandle.getUid(USER_ID, APP_ID_C);
200    private static final int UID_D = UserHandle.getUid(USER_ID, APP_ID_D);
201    private static final int UID_E = UserHandle.getUid(USER_ID, APP_ID_E);
202    private static final int UID_F = UserHandle.getUid(USER_ID, APP_ID_F);
203
204    private static final String PKG_NAME_A = "name.is.A,pkg.A";
205
206    public final @Rule NetPolicyMethodRule mNetPolicyXmlRule = new NetPolicyMethodRule();
207
208    @BeforeClass
209    public static void registerLocalServices() {
210        addLocalServiceMock(PowerManagerInternal.class);
211        addLocalServiceMock(DeviceIdleController.LocalService.class);
212        final UsageStatsManagerInternal usageStats =
213                addLocalServiceMock(UsageStatsManagerInternal.class);
214        when(usageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
215    }
216
217    @Before
218    public void callSystemReady() throws Exception {
219        MockitoAnnotations.initMocks(this);
220
221        final Context context = InstrumentationRegistry.getContext();
222
223        setCurrentTimeMillis(TEST_START);
224
225        // intercept various broadcasts, and pretend that uids have packages
226        mServiceContext = new BroadcastInterceptingContext(context) {
227            @Override
228            public PackageManager getPackageManager() {
229                return mPackageManager;
230            }
231
232            @Override
233            public void startActivity(Intent intent) {
234                // ignored
235            }
236        };
237
238        setNetpolicyXml(context);
239
240        doAnswer(new Answer<Void>() {
241
242            @Override
243            public Void answer(InvocationOnMock invocation) throws Throwable {
244                mUidObserver = (IUidObserver) invocation.getArguments()[0];
245                Log.d(TAG, "set mUidObserver to " + mUidObserver);
246                return null;
247            }
248        }).when(mActivityManager).registerUidObserver(any(), anyInt());
249
250        mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
251                mNetworkManager, mIpm, mTime, mPolicyDir, true);
252        mService.bindConnectivityManager(mConnManager);
253        mService.bindNotificationManager(mNotifManager);
254        mPolicyListener = new NetworkPolicyListenerAnswer(mService);
255
256        // Sets some common expectations.
257        when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer(
258                new Answer<PackageInfo>() {
259
260                    @Override
261                    public PackageInfo answer(InvocationOnMock invocation) throws Throwable {
262                        final String packageName = (String) invocation.getArguments()[0];
263                        final PackageInfo info = new PackageInfo();
264                        final Signature signature;
265                        if ("android".equals(packageName)) {
266                            signature = new Signature("F00D");
267                        } else {
268                            signature = new Signature("DEAD");
269                        }
270                        info.signatures = new Signature[] {
271                            signature
272                        };
273                        return info;
274                    }
275                });
276        when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
277                .thenReturn(new ApplicationInfo());
278        when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A});
279        when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
280        expectCurrentTime();
281
282        // Prepare NPMS.
283        mService.systemReady();
284
285        // catch INetworkManagementEventObserver during systemReady()
286        final ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
287              ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
288        verify(mNetworkManager).registerObserver(networkObserver.capture());
289        mNetworkObserver = networkObserver.getValue();
290    }
291
292    @After
293    public void removeFiles() throws Exception {
294        for (File file : mPolicyDir.listFiles()) {
295            file.delete();
296        }
297    }
298
299    @After
300    public void unregisterLocalServices() throws Exception {
301        // Registered by NetworkPolicyManagerService's constructor.
302        LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
303    }
304
305    @Test
306    public void testTurnRestrictBackgroundOn() throws Exception {
307        assertRestrictBackgroundOff(); // Sanity check.
308        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
309        setRestrictBackground(true);
310        assertRestrictBackgroundChangedReceived(futureIntent, null);
311    }
312
313    @Test
314    @NetPolicyXml("restrict-background-on.xml")
315    public void testTurnRestrictBackgroundOff() throws Exception {
316        assertRestrictBackgroundOn(); // Sanity check.
317        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
318        setRestrictBackground(false);
319        assertRestrictBackgroundChangedReceived(futureIntent, null);
320    }
321
322    /**
323     * Adds whitelist when restrict background is on - app should receive an intent.
324     */
325    @Test
326    @NetPolicyXml("restrict-background-on.xml")
327    public void testAddRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception {
328        assertRestrictBackgroundOn(); // Sanity check.
329        addRestrictBackgroundWhitelist(true);
330    }
331
332    /**
333     * Adds whitelist when restrict background is off - app should not receive an intent.
334     */
335    @Test
336    public void testAddRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception {
337        assertRestrictBackgroundOff(); // Sanity check.
338        addRestrictBackgroundWhitelist(false);
339    }
340
341    private void addRestrictBackgroundWhitelist(boolean expectIntent) throws Exception {
342        // Sanity checks.
343        assertWhitelistUids();
344        assertUidPolicy(UID_A, POLICY_NONE);
345
346        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
347        mPolicyListener.expect().onRestrictBackgroundWhitelistChanged(anyInt(), anyBoolean());
348
349        mService.setUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
350
351        assertWhitelistUids(UID_A);
352        assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
353        mPolicyListener.waitAndVerify().onRestrictBackgroundWhitelistChanged(APP_ID_A, true);
354        mPolicyListener.verifyNotCalled().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
355        if (expectIntent) {
356            assertRestrictBackgroundChangedReceived(futureIntent, PKG_NAME_A);
357        } else {
358            futureIntent.assertNotReceived();
359        }
360    }
361
362    /**
363     * Removes whitelist when restrict background is on - app should receive an intent.
364     */
365    @Test
366    @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
367    public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception {
368        assertRestrictBackgroundOn(); // Sanity check.
369        removeRestrictBackgroundWhitelist(true);
370    }
371
372    /**
373     * Removes whitelist when restrict background is off - app should not receive an intent.
374     */
375    @Test
376    @NetPolicyXml("uidA-whitelisted-restrict-background-off.xml")
377    public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception {
378        assertRestrictBackgroundOff(); // Sanity check.
379        removeRestrictBackgroundWhitelist(false);
380    }
381
382    private void removeRestrictBackgroundWhitelist(boolean expectIntent) throws Exception {
383        // Sanity checks.
384        assertWhitelistUids(UID_A);
385        assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
386
387        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
388        mPolicyListener.expect().onRestrictBackgroundWhitelistChanged(anyInt(), anyBoolean());
389
390        mService.setUidPolicy(UID_A, POLICY_NONE);
391
392        assertWhitelistUids();
393        assertUidPolicy(UID_A, POLICY_NONE);
394        mPolicyListener.waitAndVerify().onRestrictBackgroundWhitelistChanged(APP_ID_A, false);
395        mPolicyListener.verifyNotCalled().onRestrictBackgroundBlacklistChanged(APP_ID_A, false);
396        if (expectIntent) {
397            assertRestrictBackgroundChangedReceived(futureIntent, PKG_NAME_A);
398        } else {
399            futureIntent.assertNotReceived();
400        }
401    }
402
403    /**
404     * Adds blacklist when restrict background is on - app should not receive an intent.
405     */
406    @Test
407    @NetPolicyXml("restrict-background-on.xml")
408    public void testAddRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception {
409        assertRestrictBackgroundOn(); // Sanity check.
410        addRestrictBackgroundBlacklist(false);
411    }
412
413    /**
414     * Adds blacklist when restrict background is off - app should receive an intent.
415     */
416    @Test
417    public void testAddRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception {
418        assertRestrictBackgroundOff(); // Sanity check.
419        addRestrictBackgroundBlacklist(true);
420    }
421
422    private void addRestrictBackgroundBlacklist(boolean expectIntent) throws Exception {
423        assertUidPolicy(UID_A, POLICY_NONE); // Sanity check.
424        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
425        mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
426
427        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
428
429        assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
430        mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
431        mPolicyListener.verifyNotCalled().onRestrictBackgroundWhitelistChanged(APP_ID_A, true);
432        if (expectIntent) {
433            assertRestrictBackgroundChangedReceived(futureIntent, PKG_NAME_A);
434        } else {
435            futureIntent.assertNotReceived();
436        }
437    }
438
439    /**
440     * Removes blacklist when restrict background is on - app should not receive an intent.
441     */
442    @Test
443    @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml")
444    public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception {
445        assertRestrictBackgroundOn(); // Sanity check.
446        removeRestrictBackgroundBlacklist(false);
447    }
448
449    /**
450     * Removes blacklist when restrict background is off - app should receive an intent.
451     */
452    @Test
453    @NetPolicyXml("uidA-blacklisted-restrict-background-off.xml")
454    public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception {
455        assertRestrictBackgroundOff(); // Sanity check.
456        removeRestrictBackgroundBlacklist(true);
457    }
458
459    private void removeRestrictBackgroundBlacklist(boolean expectIntent) throws Exception {
460        assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND); // Sanity check.
461        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
462        mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
463
464        mService.setUidPolicy(UID_A, POLICY_NONE);
465
466        assertUidPolicy(UID_A, POLICY_NONE);
467        mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, false);
468        mPolicyListener.verifyNotCalled().onRestrictBackgroundWhitelistChanged(APP_ID_A, false);
469        if (expectIntent) {
470            assertRestrictBackgroundChangedReceived(futureIntent, PKG_NAME_A);
471        } else {
472            futureIntent.assertNotReceived();
473        }
474    }
475
476    @Test
477    @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml")
478    public void testBlacklistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
479        // Sanity checks.
480        assertRestrictBackgroundOn();
481        assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
482
483        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
484        setRestrictBackground(true);
485        futureIntent.assertNotReceived();
486    }
487
488    @Test
489    @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
490    public void testWhitelistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
491        // Sanity checks.
492        assertRestrictBackgroundOn();
493        assertWhitelistUids(UID_A);
494
495        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
496        setRestrictBackground(true);
497        futureIntent.assertNotReceived();
498    }
499
500    @Test
501    @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
502    public void testWhitelistedAppIsNotifiedWhenBlacklisted() throws Exception {
503        // Sanity checks.
504        assertRestrictBackgroundOn();
505        assertWhitelistUids(UID_A);
506
507        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
508        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
509        assertRestrictBackgroundChangedReceived(futureIntent, PKG_NAME_A);
510    }
511
512    @Test
513    @NetPolicyXml("restrict-background-lists-whitelist-format.xml")
514    public void testRestrictBackgroundLists_whitelistFormat() throws Exception {
515        restrictBackgroundListsTest();
516    }
517
518    @Test
519    @NetPolicyXml("restrict-background-lists-uid-policy-format.xml")
520    public void testRestrictBackgroundLists_uidPolicyFormat() throws Exception {
521        restrictBackgroundListsTest();
522    }
523
524    private void restrictBackgroundListsTest() throws Exception {
525        // UIds that are whitelisted.
526        assertWhitelistUids(UID_A, UID_B, UID_C);
527        assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
528        assertUidPolicy(UID_B, POLICY_ALLOW_METERED_BACKGROUND);
529        assertUidPolicy(UID_C, POLICY_ALLOW_METERED_BACKGROUND);
530
531        // UIDs that are blacklisted.
532        assertUidPolicy(UID_D, POLICY_NONE);
533        assertUidPolicy(UID_E, POLICY_REJECT_METERED_BACKGROUND);
534
535        // UIDS that have legacy policies.
536        assertUidPolicy(UID_F, 2); // POLICY_ALLOW_BACKGROUND_BATTERY_SAVE
537
538        // Remove whitelist.
539        mService.setUidPolicy(UID_A, POLICY_NONE);
540        assertUidPolicy(UID_A, POLICY_NONE);
541        assertWhitelistUids(UID_B, UID_C);
542
543        // Add whitelist when blacklisted.
544        mService.setUidPolicy(UID_E, POLICY_ALLOW_METERED_BACKGROUND);
545        assertUidPolicy(UID_E, POLICY_ALLOW_METERED_BACKGROUND);
546        assertWhitelistUids(UID_B, UID_C, UID_E);
547
548        // Add blacklist when whitelisted.
549        mService.setUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND);
550        assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND);
551        assertWhitelistUids(UID_C, UID_E);
552    }
553
554    /**
555     * Tests scenario where an UID had {@code restrict-background} and {@code uid-policy} tags.
556     */
557    @Test
558    @NetPolicyXml("restrict-background-lists-mixed-format.xml")
559    public void testRestrictBackgroundLists_mixedFormat() throws Exception {
560        assertWhitelistUids(UID_A, UID_C, UID_D);
561        assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
562        assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND); // Blacklist prevails.
563        assertUidPolicy(UID_C, (POLICY_ALLOW_METERED_BACKGROUND | 2));
564        assertUidPolicy(UID_D, POLICY_ALLOW_METERED_BACKGROUND);
565    }
566
567    @Test
568    @NetPolicyXml("uids-with-mixed-policies.xml")
569    public void testGetUidsWithPolicy() throws Exception {
570        assertContainsInAnyOrder(mService.getUidsWithPolicy(POLICY_NONE),
571                UID_A);
572        assertContainsInAnyOrder(mService.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND),
573                UID_B, UID_D);
574        assertContainsInAnyOrder(mService.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND),
575                UID_E, UID_F);
576        // Legacy (POLICY_ALLOW_BACKGROUND_BATTERY_SAVE)
577        assertContainsInAnyOrder(mService.getUidsWithPolicy(2),
578                UID_C, UID_D, UID_F);
579    }
580
581    // NOTE: testPolicyChangeTriggersListener() and testUidForeground() are too superficial, they
582    // don't check for side-effects (like calls to NetworkManagementService) neither cover all
583    // different modes (Data Saver, Battery Saver, Doze, App idle, etc...).
584    // These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests.
585
586    @Test
587    public void testPolicyChangeTriggersListener() throws Exception {
588        mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
589
590        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
591        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
592
593        mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
594    }
595
596    @Test
597    public void testUidForeground() throws Exception {
598        // push all uids into background
599        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
600        mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE);
601        assertFalse(mService.isUidForeground(UID_A));
602        assertFalse(mService.isUidForeground(UID_B));
603
604        // push one of the uids into foreground
605        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP);
606        assertTrue(mService.isUidForeground(UID_A));
607        assertFalse(mService.isUidForeground(UID_B));
608
609        // and swap another uid into foreground
610        mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
611        mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP);
612        assertFalse(mService.isUidForeground(UID_A));
613        assertTrue(mService.isUidForeground(UID_B));
614    }
615
616    @Test
617    public void testLastCycleBoundaryThisMonth() throws Exception {
618        // assume cycle day of "5th", which should be in same month
619        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
620        final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
621
622        final NetworkPolicy policy = new NetworkPolicy(
623                sTemplateWifi, 5, TIMEZONE_UTC, 1024L, 1024L, false);
624        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
625        assertTimeEquals(expectedCycle, actualCycle);
626    }
627
628    @Test
629    public void testLastCycleBoundaryLastMonth() throws Exception {
630        // assume cycle day of "20th", which should be in last month
631        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
632        final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
633
634        final NetworkPolicy policy = new NetworkPolicy(
635                sTemplateWifi, 20, TIMEZONE_UTC, 1024L, 1024L, false);
636        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
637        assertTimeEquals(expectedCycle, actualCycle);
638    }
639
640    @Test
641    public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
642        // assume cycle day of "30th" in february; should go to january
643        final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
644        final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
645
646        final NetworkPolicy policy = new NetworkPolicy(
647                sTemplateWifi, 30, TIMEZONE_UTC, 1024L, 1024L, false);
648        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
649        assertTimeEquals(expectedCycle, actualCycle);
650    }
651
652    @Test
653    public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
654        // assume cycle day of "30th" in february, which should clamp
655        final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
656        final long expectedCycle = parseTime("2007-02-28T23:59:59.000Z");
657
658        final NetworkPolicy policy = new NetworkPolicy(
659                sTemplateWifi, 30, TIMEZONE_UTC, 1024L, 1024L, false);
660        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
661        assertTimeEquals(expectedCycle, actualCycle);
662    }
663
664    @Test
665    public void testCycleBoundaryLeapYear() throws Exception {
666        final NetworkPolicy policy = new NetworkPolicy(
667                sTemplateWifi, 29, TIMEZONE_UTC, 1024L, 1024L, false);
668
669        assertTimeEquals(parseTime("2012-01-29T00:00:00.000Z"),
670                computeNextCycleBoundary(parseTime("2012-01-14T00:00:00.000Z"), policy));
671        assertTimeEquals(parseTime("2012-02-29T00:00:00.000Z"),
672                computeNextCycleBoundary(parseTime("2012-02-14T00:00:00.000Z"), policy));
673        assertTimeEquals(parseTime("2012-02-29T00:00:00.000Z"),
674                computeLastCycleBoundary(parseTime("2012-03-14T00:00:00.000Z"), policy));
675        assertTimeEquals(parseTime("2012-03-29T00:00:00.000Z"),
676                computeNextCycleBoundary(parseTime("2012-03-14T00:00:00.000Z"), policy));
677
678        assertTimeEquals(parseTime("2007-01-29T00:00:00.000Z"),
679                computeNextCycleBoundary(parseTime("2007-01-14T00:00:00.000Z"), policy));
680        assertTimeEquals(parseTime("2007-02-28T23:59:59.000Z"),
681                computeNextCycleBoundary(parseTime("2007-02-14T00:00:00.000Z"), policy));
682        assertTimeEquals(parseTime("2007-02-28T23:59:59.000Z"),
683                computeLastCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy));
684        assertTimeEquals(parseTime("2007-03-29T00:00:00.000Z"),
685                computeNextCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy));
686    }
687
688    @Test
689    public void testNextCycleTimezoneAfterUtc() throws Exception {
690        // US/Central is UTC-6
691        final NetworkPolicy policy = new NetworkPolicy(
692                sTemplateWifi, 10, "US/Central", 1024L, 1024L, false);
693        assertTimeEquals(parseTime("2012-01-10T06:00:00.000Z"),
694                computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
695    }
696
697    @Test
698    public void testNextCycleTimezoneBeforeUtc() throws Exception {
699        // Israel is UTC+2
700        final NetworkPolicy policy = new NetworkPolicy(
701                sTemplateWifi, 10, "Israel", 1024L, 1024L, false);
702        assertTimeEquals(parseTime("2012-01-09T22:00:00.000Z"),
703                computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
704    }
705
706    @Test
707    public void testNextCycleSane() throws Exception {
708        final NetworkPolicy policy = new NetworkPolicy(
709                sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
710        final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
711
712        // walk forwards, ensuring that cycle boundaries don't get stuck
713        long currentCycle = computeNextCycleBoundary(parseTime("2011-08-01T00:00:00.000Z"), policy);
714        for (int i = 0; i < 128; i++) {
715            long nextCycle = computeNextCycleBoundary(currentCycle, policy);
716            assertEqualsFuzzy(DAY_IN_MILLIS * 30, nextCycle - currentCycle, DAY_IN_MILLIS * 3);
717            assertUnique(seen, nextCycle);
718            currentCycle = nextCycle;
719        }
720    }
721
722    @Test
723    public void testLastCycleSane() throws Exception {
724        final NetworkPolicy policy = new NetworkPolicy(
725                sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
726        final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
727
728        // walk backwards, ensuring that cycle boundaries look sane
729        long currentCycle = computeLastCycleBoundary(parseTime("2011-08-04T00:00:00.000Z"), policy);
730        for (int i = 0; i < 128; i++) {
731            long lastCycle = computeLastCycleBoundary(currentCycle, policy);
732            assertEqualsFuzzy(DAY_IN_MILLIS * 30, currentCycle - lastCycle, DAY_IN_MILLIS * 3);
733            assertUnique(seen, lastCycle);
734            currentCycle = lastCycle;
735        }
736    }
737
738    @Test
739    public void testCycleTodayJanuary() throws Exception {
740        final NetworkPolicy policy = new NetworkPolicy(
741                sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false);
742
743        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
744                computeNextCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy));
745        assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"),
746                computeNextCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy));
747        assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"),
748                computeNextCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
749
750        assertTimeEquals(parseTime("2012-12-14T00:00:00.000-08:00"),
751                computeLastCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy));
752        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
753                computeLastCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy));
754        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
755                computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
756    }
757
758    @Test
759    public void testLastCycleBoundaryDST() throws Exception {
760        final long currentTime = parseTime("1989-01-02T07:30:00.000");
761        final long expectedCycle = parseTime("1988-12-03T02:00:00.000Z");
762
763        final NetworkPolicy policy = new NetworkPolicy(
764                sTemplateWifi, 3, "America/Argentina/Buenos_Aires", 1024L, 1024L, false);
765        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
766        assertTimeEquals(expectedCycle, actualCycle);
767    }
768
769    @Test
770    public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
771        NetworkState[] state = null;
772        NetworkStats stats = null;
773
774        final long TIME_FEB_15 = 1171497600000L;
775        final long TIME_MAR_10 = 1173484800000L;
776        final int CYCLE_DAY = 15;
777
778        setCurrentTimeMillis(TIME_MAR_10);
779
780        // first, pretend that wifi network comes online. no policy active,
781        // which means we shouldn't push limit to interface.
782        state = new NetworkState[] { buildWifi() };
783        when(mConnManager.getAllNetworkState()).thenReturn(state);
784        expectCurrentTime();
785
786        mPolicyListener.expect().onMeteredIfacesChanged(any());
787        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
788        mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
789
790        // now change cycle to be on 15th, and test in early march, to verify we
791        // pick cycle day in previous month.
792        when(mConnManager.getAllNetworkState()).thenReturn(state);
793        expectCurrentTime();
794
795        // pretend that 512 bytes total have happened
796        stats = new NetworkStats(getElapsedRealtime(), 1)
797                .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
798        when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
799                .thenReturn(stats.getTotalBytes());
800
801        mPolicyListener.expect().onMeteredIfacesChanged(any());
802        setNetworkPolicies(new NetworkPolicy(
803                sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
804        mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
805
806        // TODO: consider making strongly ordered mock
807        verifyPolicyDataEnable(TYPE_WIFI, true);
808        verifyRemoveInterfaceQuota(TEST_IFACE);
809        verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
810    }
811
812    @Test
813    public void testOverWarningLimitNotification() throws Exception {
814        NetworkState[] state = null;
815        NetworkStats stats = null;
816        Future<String> tagFuture = null;
817
818        final long TIME_FEB_15 = 1171497600000L;
819        final long TIME_MAR_10 = 1173484800000L;
820        final int CYCLE_DAY = 15;
821
822        setCurrentTimeMillis(TIME_MAR_10);
823
824        // assign wifi policy
825        state = new NetworkState[] {};
826        stats = new NetworkStats(getElapsedRealtime(), 1)
827                .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
828
829        {
830            expectCurrentTime();
831            when(mConnManager.getAllNetworkState()).thenReturn(state);
832            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
833                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
834
835            mPolicyListener.expect().onMeteredIfacesChanged(any());
836            setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1
837                    * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
838            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
839            verifyPolicyDataEnable(TYPE_WIFI, true);
840        }
841
842        // bring up wifi network
843        incrementCurrentTime(MINUTE_IN_MILLIS);
844        state = new NetworkState[] { buildWifi() };
845        stats = new NetworkStats(getElapsedRealtime(), 1)
846                .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
847
848        {
849            expectCurrentTime();
850            when(mConnManager.getAllNetworkState()).thenReturn(state);
851            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
852                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
853
854            mPolicyListener.expect().onMeteredIfacesChanged(any());
855            mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
856            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
857
858            verifyPolicyDataEnable(TYPE_WIFI, true);
859            verifyRemoveInterfaceQuota(TEST_IFACE);
860            verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
861        }
862
863        // go over warning, which should kick notification
864        incrementCurrentTime(MINUTE_IN_MILLIS);
865        stats = new NetworkStats(getElapsedRealtime(), 1)
866                .addIfaceValues(TEST_IFACE, 1536 * KB_IN_BYTES, 15L, 0L, 0L);
867
868        {
869            expectCurrentTime();
870            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
871                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
872            tagFuture = expectEnqueueNotification();
873
874            mNetworkObserver.limitReached(null, TEST_IFACE);
875
876            assertNotificationType(TYPE_WARNING, tagFuture.get());
877            verifyPolicyDataEnable(TYPE_WIFI, true);
878
879        }
880
881        // go over limit, which should kick notification and dialog
882        incrementCurrentTime(MINUTE_IN_MILLIS);
883        stats = new NetworkStats(getElapsedRealtime(), 1)
884                .addIfaceValues(TEST_IFACE, 5 * MB_IN_BYTES, 512L, 0L, 0L);
885
886        {
887            expectCurrentTime();
888            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
889                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
890            tagFuture = expectEnqueueNotification();
891
892            mNetworkObserver.limitReached(null, TEST_IFACE);
893
894            assertNotificationType(TYPE_LIMIT, tagFuture.get());
895            verifyPolicyDataEnable(TYPE_WIFI, false);
896        }
897
898        // now snooze policy, which should remove quota
899        incrementCurrentTime(MINUTE_IN_MILLIS);
900
901        {
902            expectCurrentTime();
903            when(mConnManager.getAllNetworkState()).thenReturn(state);
904            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
905                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
906            tagFuture = expectEnqueueNotification();
907
908            mPolicyListener.expect().onMeteredIfacesChanged(any());
909            mService.snoozeLimit(sTemplateWifi);
910            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
911
912            assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
913            // snoozed interface still has high quota so background data is
914            // still restricted.
915            verifyRemoveInterfaceQuota(TEST_IFACE);
916            verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
917            verifyPolicyDataEnable(TYPE_WIFI, true);
918        }
919    }
920
921    @Test
922    public void testMeteredNetworkWithoutLimit() throws Exception {
923        NetworkState[] state = null;
924        NetworkStats stats = null;
925
926        final long TIME_FEB_15 = 1171497600000L;
927        final long TIME_MAR_10 = 1173484800000L;
928        final int CYCLE_DAY = 15;
929
930        setCurrentTimeMillis(TIME_MAR_10);
931
932        // bring up wifi network with metered policy
933        state = new NetworkState[] { buildWifi() };
934        stats = new NetworkStats(getElapsedRealtime(), 1)
935                .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
936
937        {
938            expectCurrentTime();
939            when(mConnManager.getAllNetworkState()).thenReturn(state);
940            when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
941                    currentTimeMillis())).thenReturn(stats.getTotalBytes());
942
943            mPolicyListener.expect().onMeteredIfacesChanged(any());
944            setNetworkPolicies(new NetworkPolicy(
945                    sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED,
946                    true));
947            mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
948
949            verifyPolicyDataEnable(TYPE_WIFI, true);
950            verifyRemoveInterfaceQuota(TEST_IFACE);
951            verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
952        }
953    }
954
955    private static long parseTime(String time) {
956        final Time result = new Time();
957        result.parse3339(time);
958        return result.toMillis(true);
959    }
960
961    private void setNetworkPolicies(NetworkPolicy... policies) {
962        mService.setNetworkPolicies(policies);
963    }
964
965    private static NetworkState buildWifi() {
966        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
967        info.setDetailedState(DetailedState.CONNECTED, null, null);
968        final LinkProperties prop = new LinkProperties();
969        prop.setInterfaceName(TEST_IFACE);
970        return new NetworkState(info, prop, null, null, null, TEST_SSID);
971    }
972
973    private void expectCurrentTime() throws Exception {
974        when(mTime.forceRefresh()).thenReturn(false);
975        when(mTime.hasCache()).thenReturn(true);
976        when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
977        when(mTime.getCacheAge()).thenReturn(0L);
978        when(mTime.getCacheCertainty()).thenReturn(0L);
979    }
980
981    private Future<String> expectEnqueueNotification() throws Exception {
982        final FutureAnswer<String> futureAnswer = new FutureAnswer<String>(2);
983        doAnswer(futureAnswer).when(mNotifManager).enqueueNotificationWithTag(
984                anyString(), anyString(), anyString() /* capture here (index 2)*/,
985                anyInt(), isA(Notification.class), isA(int[].class), anyInt());
986        return futureAnswer;
987    }
988
989    private void expectHasInternetPermission(int uid, boolean hasIt) throws Exception {
990        when(mIpm.checkUidPermission(Manifest.permission.INTERNET, uid)).thenReturn(
991                hasIt ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
992    }
993
994    private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
995        verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
996    }
997
998    private void verifyRemoveInterfaceQuota(String iface) throws Exception {
999        verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface);
1000    }
1001
1002    private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception {
1003        // TODO: bring back this test
1004        return null;
1005    }
1006
1007    private void verifyAdvisePersistThreshold() throws Exception {
1008        verify(mStatsService).advisePersistThreshold(anyLong());
1009    }
1010
1011    private static class TestAbstractFuture<T> extends AbstractFuture<T> {
1012        @Override
1013        public T get() throws InterruptedException, ExecutionException {
1014            try {
1015                return get(5, TimeUnit.SECONDS);
1016            } catch (TimeoutException e) {
1017                throw new RuntimeException(e);
1018            }
1019        }
1020    }
1021
1022    private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> {
1023        private final int index;
1024
1025        FutureAnswer(int index) {
1026            this.index = index;
1027        }
1028        @Override
1029        public Void answer(InvocationOnMock invocation) throws Throwable {
1030            @SuppressWarnings("unchecked")
1031            T captured = (T) invocation.getArguments()[index];
1032            set(captured);
1033            return null;
1034        }
1035    }
1036
1037    private static void assertTimeEquals(long expected, long actual) {
1038        if (expected != actual) {
1039            fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
1040        }
1041    }
1042
1043    private static String formatTime(long millis) {
1044        final Time time = new Time(Time.TIMEZONE_UTC);
1045        time.set(millis);
1046        return time.format3339(false);
1047    }
1048
1049    private static void assertEqualsFuzzy(long expected, long actual, long fuzzy) {
1050        final long low = expected - fuzzy;
1051        final long high = expected + fuzzy;
1052        if (actual < low || actual > high) {
1053            fail("value " + actual + " is outside [" + low + "," + high + "]");
1054        }
1055    }
1056
1057    private static void assertUnique(LinkedHashSet<Long> seen, Long value) {
1058        if (!seen.add(value)) {
1059            fail("found duplicate time " + value + " in series " + seen.toString());
1060        }
1061    }
1062
1063    private static void assertNotificationType(int expected, String actualTag) {
1064        assertEquals("notification type mismatch for '" + actualTag +"'",
1065                Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
1066    }
1067
1068    private void assertUidPolicy(int uid, int expected) {
1069        final int actual = mService.getUidPolicy(uid);
1070        if (expected != actual) {
1071            fail("Wrong policy for UID " + uid + ": expected " + uidPoliciesToString(expected)
1072                    + ", actual " + uidPoliciesToString(actual));
1073        }
1074    }
1075
1076    private void assertWhitelistUids(int... uids) {
1077        assertContainsInAnyOrder(mService.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND), uids);
1078    }
1079
1080    private void assertRestrictBackgroundOn() throws Exception {
1081        assertTrue("restrictBackground should be set", mService.getRestrictBackground());
1082    }
1083
1084    private void assertRestrictBackgroundOff() throws Exception {
1085        assertFalse("restrictBackground should not be set", mService.getRestrictBackground());
1086    }
1087
1088    private FutureIntent newRestrictBackgroundChangedFuture() {
1089        return mServiceContext
1090                .nextBroadcastIntent(ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED);
1091    }
1092
1093    private void assertRestrictBackgroundChangedReceived(Future<Intent> future,
1094            String expectedPackage) throws Exception {
1095        final String action = ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
1096        final Intent intent = future.get(5, TimeUnit.SECONDS);
1097        assertNotNull("Didn't get a " + action + "intent in 5 seconds");
1098        assertEquals("Wrong package on " + action + " intent", expectedPackage, intent.getPackage());
1099    }
1100
1101    // TODO: replace by Truth, Hamcrest, or a similar tool.
1102    private void assertContainsInAnyOrder(int[] actual, int...expected) {
1103        final StringBuilder errors = new StringBuilder();
1104        if (actual.length != expected.length) {
1105            errors.append("\tsize does not match\n");
1106        }
1107        final List<Integer> actualList =
1108                Arrays.stream(actual).boxed().collect(Collectors.<Integer>toList());
1109        final List<Integer> expectedList =
1110                Arrays.stream(expected).boxed().collect(Collectors.<Integer>toList());
1111        if (!actualList.containsAll(expectedList)) {
1112            errors.append("\tmissing elements on actual list\n");
1113        }
1114        if (!expectedList.containsAll(actualList)) {
1115            errors.append("\tmissing elements on expected list\n");
1116        }
1117        if (errors.length() > 0) {
1118            fail("assertContainsInAnyOrder(expected=" + Arrays.toString(expected)
1119                    + ", actual=" + Arrays.toString(actual) +") failed: \n" + errors);
1120        }
1121    }
1122
1123    private long getElapsedRealtime() {
1124        return mElapsedRealtime;
1125    }
1126
1127    private void setCurrentTimeMillis(long currentTimeMillis) {
1128        mStartTime = currentTimeMillis;
1129        mElapsedRealtime = 0L;
1130    }
1131
1132    private long currentTimeMillis() {
1133        return mStartTime + mElapsedRealtime;
1134    }
1135
1136    private void incrementCurrentTime(long duration) {
1137        mElapsedRealtime += duration;
1138    }
1139
1140    private FutureIntent mRestrictBackgroundChanged;
1141
1142    private void setRestrictBackground(boolean flag) throws Exception {
1143        // Must set expectation, otherwise NMPS will reset value to previous one.
1144        when(mNetworkManager.setDataSaverModeEnabled(flag)).thenReturn(true);
1145        mService.setRestrictBackground(flag);
1146        // Sanity check.
1147        assertEquals("restrictBackground not set", flag, mService.getRestrictBackground());
1148    }
1149
1150    /**
1151     * Creates a mock and registers it to {@link LocalServices}.
1152     */
1153    private static <T> T addLocalServiceMock(Class<T> clazz) {
1154        final T mock = mock(clazz);
1155        LocalServices.addService(clazz, mock);
1156        return mock;
1157    }
1158
1159    /**
1160     * Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls.
1161     *
1162     * <p>Typical usage:
1163     * <pre><code>
1164     *    mPolicyListener.expect().someCallback(any());
1165     *    // do something on objects under test
1166     *    mPolicyListener.waitAndVerify().someCallback(eq(expectedValue));
1167     * </code></pre>
1168     */
1169    final class NetworkPolicyListenerAnswer implements Answer<Void> {
1170        private CountDownLatch latch;
1171        private final INetworkPolicyListener listener;
1172
1173        NetworkPolicyListenerAnswer(NetworkPolicyManagerService service) {
1174            this.listener = mock(INetworkPolicyListener.class);
1175            // RemoteCallbackList needs a binder to use as key
1176            when(listener.asBinder()).thenReturn(new Binder());
1177            service.registerListener(listener);
1178        }
1179
1180        @Override
1181        public Void answer(InvocationOnMock invocation) throws Throwable {
1182            Log.d(TAG,"counting down on answer: " + invocation);
1183            latch.countDown();
1184            return null;
1185        }
1186
1187        INetworkPolicyListener expect() {
1188            assertNull("expect() called before waitAndVerify()", latch);
1189            latch = new CountDownLatch(1);
1190            return doAnswer(this).when(listener);
1191        }
1192
1193        INetworkPolicyListener waitAndVerify() {
1194            assertNotNull("waitAndVerify() called before expect()", latch);
1195            try {
1196                assertTrue("callback not called in 5 seconds", latch.await(5, TimeUnit.SECONDS));
1197            } catch (InterruptedException e) {
1198                fail("Thread interrupted before callback called");
1199            } finally {
1200                latch = null;
1201            }
1202            return verify(listener, atLeastOnce());
1203        }
1204
1205        INetworkPolicyListener verifyNotCalled() {
1206            return verify(listener, never());
1207        }
1208
1209    }
1210
1211    private void setNetpolicyXml(Context context) throws Exception {
1212        mPolicyDir = context.getFilesDir();
1213        if (mPolicyDir.exists()) {
1214            IoUtils.deleteContents(mPolicyDir);
1215        }
1216        if (!TextUtils.isEmpty(mNetpolicyXml)) {
1217            final String assetPath = NETPOLICY_DIR + "/" + mNetpolicyXml;
1218            final File netConfigFile = new File(mPolicyDir, "netpolicy.xml");
1219            Log.d(TAG, "Creating " + netConfigFile + " from asset " + assetPath);
1220            try (final InputStream in = context.getResources().getAssets().open(assetPath);
1221                    final OutputStream out = new FileOutputStream(netConfigFile)) {
1222                Streams.copy(in, out);
1223            }
1224        }
1225    }
1226
1227    /**
1228     * Annotation used to define the relative path of the {@code netpolicy.xml} file.
1229     */
1230    @Retention(RetentionPolicy.RUNTIME)
1231    @Target(ElementType.METHOD)
1232    public @interface NetPolicyXml {
1233
1234        public String value() default "";
1235
1236    }
1237
1238    /**
1239     * Rule used to set {@code mNetPolicyXml} according to the {@link NetPolicyXml} annotation.
1240     */
1241    public static class NetPolicyMethodRule implements MethodRule {
1242
1243        @Override
1244        public Statement apply(Statement base, FrameworkMethod method, Object target) {
1245            for (Annotation annotation : method.getAnnotations()) {
1246                if ((annotation instanceof NetPolicyXml)) {
1247                    final String path = ((NetPolicyXml) annotation).value();
1248                    if (!path.isEmpty()) {
1249                        ((NetworkPolicyManagerServiceTest) target).mNetpolicyXml = path;
1250                        break;
1251                    }
1252                }
1253            }
1254            return base;
1255        }
1256    }
1257}
1258