NetworkPolicyManagerServiceTest.java revision 21b5ee3f0e39be4a79bcfb2b79b0529f75f5cb58
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.content.Intent.ACTION_UID_REMOVED;
20import static android.content.Intent.EXTRA_UID;
21import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
22import static android.net.ConnectivityManager.TYPE_WIFI;
23import static android.net.NetworkPolicy.LIMIT_DISABLED;
24import static android.net.NetworkPolicy.WARNING_DISABLED;
25import static android.net.NetworkPolicyManager.POLICY_NONE;
26import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
27import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
28import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
29import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
30import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
31import static android.net.TrafficStats.KB_IN_BYTES;
32import static android.net.TrafficStats.MB_IN_BYTES;
33import static android.text.format.DateUtils.DAY_IN_MILLIS;
34import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
35import static android.text.format.Time.TIMEZONE_UTC;
36import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
37import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
38import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
39import static org.easymock.EasyMock.anyInt;
40import static org.easymock.EasyMock.anyLong;
41import static org.easymock.EasyMock.aryEq;
42import static org.easymock.EasyMock.capture;
43import static org.easymock.EasyMock.createMock;
44import static org.easymock.EasyMock.eq;
45import static org.easymock.EasyMock.expect;
46import static org.easymock.EasyMock.expectLastCall;
47import static org.easymock.EasyMock.isA;
48
49import android.app.IActivityManager;
50import android.app.INotificationManager;
51import android.app.IProcessObserver;
52import android.app.Notification;
53import android.content.Intent;
54import android.content.pm.PackageInfo;
55import android.content.pm.PackageManager;
56import android.content.pm.Signature;
57import android.net.ConnectivityManager;
58import android.net.IConnectivityManager;
59import android.net.INetworkManagementEventObserver;
60import android.net.INetworkPolicyListener;
61import android.net.INetworkStatsService;
62import android.net.LinkProperties;
63import android.net.NetworkInfo;
64import android.net.NetworkInfo.DetailedState;
65import android.net.NetworkPolicy;
66import android.net.NetworkState;
67import android.net.NetworkStats;
68import android.net.NetworkTemplate;
69import android.os.Binder;
70import android.os.INetworkManagementService;
71import android.os.IPowerManager;
72import android.os.MessageQueue.IdleHandler;
73import android.os.UserHandle;
74import android.test.AndroidTestCase;
75import android.test.mock.MockPackageManager;
76import android.test.suitebuilder.annotation.LargeTest;
77import android.test.suitebuilder.annotation.Suppress;
78import android.text.format.Time;
79import android.util.TrustedTime;
80
81import com.android.server.net.NetworkPolicyManagerService;
82import com.google.common.util.concurrent.AbstractFuture;
83
84import org.easymock.Capture;
85import org.easymock.EasyMock;
86import org.easymock.IAnswer;
87
88import java.io.File;
89import java.util.LinkedHashSet;
90import java.util.concurrent.ExecutionException;
91import java.util.concurrent.Future;
92import java.util.concurrent.TimeUnit;
93import java.util.concurrent.TimeoutException;
94import java.util.logging.Handler;
95
96import libcore.io.IoUtils;
97
98/**
99 * Tests for {@link NetworkPolicyManagerService}.
100 */
101@LargeTest
102public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
103    private static final String TAG = "NetworkPolicyManagerServiceTest";
104
105    private static final long TEST_START = 1194220800000L;
106    private static final String TEST_IFACE = "test0";
107    private static final String TEST_SSID = "AndroidAP";
108
109    private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi(TEST_SSID);
110
111    private BroadcastInterceptingContext mServiceContext;
112    private File mPolicyDir;
113
114    private IActivityManager mActivityManager;
115    private IPowerManager mPowerManager;
116    private INetworkStatsService mStatsService;
117    private INetworkManagementService mNetworkManager;
118    private INetworkPolicyListener mPolicyListener;
119    private TrustedTime mTime;
120    private IConnectivityManager mConnManager;
121    private INotificationManager mNotifManager;
122
123    private NetworkPolicyManagerService mService;
124    private IProcessObserver mProcessObserver;
125    private INetworkManagementEventObserver mNetworkObserver;
126
127    private Binder mStubBinder = new Binder();
128
129    private long mStartTime;
130    private long mElapsedRealtime;
131
132    private static final int USER_ID = 0;
133
134    private static final int APP_ID_A = android.os.Process.FIRST_APPLICATION_UID + 800;
135    private static final int APP_ID_B = android.os.Process.FIRST_APPLICATION_UID + 801;
136
137    private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A);
138    private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B);
139
140    private static final int PID_1 = 400;
141    private static final int PID_2 = 401;
142    private static final int PID_3 = 402;
143
144    @Override
145    public void setUp() throws Exception {
146        super.setUp();
147
148        setCurrentTimeMillis(TEST_START);
149
150        // intercept various broadcasts, and pretend that uids have packages
151        mServiceContext = new BroadcastInterceptingContext(getContext()) {
152            @Override
153            public PackageManager getPackageManager() {
154                return new MockPackageManager() {
155                    @Override
156                    public String[] getPackagesForUid(int uid) {
157                        return new String[] { "com.example" };
158                    }
159
160                    @Override
161                    public PackageInfo getPackageInfo(String packageName, int flags) {
162                        final PackageInfo info = new PackageInfo();
163                        final Signature signature;
164                        if ("android".equals(packageName)) {
165                            signature = new Signature("F00D");
166                        } else {
167                            signature = new Signature("DEAD");
168                        }
169                        info.signatures = new Signature[] { signature };
170                        return info;
171                    }
172
173                };
174            }
175
176            @Override
177            public void startActivity(Intent intent) {
178                // ignored
179            }
180        };
181
182        mPolicyDir = getContext().getFilesDir();
183        if (mPolicyDir.exists()) {
184            IoUtils.deleteContents(mPolicyDir);
185        }
186
187        mActivityManager = createMock(IActivityManager.class);
188        mPowerManager = createMock(IPowerManager.class);
189        mStatsService = createMock(INetworkStatsService.class);
190        mNetworkManager = createMock(INetworkManagementService.class);
191        mPolicyListener = createMock(INetworkPolicyListener.class);
192        mTime = createMock(TrustedTime.class);
193        mConnManager = createMock(IConnectivityManager.class);
194        mNotifManager = createMock(INotificationManager.class);
195
196        mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mPowerManager,
197                mStatsService, mNetworkManager, mTime, mPolicyDir, true);
198        mService.bindConnectivityManager(mConnManager);
199        mService.bindNotificationManager(mNotifManager);
200
201        // RemoteCallbackList needs a binder to use as key
202        expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
203        replay();
204        mService.registerListener(mPolicyListener);
205        verifyAndReset();
206
207        // catch IProcessObserver during systemReady()
208        final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
209        mActivityManager.registerProcessObserver(capture(processObserver));
210        expectLastCall().atLeastOnce();
211
212        // catch INetworkManagementEventObserver during systemReady()
213        final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
214                INetworkManagementEventObserver>();
215        mNetworkManager.registerObserver(capture(networkObserver));
216        expectLastCall().atLeastOnce();
217
218        // expect to answer screen status during systemReady()
219        expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
220        expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
221        expectCurrentTime();
222
223        replay();
224        mService.systemReady();
225        verifyAndReset();
226
227        mProcessObserver = processObserver.getValue();
228        mNetworkObserver = networkObserver.getValue();
229
230    }
231
232    @Override
233    public void tearDown() throws Exception {
234        for (File file : mPolicyDir.listFiles()) {
235            file.delete();
236        }
237
238        mServiceContext = null;
239        mPolicyDir = null;
240
241        mActivityManager = null;
242        mPowerManager = null;
243        mStatsService = null;
244        mPolicyListener = null;
245        mTime = null;
246
247        mService = null;
248        mProcessObserver = null;
249
250        super.tearDown();
251    }
252
253    @Suppress
254    public void testPolicyChangeTriggersBroadcast() throws Exception {
255        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
256
257        // change background policy and expect broadcast
258        final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
259                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
260
261        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
262
263        backgroundChanged.get();
264    }
265
266    public void testPidForegroundCombined() throws Exception {
267        IdleFuture idle;
268
269        // push all uid into background
270        idle = expectIdle();
271        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
272        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
273        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
274        idle.get();
275        assertFalse(mService.isUidForeground(UID_A));
276        assertFalse(mService.isUidForeground(UID_B));
277
278        // push one of the shared pids into foreground
279        idle = expectIdle();
280        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
281        idle.get();
282        assertTrue(mService.isUidForeground(UID_A));
283        assertFalse(mService.isUidForeground(UID_B));
284
285        // and swap another uid into foreground
286        idle = expectIdle();
287        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
288        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
289        idle.get();
290        assertFalse(mService.isUidForeground(UID_A));
291        assertTrue(mService.isUidForeground(UID_B));
292
293        // push both pid into foreground
294        idle = expectIdle();
295        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
296        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
297        idle.get();
298        assertTrue(mService.isUidForeground(UID_A));
299
300        // pull one out, should still be foreground
301        idle = expectIdle();
302        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
303        idle.get();
304        assertTrue(mService.isUidForeground(UID_A));
305
306        // pull final pid out, should now be background
307        idle = expectIdle();
308        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
309        idle.get();
310        assertFalse(mService.isUidForeground(UID_A));
311    }
312
313    public void testScreenChangesRules() throws Exception {
314        Future<Void> future;
315
316        expectSetUidNetworkRules(UID_A, false);
317        expectSetUidForeground(UID_A, true);
318        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
319        replay();
320        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
321        future.get();
322        verifyAndReset();
323
324        // push strict policy for foreground uid, verify ALLOW rule
325        expectSetUidNetworkRules(UID_A, false);
326        expectSetUidForeground(UID_A, true);
327        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
328        replay();
329        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
330        future.get();
331        verifyAndReset();
332
333        // now turn screen off and verify REJECT rule
334        expect(mPowerManager.isInteractive()).andReturn(false).atLeastOnce();
335        expectSetUidNetworkRules(UID_A, true);
336        expectSetUidForeground(UID_A, false);
337        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
338        replay();
339        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
340        future.get();
341        verifyAndReset();
342
343        // and turn screen back on, verify ALLOW rule restored
344        expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
345        expectSetUidNetworkRules(UID_A, false);
346        expectSetUidForeground(UID_A, true);
347        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
348        replay();
349        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
350        future.get();
351        verifyAndReset();
352    }
353
354    public void testPolicyNone() throws Exception {
355        Future<Void> future;
356
357        expectSetUidNetworkRules(UID_A, false);
358        expectSetUidForeground(UID_A, true);
359        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
360        replay();
361        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
362        future.get();
363        verifyAndReset();
364
365        // POLICY_NONE should RULE_ALLOW in foreground
366        expectSetUidNetworkRules(UID_A, false);
367        expectSetUidForeground(UID_A, true);
368        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
369        replay();
370        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
371        future.get();
372        verifyAndReset();
373
374        // POLICY_NONE should RULE_ALLOW in background
375        expectSetUidNetworkRules(UID_A, false);
376        expectSetUidForeground(UID_A, false);
377        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
378        replay();
379        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
380        future.get();
381        verifyAndReset();
382    }
383
384    public void testPolicyReject() throws Exception {
385        Future<Void> future;
386
387        // POLICY_REJECT should RULE_ALLOW in background
388        expectSetUidNetworkRules(UID_A, true);
389        expectSetUidForeground(UID_A, false);
390        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
391        replay();
392        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
393        future.get();
394        verifyAndReset();
395
396        // POLICY_REJECT should RULE_ALLOW in foreground
397        expectSetUidNetworkRules(UID_A, false);
398        expectSetUidForeground(UID_A, true);
399        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
400        replay();
401        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
402        future.get();
403        verifyAndReset();
404
405        // POLICY_REJECT should RULE_REJECT in background
406        expectSetUidNetworkRules(UID_A, true);
407        expectSetUidForeground(UID_A, false);
408        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
409        replay();
410        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
411        future.get();
412        verifyAndReset();
413    }
414
415    public void testPolicyRejectAddRemove() throws Exception {
416        Future<Void> future;
417
418        // POLICY_NONE should have RULE_ALLOW in background
419        expectSetUidNetworkRules(UID_A, false);
420        expectSetUidForeground(UID_A, false);
421        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
422        replay();
423        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
424        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
425        future.get();
426        verifyAndReset();
427
428        // adding POLICY_REJECT should cause RULE_REJECT
429        expectSetUidNetworkRules(UID_A, true);
430        expectSetUidForeground(UID_A, false);
431        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
432        replay();
433        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
434        future.get();
435        verifyAndReset();
436
437        // removing POLICY_REJECT should return us to RULE_ALLOW
438        expectSetUidNetworkRules(UID_A, false);
439        expectSetUidForeground(UID_A, false);
440        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
441        replay();
442        mService.setUidPolicy(APP_ID_A, POLICY_NONE);
443        future.get();
444        verifyAndReset();
445    }
446
447    public void testLastCycleBoundaryThisMonth() throws Exception {
448        // assume cycle day of "5th", which should be in same month
449        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
450        final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
451
452        final NetworkPolicy policy = new NetworkPolicy(
453                sTemplateWifi, 5, TIMEZONE_UTC, 1024L, 1024L, false);
454        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
455        assertTimeEquals(expectedCycle, actualCycle);
456    }
457
458    public void testLastCycleBoundaryLastMonth() throws Exception {
459        // assume cycle day of "20th", which should be in last month
460        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
461        final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
462
463        final NetworkPolicy policy = new NetworkPolicy(
464                sTemplateWifi, 20, TIMEZONE_UTC, 1024L, 1024L, false);
465        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
466        assertTimeEquals(expectedCycle, actualCycle);
467    }
468
469    public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
470        // assume cycle day of "30th" in february; should go to january
471        final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
472        final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
473
474        final NetworkPolicy policy = new NetworkPolicy(
475                sTemplateWifi, 30, TIMEZONE_UTC, 1024L, 1024L, false);
476        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
477        assertTimeEquals(expectedCycle, actualCycle);
478    }
479
480    public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
481        // assume cycle day of "30th" in february, which should clamp
482        final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
483        final long expectedCycle = parseTime("2007-02-28T23:59:59.000Z");
484
485        final NetworkPolicy policy = new NetworkPolicy(
486                sTemplateWifi, 30, TIMEZONE_UTC, 1024L, 1024L, false);
487        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
488        assertTimeEquals(expectedCycle, actualCycle);
489    }
490
491    public void testCycleBoundaryLeapYear() throws Exception {
492        final NetworkPolicy policy = new NetworkPolicy(
493                sTemplateWifi, 29, TIMEZONE_UTC, 1024L, 1024L, false);
494
495        assertTimeEquals(parseTime("2012-01-29T00:00:00.000Z"),
496                computeNextCycleBoundary(parseTime("2012-01-14T00:00:00.000Z"), policy));
497        assertTimeEquals(parseTime("2012-02-29T00:00:00.000Z"),
498                computeNextCycleBoundary(parseTime("2012-02-14T00:00:00.000Z"), policy));
499        assertTimeEquals(parseTime("2012-02-29T00:00:00.000Z"),
500                computeLastCycleBoundary(parseTime("2012-03-14T00:00:00.000Z"), policy));
501        assertTimeEquals(parseTime("2012-03-29T00:00:00.000Z"),
502                computeNextCycleBoundary(parseTime("2012-03-14T00:00:00.000Z"), policy));
503
504        assertTimeEquals(parseTime("2007-01-29T00:00:00.000Z"),
505                computeNextCycleBoundary(parseTime("2007-01-14T00:00:00.000Z"), policy));
506        assertTimeEquals(parseTime("2007-02-28T23:59:59.000Z"),
507                computeNextCycleBoundary(parseTime("2007-02-14T00:00:00.000Z"), policy));
508        assertTimeEquals(parseTime("2007-02-28T23:59:59.000Z"),
509                computeLastCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy));
510        assertTimeEquals(parseTime("2007-03-29T00:00:00.000Z"),
511                computeNextCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy));
512    }
513
514    public void testNextCycleTimezoneAfterUtc() throws Exception {
515        // US/Central is UTC-6
516        final NetworkPolicy policy = new NetworkPolicy(
517                sTemplateWifi, 10, "US/Central", 1024L, 1024L, false);
518        assertTimeEquals(parseTime("2012-01-10T06:00:00.000Z"),
519                computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
520    }
521
522    public void testNextCycleTimezoneBeforeUtc() throws Exception {
523        // Israel is UTC+2
524        final NetworkPolicy policy = new NetworkPolicy(
525                sTemplateWifi, 10, "Israel", 1024L, 1024L, false);
526        assertTimeEquals(parseTime("2012-01-09T22:00:00.000Z"),
527                computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
528    }
529
530    public void testNextCycleSane() throws Exception {
531        final NetworkPolicy policy = new NetworkPolicy(
532                sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
533        final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
534
535        // walk forwards, ensuring that cycle boundaries don't get stuck
536        long currentCycle = computeNextCycleBoundary(parseTime("2011-08-01T00:00:00.000Z"), policy);
537        for (int i = 0; i < 128; i++) {
538            long nextCycle = computeNextCycleBoundary(currentCycle, policy);
539            assertEqualsFuzzy(DAY_IN_MILLIS * 30, nextCycle - currentCycle, DAY_IN_MILLIS * 3);
540            assertUnique(seen, nextCycle);
541            currentCycle = nextCycle;
542        }
543    }
544
545    public void testLastCycleSane() throws Exception {
546        final NetworkPolicy policy = new NetworkPolicy(
547                sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
548        final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
549
550        // walk backwards, ensuring that cycle boundaries look sane
551        long currentCycle = computeLastCycleBoundary(parseTime("2011-08-04T00:00:00.000Z"), policy);
552        for (int i = 0; i < 128; i++) {
553            long lastCycle = computeLastCycleBoundary(currentCycle, policy);
554            assertEqualsFuzzy(DAY_IN_MILLIS * 30, currentCycle - lastCycle, DAY_IN_MILLIS * 3);
555            assertUnique(seen, lastCycle);
556            currentCycle = lastCycle;
557        }
558    }
559
560    public void testCycleTodayJanuary() throws Exception {
561        final NetworkPolicy policy = new NetworkPolicy(
562                sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false);
563
564        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
565                computeNextCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy));
566        assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"),
567                computeNextCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy));
568        assertTimeEquals(parseTime("2013-02-14T00:00:00.000-08:00"),
569                computeNextCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
570
571        assertTimeEquals(parseTime("2012-12-14T00:00:00.000-08:00"),
572                computeLastCycleBoundary(parseTime("2013-01-13T23:59:59.000-08:00"), policy));
573        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
574                computeLastCycleBoundary(parseTime("2013-01-14T00:00:01.000-08:00"), policy));
575        assertTimeEquals(parseTime("2013-01-14T00:00:00.000-08:00"),
576                computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
577    }
578
579    public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
580        NetworkState[] state = null;
581        NetworkStats stats = null;
582        Future<Void> future;
583
584        final long TIME_FEB_15 = 1171497600000L;
585        final long TIME_MAR_10 = 1173484800000L;
586        final int CYCLE_DAY = 15;
587
588        setCurrentTimeMillis(TIME_MAR_10);
589
590        // first, pretend that wifi network comes online. no policy active,
591        // which means we shouldn't push limit to interface.
592        state = new NetworkState[] { buildWifi() };
593        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
594        expectCurrentTime();
595        expectClearNotifications();
596        expectAdvisePersistThreshold();
597        future = expectMeteredIfacesChanged();
598
599        replay();
600        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
601        future.get();
602        verifyAndReset();
603
604        // now change cycle to be on 15th, and test in early march, to verify we
605        // pick cycle day in previous month.
606        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
607        expectCurrentTime();
608
609        // pretend that 512 bytes total have happened
610        stats = new NetworkStats(getElapsedRealtime(), 1)
611                .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
612        expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
613                .andReturn(stats.getTotalBytes()).atLeastOnce();
614        expectPolicyDataEnable(TYPE_WIFI, true);
615
616        // TODO: consider making strongly ordered mock
617        expectRemoveInterfaceQuota(TEST_IFACE);
618        expectSetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
619
620        expectClearNotifications();
621        expectAdvisePersistThreshold();
622        future = expectMeteredIfacesChanged(TEST_IFACE);
623
624        replay();
625        setNetworkPolicies(new NetworkPolicy(
626                sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
627        future.get();
628        verifyAndReset();
629    }
630
631    public void testUidRemovedPolicyCleared() throws Exception {
632        Future<Void> future;
633
634        // POLICY_REJECT should RULE_REJECT in background
635        expectSetUidNetworkRules(UID_A, true);
636        expectSetUidForeground(UID_A, false);
637        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
638        replay();
639        mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
640        future.get();
641        verifyAndReset();
642
643        // uninstall should clear RULE_REJECT
644        expectSetUidNetworkRules(UID_A, false);
645        expectSetUidForeground(UID_A, false);
646        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
647        replay();
648        final Intent intent = new Intent(ACTION_UID_REMOVED);
649        intent.putExtra(EXTRA_UID, UID_A);
650        mServiceContext.sendBroadcast(intent);
651        future.get();
652        verifyAndReset();
653    }
654
655    public void testOverWarningLimitNotification() throws Exception {
656        NetworkState[] state = null;
657        NetworkStats stats = null;
658        Future<Void> future;
659        Future<String> tagFuture;
660
661        final long TIME_FEB_15 = 1171497600000L;
662        final long TIME_MAR_10 = 1173484800000L;
663        final int CYCLE_DAY = 15;
664
665        setCurrentTimeMillis(TIME_MAR_10);
666
667        // assign wifi policy
668        state = new NetworkState[] {};
669        stats = new NetworkStats(getElapsedRealtime(), 1)
670                .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
671
672        {
673            expectCurrentTime();
674            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
675            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
676                    .andReturn(stats.getTotalBytes()).atLeastOnce();
677            expectPolicyDataEnable(TYPE_WIFI, true);
678
679            expectClearNotifications();
680            expectAdvisePersistThreshold();
681            future = expectMeteredIfacesChanged();
682
683            replay();
684            setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1
685                    * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
686            future.get();
687            verifyAndReset();
688        }
689
690        // bring up wifi network
691        incrementCurrentTime(MINUTE_IN_MILLIS);
692        state = new NetworkState[] { buildWifi() };
693        stats = new NetworkStats(getElapsedRealtime(), 1)
694                .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
695
696        {
697            expectCurrentTime();
698            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
699            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
700                    .andReturn(stats.getTotalBytes()).atLeastOnce();
701            expectPolicyDataEnable(TYPE_WIFI, true);
702
703            expectRemoveInterfaceQuota(TEST_IFACE);
704            expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
705
706            expectClearNotifications();
707            expectAdvisePersistThreshold();
708            future = expectMeteredIfacesChanged(TEST_IFACE);
709
710            replay();
711            mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION_IMMEDIATE));
712            future.get();
713            verifyAndReset();
714        }
715
716        // go over warning, which should kick notification
717        incrementCurrentTime(MINUTE_IN_MILLIS);
718        stats = new NetworkStats(getElapsedRealtime(), 1)
719                .addIfaceValues(TEST_IFACE, 1536 * KB_IN_BYTES, 15L, 0L, 0L);
720
721        {
722            expectCurrentTime();
723            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
724                    .andReturn(stats.getTotalBytes()).atLeastOnce();
725            expectPolicyDataEnable(TYPE_WIFI, true);
726
727            expectForceUpdate();
728            expectClearNotifications();
729            tagFuture = expectEnqueueNotification();
730
731            replay();
732            mNetworkObserver.limitReached(null, TEST_IFACE);
733            assertNotificationType(TYPE_WARNING, tagFuture.get());
734            verifyAndReset();
735        }
736
737        // go over limit, which should kick notification and dialog
738        incrementCurrentTime(MINUTE_IN_MILLIS);
739        stats = new NetworkStats(getElapsedRealtime(), 1)
740                .addIfaceValues(TEST_IFACE, 5 * MB_IN_BYTES, 512L, 0L, 0L);
741
742        {
743            expectCurrentTime();
744            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
745                    .andReturn(stats.getTotalBytes()).atLeastOnce();
746            expectPolicyDataEnable(TYPE_WIFI, false);
747
748            expectForceUpdate();
749            expectClearNotifications();
750            tagFuture = expectEnqueueNotification();
751
752            replay();
753            mNetworkObserver.limitReached(null, TEST_IFACE);
754            assertNotificationType(TYPE_LIMIT, tagFuture.get());
755            verifyAndReset();
756        }
757
758        // now snooze policy, which should remove quota
759        incrementCurrentTime(MINUTE_IN_MILLIS);
760
761        {
762            expectCurrentTime();
763            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
764            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
765                    .andReturn(stats.getTotalBytes()).atLeastOnce();
766            expectPolicyDataEnable(TYPE_WIFI, true);
767
768            // snoozed interface still has high quota so background data is
769            // still restricted.
770            expectRemoveInterfaceQuota(TEST_IFACE);
771            expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
772            expectAdvisePersistThreshold();
773            expectMeteredIfacesChanged(TEST_IFACE);
774
775            future = expectClearNotifications();
776            tagFuture = expectEnqueueNotification();
777
778            replay();
779            mService.snoozeLimit(sTemplateWifi);
780            assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
781            future.get();
782            verifyAndReset();
783        }
784    }
785
786    public void testMeteredNetworkWithoutLimit() throws Exception {
787        NetworkState[] state = null;
788        NetworkStats stats = null;
789        Future<Void> future;
790        Future<String> tagFuture;
791
792        final long TIME_FEB_15 = 1171497600000L;
793        final long TIME_MAR_10 = 1173484800000L;
794        final int CYCLE_DAY = 15;
795
796        setCurrentTimeMillis(TIME_MAR_10);
797
798        // bring up wifi network with metered policy
799        state = new NetworkState[] { buildWifi() };
800        stats = new NetworkStats(getElapsedRealtime(), 1)
801                .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
802
803        {
804            expectCurrentTime();
805            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
806            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
807                    .andReturn(stats.getTotalBytes()).atLeastOnce();
808            expectPolicyDataEnable(TYPE_WIFI, true);
809
810            expectRemoveInterfaceQuota(TEST_IFACE);
811            expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
812
813            expectClearNotifications();
814            expectAdvisePersistThreshold();
815            future = expectMeteredIfacesChanged(TEST_IFACE);
816
817            replay();
818            setNetworkPolicies(new NetworkPolicy(
819                    sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED,
820                    true));
821            future.get();
822            verifyAndReset();
823        }
824    }
825
826    private static long parseTime(String time) {
827        final Time result = new Time();
828        result.parse3339(time);
829        return result.toMillis(true);
830    }
831
832    private void setNetworkPolicies(NetworkPolicy... policies) {
833        mService.setNetworkPolicies(policies);
834    }
835
836    private static NetworkState buildWifi() {
837        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
838        info.setDetailedState(DetailedState.CONNECTED, null, null);
839        final LinkProperties prop = new LinkProperties();
840        prop.setInterfaceName(TEST_IFACE);
841        return new NetworkState(info, prop, null, null, null, TEST_SSID);
842    }
843
844    private void expectCurrentTime() throws Exception {
845        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
846        expect(mTime.hasCache()).andReturn(true).anyTimes();
847        expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes();
848        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
849        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
850    }
851
852    private void expectForceUpdate() throws Exception {
853        mStatsService.forceUpdate();
854        expectLastCall().atLeastOnce();
855    }
856
857    private Future<Void> expectClearNotifications() throws Exception {
858        final FutureAnswer future = new FutureAnswer();
859        mNotifManager.cancelNotificationWithTag(
860                isA(String.class), isA(String.class), anyInt(), anyInt());
861        expectLastCall().andAnswer(future).anyTimes();
862        return future;
863    }
864
865    private Future<String> expectEnqueueNotification() throws Exception {
866        final FutureCapture<String> tag = new FutureCapture<String>();
867        mNotifManager.enqueueNotificationWithTag(isA(String.class), isA(String.class),
868                capture(tag.capture), anyInt(),
869                isA(Notification.class), isA(int[].class), UserHandle.myUserId());
870        return tag;
871    }
872
873    private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
874        mNetworkManager.setInterfaceQuota(iface, quotaBytes);
875        expectLastCall().atLeastOnce();
876    }
877
878    private void expectRemoveInterfaceQuota(String iface) throws Exception {
879        mNetworkManager.removeInterfaceQuota(iface);
880        expectLastCall().atLeastOnce();
881    }
882
883    private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
884        mNetworkManager.setInterfaceAlert(iface, alertBytes);
885        expectLastCall().atLeastOnce();
886    }
887
888    private void expectRemoveInterfaceAlert(String iface) throws Exception {
889        mNetworkManager.removeInterfaceAlert(iface);
890        expectLastCall().atLeastOnce();
891    }
892
893    private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
894            throws Exception {
895        mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
896        expectLastCall().atLeastOnce();
897    }
898
899    private void expectSetUidForeground(int uid, boolean uidForeground) throws Exception {
900        mStatsService.setUidForeground(uid, uidForeground);
901        expectLastCall().atLeastOnce();
902    }
903
904    private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
905        final FutureAnswer future = new FutureAnswer();
906        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
907        expectLastCall().andAnswer(future);
908        return future;
909    }
910
911    private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
912        final FutureAnswer future = new FutureAnswer();
913        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
914        expectLastCall().andAnswer(future);
915        return future;
916    }
917
918    private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
919        final FutureAnswer future = new FutureAnswer();
920        mConnManager.setPolicyDataEnable(type, enabled);
921        expectLastCall().andAnswer(future);
922        return future;
923    }
924
925    private void expectAdvisePersistThreshold() throws Exception {
926        mStatsService.advisePersistThreshold(anyLong());
927        expectLastCall().anyTimes();
928    }
929
930    private static class TestAbstractFuture<T> extends AbstractFuture<T> {
931        @Override
932        public T get() throws InterruptedException, ExecutionException {
933            try {
934                return get(5, TimeUnit.SECONDS);
935            } catch (TimeoutException e) {
936                throw new RuntimeException(e);
937            }
938        }
939    }
940
941    private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
942        @Override
943        public Void answer() {
944            set(null);
945            return null;
946        }
947    }
948
949    private static class FutureCapture<T> extends TestAbstractFuture<T> {
950        public Capture<T> capture = new Capture<T>() {
951            @Override
952            public void setValue(T value) {
953                super.setValue(value);
954                set(value);
955            }
956        };
957    }
958
959    private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler {
960        @Override
961        public Void get() throws InterruptedException, ExecutionException {
962            try {
963                return get(5, TimeUnit.SECONDS);
964            } catch (TimeoutException e) {
965                throw new RuntimeException(e);
966            }
967        }
968
969        @Override
970        public boolean queueIdle() {
971            set(null);
972            return false;
973        }
974    }
975
976    /**
977     * Wait until {@link #mService} internal {@link Handler} is idle.
978     */
979    private IdleFuture expectIdle() {
980        final IdleFuture future = new IdleFuture();
981        mService.addIdleHandler(future);
982        return future;
983    }
984
985    private static void assertTimeEquals(long expected, long actual) {
986        if (expected != actual) {
987            fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
988        }
989    }
990
991    private static String formatTime(long millis) {
992        final Time time = new Time(Time.TIMEZONE_UTC);
993        time.set(millis);
994        return time.format3339(false);
995    }
996
997    private static void assertEqualsFuzzy(long expected, long actual, long fuzzy) {
998        final long low = expected - fuzzy;
999        final long high = expected + fuzzy;
1000        if (actual < low || actual > high) {
1001            fail("value " + actual + " is outside [" + low + "," + high + "]");
1002        }
1003    }
1004
1005    private static void assertUnique(LinkedHashSet<Long> seen, Long value) {
1006        if (!seen.add(value)) {
1007            fail("found duplicate time " + value + " in series " + seen.toString());
1008        }
1009    }
1010
1011    private static void assertNotificationType(int expected, String actualTag) {
1012        assertEquals(
1013                Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
1014    }
1015
1016    private long getElapsedRealtime() {
1017        return mElapsedRealtime;
1018    }
1019
1020    private void setCurrentTimeMillis(long currentTimeMillis) {
1021        mStartTime = currentTimeMillis;
1022        mElapsedRealtime = 0L;
1023    }
1024
1025    private long currentTimeMillis() {
1026        return mStartTime + mElapsedRealtime;
1027    }
1028
1029    private void incrementCurrentTime(long duration) {
1030        mElapsedRealtime += duration;
1031    }
1032
1033    private void replay() {
1034        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
1035                mNetworkManager, mTime, mConnManager, mNotifManager);
1036    }
1037
1038    private void verifyAndReset() {
1039        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
1040                mNetworkManager, mTime, mConnManager, mNotifManager);
1041        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
1042                mNetworkManager, mTime, mConnManager, mNotifManager);
1043    }
1044}
1045