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