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