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