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