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