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