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