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