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