NetworkPolicyManagerServiceTest.java revision 41ff7ec82422a5b6d00892afdb3232bc0e53d851
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import static android.content.Intent.ACTION_UID_REMOVED;
20import static android.content.Intent.EXTRA_UID;
21import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
22import static android.net.ConnectivityManager.TYPE_WIFI;
23import static android.net.NetworkPolicy.SNOOZE_NEVER;
24import static android.net.NetworkPolicyManager.POLICY_NONE;
25import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
26import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
27import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
28import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
29import static android.net.NetworkStats.TAG_NONE;
30import static android.net.NetworkStats.UID_ALL;
31import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
32import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
33import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
34import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
35import static org.easymock.EasyMock.anyInt;
36import static org.easymock.EasyMock.aryEq;
37import static org.easymock.EasyMock.capture;
38import static org.easymock.EasyMock.createMock;
39import static org.easymock.EasyMock.eq;
40import static org.easymock.EasyMock.expect;
41import static org.easymock.EasyMock.expectLastCall;
42import static org.easymock.EasyMock.isA;
43
44import android.app.IActivityManager;
45import android.app.INotificationManager;
46import android.app.IProcessObserver;
47import android.app.Notification;
48import android.content.Intent;
49import android.content.pm.PackageInfo;
50import android.content.pm.PackageManager;
51import android.content.pm.Signature;
52import android.net.ConnectivityManager;
53import android.net.IConnectivityManager;
54import android.net.INetworkManagementEventObserver;
55import android.net.INetworkPolicyListener;
56import android.net.INetworkStatsService;
57import android.net.LinkProperties;
58import android.net.NetworkInfo;
59import android.net.NetworkInfo.DetailedState;
60import android.net.NetworkPolicy;
61import android.net.NetworkState;
62import android.net.NetworkStats;
63import android.net.NetworkTemplate;
64import android.os.Binder;
65import android.os.INetworkManagementService;
66import android.os.IPowerManager;
67import android.test.AndroidTestCase;
68import android.test.mock.MockPackageManager;
69import android.test.suitebuilder.annotation.LargeTest;
70import android.test.suitebuilder.annotation.Suppress;
71import android.text.format.Time;
72import android.util.TrustedTime;
73
74import com.android.server.net.NetworkPolicyManagerService;
75import com.google.common.util.concurrent.AbstractFuture;
76
77import org.easymock.Capture;
78import org.easymock.EasyMock;
79import org.easymock.IAnswer;
80
81import java.io.File;
82import java.util.concurrent.ExecutionException;
83import java.util.concurrent.Future;
84import java.util.concurrent.TimeUnit;
85import java.util.concurrent.TimeoutException;
86
87/**
88 * Tests for {@link NetworkPolicyManagerService}.
89 */
90@LargeTest
91public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
92    private static final String TAG = "NetworkPolicyManagerServiceTest";
93
94    private static final long TEST_START = 1194220800000L;
95    private static final String TEST_IFACE = "test0";
96
97    private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi();
98
99    private BroadcastInterceptingContext mServiceContext;
100    private File mPolicyDir;
101
102    private IActivityManager mActivityManager;
103    private IPowerManager mPowerManager;
104    private INetworkStatsService mStatsService;
105    private INetworkManagementService mNetworkManager;
106    private INetworkPolicyListener mPolicyListener;
107    private TrustedTime mTime;
108    private IConnectivityManager mConnManager;
109    private INotificationManager mNotifManager;
110
111    private NetworkPolicyManagerService mService;
112    private IProcessObserver mProcessObserver;
113    private INetworkManagementEventObserver mNetworkObserver;
114
115    private Binder mStubBinder = new Binder();
116
117    private static final int UID_A = android.os.Process.FIRST_APPLICATION_UID + 800;
118    private static final int UID_B = android.os.Process.FIRST_APPLICATION_UID + 801;
119
120    private static final int PID_1 = 400;
121    private static final int PID_2 = 401;
122    private static final int PID_3 = 402;
123
124    @Override
125    public void setUp() throws Exception {
126        super.setUp();
127
128        // intercept various broadcasts, and pretend that uids have packages
129        mServiceContext = new BroadcastInterceptingContext(getContext()) {
130            @Override
131            public PackageManager getPackageManager() {
132                return new MockPackageManager() {
133                    @Override
134                    public String[] getPackagesForUid(int uid) {
135                        return new String[] { "com.example" };
136                    }
137
138                    @Override
139                    public PackageInfo getPackageInfo(String packageName, int flags) {
140                        final PackageInfo info = new PackageInfo();
141                        final Signature signature;
142                        if ("android".equals(packageName)) {
143                            signature = new Signature("F00D");
144                        } else {
145                            signature = new Signature("DEAD");
146                        }
147                        info.signatures = new Signature[] { signature };
148                        return info;
149                    }
150                };
151            }
152
153            @Override
154            public void startActivity(Intent intent) {
155                // ignored
156            }
157        };
158
159        mPolicyDir = getContext().getFilesDir();
160        for (File file : mPolicyDir.listFiles()) {
161            file.delete();
162        }
163
164        mActivityManager = createMock(IActivityManager.class);
165        mPowerManager = createMock(IPowerManager.class);
166        mStatsService = createMock(INetworkStatsService.class);
167        mNetworkManager = createMock(INetworkManagementService.class);
168        mPolicyListener = createMock(INetworkPolicyListener.class);
169        mTime = createMock(TrustedTime.class);
170        mConnManager = createMock(IConnectivityManager.class);
171        mNotifManager = createMock(INotificationManager.class);
172
173        mService = new NetworkPolicyManagerService(
174                mServiceContext, mActivityManager, mPowerManager, mStatsService,
175                mNetworkManager, mTime, mPolicyDir);
176        mService.bindConnectivityManager(mConnManager);
177        mService.bindNotificationManager(mNotifManager);
178
179        // RemoteCallbackList needs a binder to use as key
180        expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
181        replay();
182        mService.registerListener(mPolicyListener);
183        verifyAndReset();
184
185        // catch IProcessObserver during systemReady()
186        final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
187        mActivityManager.registerProcessObserver(capture(processObserver));
188        expectLastCall().atLeastOnce();
189
190        // catch INetworkManagementEventObserver during systemReady()
191        final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
192                INetworkManagementEventObserver>();
193        mNetworkManager.registerObserver(capture(networkObserver));
194        expectLastCall().atLeastOnce();
195
196        // expect to answer screen status during systemReady()
197        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
198        expectTime(System.currentTimeMillis());
199
200        // default behavior is background data enabled
201        expect(mConnManager.getBackgroundDataSetting()).andReturn(true);
202
203        replay();
204        mService.systemReady();
205        verifyAndReset();
206
207        mProcessObserver = processObserver.getValue();
208        mNetworkObserver = networkObserver.getValue();
209
210    }
211
212    @Override
213    public void tearDown() throws Exception {
214        for (File file : mPolicyDir.listFiles()) {
215            file.delete();
216        }
217
218        mServiceContext = null;
219        mPolicyDir = null;
220
221        mActivityManager = null;
222        mPowerManager = null;
223        mStatsService = null;
224        mPolicyListener = null;
225        mTime = null;
226
227        mService = null;
228        mProcessObserver = null;
229
230        super.tearDown();
231    }
232
233    @Suppress
234    public void testPolicyChangeTriggersBroadcast() throws Exception {
235        mService.setUidPolicy(UID_A, POLICY_NONE);
236
237        // change background policy and expect broadcast
238        final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
239                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
240
241        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
242
243        backgroundChanged.get();
244    }
245
246    public void testPidForegroundCombined() throws Exception {
247        // push all uid into background
248        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
249        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
250        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
251        assertFalse(mService.isUidForeground(UID_A));
252        assertFalse(mService.isUidForeground(UID_B));
253
254        // push one of the shared pids into foreground
255        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
256        assertTrue(mService.isUidForeground(UID_A));
257        assertFalse(mService.isUidForeground(UID_B));
258
259        // and swap another uid into foreground
260        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
261        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
262        assertFalse(mService.isUidForeground(UID_A));
263        assertTrue(mService.isUidForeground(UID_B));
264
265        // push both pid into foreground
266        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
267        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
268        assertTrue(mService.isUidForeground(UID_A));
269
270        // pull one out, should still be foreground
271        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
272        assertTrue(mService.isUidForeground(UID_A));
273
274        // pull final pid out, should now be background
275        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
276        assertFalse(mService.isUidForeground(UID_A));
277    }
278
279    public void testScreenChangesRules() throws Exception {
280        Future<Void> future;
281
282        expectSetUidNetworkRules(UID_A, false);
283        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
284        replay();
285        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
286        future.get();
287        verifyAndReset();
288
289        // push strict policy for foreground uid, verify ALLOW rule
290        expectSetUidNetworkRules(UID_A, false);
291        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
292        replay();
293        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
294        future.get();
295        verifyAndReset();
296
297        // now turn screen off and verify REJECT rule
298        expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
299        expectSetUidNetworkRules(UID_A, true);
300        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
301        replay();
302        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
303        future.get();
304        verifyAndReset();
305
306        // and turn screen back on, verify ALLOW rule restored
307        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
308        expectSetUidNetworkRules(UID_A, false);
309        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
310        replay();
311        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
312        future.get();
313        verifyAndReset();
314    }
315
316    public void testPolicyNone() throws Exception {
317        Future<Void> future;
318
319        expectSetUidNetworkRules(UID_A, false);
320        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
321        replay();
322        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
323        future.get();
324        verifyAndReset();
325
326        // POLICY_NONE should RULE_ALLOW in foreground
327        expectSetUidNetworkRules(UID_A, false);
328        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
329        replay();
330        mService.setUidPolicy(UID_A, POLICY_NONE);
331        future.get();
332        verifyAndReset();
333
334        // POLICY_NONE should RULE_ALLOW in background
335        expectSetUidNetworkRules(UID_A, false);
336        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
337        replay();
338        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
339        future.get();
340        verifyAndReset();
341    }
342
343    public void testPolicyReject() throws Exception {
344        Future<Void> future;
345
346        // POLICY_REJECT should RULE_ALLOW in background
347        expectSetUidNetworkRules(UID_A, true);
348        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
349        replay();
350        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
351        future.get();
352        verifyAndReset();
353
354        // POLICY_REJECT should RULE_ALLOW in foreground
355        expectSetUidNetworkRules(UID_A, false);
356        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
357        replay();
358        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
359        future.get();
360        verifyAndReset();
361
362        // POLICY_REJECT should RULE_REJECT in background
363        expectSetUidNetworkRules(UID_A, true);
364        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
365        replay();
366        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
367        future.get();
368        verifyAndReset();
369    }
370
371    public void testPolicyRejectAddRemove() throws Exception {
372        Future<Void> future;
373
374        // POLICY_NONE should have RULE_ALLOW in background
375        expectSetUidNetworkRules(UID_A, false);
376        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
377        replay();
378        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
379        mService.setUidPolicy(UID_A, POLICY_NONE);
380        future.get();
381        verifyAndReset();
382
383        // adding POLICY_REJECT should cause RULE_REJECT
384        expectSetUidNetworkRules(UID_A, true);
385        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
386        replay();
387        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
388        future.get();
389        verifyAndReset();
390
391        // removing POLICY_REJECT should return us to RULE_ALLOW
392        expectSetUidNetworkRules(UID_A, false);
393        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
394        replay();
395        mService.setUidPolicy(UID_A, POLICY_NONE);
396        future.get();
397        verifyAndReset();
398    }
399
400    public void testLastCycleBoundaryThisMonth() throws Exception {
401        // assume cycle day of "5th", which should be in same month
402        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
403        final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
404
405        final NetworkPolicy policy = new NetworkPolicy(
406                sTemplateWifi, 5, 1024L, 1024L, SNOOZE_NEVER);
407        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
408        assertEquals(expectedCycle, actualCycle);
409    }
410
411    public void testLastCycleBoundaryLastMonth() throws Exception {
412        // assume cycle day of "20th", which should be in last month
413        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
414        final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
415
416        final NetworkPolicy policy = new NetworkPolicy(
417                sTemplateWifi, 20, 1024L, 1024L, SNOOZE_NEVER);
418        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
419        assertEquals(expectedCycle, actualCycle);
420    }
421
422    public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
423        // assume cycle day of "30th" in february; should go to january
424        final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
425        final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
426
427        final NetworkPolicy policy = new NetworkPolicy(
428                sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
429        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
430        assertEquals(expectedCycle, actualCycle);
431    }
432
433    public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
434        // assume cycle day of "30th" in february, which should clamp
435        final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
436        final long expectedCycle = parseTime("2007-03-01T00:00:00.000Z");
437
438        final NetworkPolicy policy = new NetworkPolicy(
439                sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
440        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
441        assertEquals(expectedCycle, actualCycle);
442    }
443
444    public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
445        long elapsedRealtime = 0;
446        NetworkState[] state = null;
447        NetworkStats stats = null;
448        Future<Void> future;
449
450        final long TIME_FEB_15 = 1171497600000L;
451        final long TIME_MAR_10 = 1173484800000L;
452        final int CYCLE_DAY = 15;
453
454        // first, pretend that wifi network comes online. no policy active,
455        // which means we shouldn't push limit to interface.
456        state = new NetworkState[] { buildWifi() };
457        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
458        expectTime(TIME_MAR_10 + elapsedRealtime);
459        expectClearNotifications();
460        future = expectMeteredIfacesChanged();
461
462        replay();
463        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
464        future.get();
465        verifyAndReset();
466
467        // now change cycle to be on 15th, and test in early march, to verify we
468        // pick cycle day in previous month.
469        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
470        expectTime(TIME_MAR_10 + elapsedRealtime);
471
472        // pretend that 512 bytes total have happened
473        stats = new NetworkStats(elapsedRealtime, 1)
474                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L);
475        expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
476                .andReturn(stats).atLeastOnce();
477
478        // TODO: consider making strongly ordered mock
479        expectRemoveInterfaceQuota(TEST_IFACE);
480        expectSetInterfaceQuota(TEST_IFACE, 1536L);
481        expectRemoveInterfaceAlert(TEST_IFACE);
482        expectSetInterfaceAlert(TEST_IFACE, 512L);
483
484        expectClearNotifications();
485        future = expectMeteredIfacesChanged(TEST_IFACE);
486
487        replay();
488        setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L, SNOOZE_NEVER));
489        future.get();
490        verifyAndReset();
491    }
492
493    public void testUidRemovedPolicyCleared() throws Exception {
494        Future<Void> future;
495
496        // POLICY_REJECT should RULE_REJECT in background
497        expectSetUidNetworkRules(UID_A, true);
498        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
499        replay();
500        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
501        future.get();
502        verifyAndReset();
503
504        // uninstall should clear RULE_REJECT
505        expectSetUidNetworkRules(UID_A, false);
506        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
507        replay();
508        final Intent intent = new Intent(ACTION_UID_REMOVED);
509        intent.putExtra(EXTRA_UID, UID_A);
510        mServiceContext.sendBroadcast(intent);
511        future.get();
512        verifyAndReset();
513    }
514
515    public void testOverWarningLimitNotification() throws Exception {
516        long elapsedRealtime = 0;
517        long currentTime = 0;
518        NetworkState[] state = null;
519        NetworkStats stats = null;
520        Future<Void> future;
521        Capture<String> tag;
522
523        final long TIME_FEB_15 = 1171497600000L;
524        final long TIME_MAR_10 = 1173484800000L;
525        final int CYCLE_DAY = 15;
526
527        // assign wifi policy
528        elapsedRealtime = 0;
529        currentTime = TIME_MAR_10 + elapsedRealtime;
530        state = new NetworkState[] {};
531
532        {
533            expectTime(currentTime);
534            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
535
536            expectClearNotifications();
537            future = expectMeteredIfacesChanged();
538
539            replay();
540            setNetworkPolicies(
541                    new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L, SNOOZE_NEVER));
542            future.get();
543            verifyAndReset();
544        }
545
546        // bring up wifi network
547        elapsedRealtime += MINUTE_IN_MILLIS;
548        currentTime = TIME_MAR_10 + elapsedRealtime;
549        stats = new NetworkStats(elapsedRealtime, 1)
550                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L);
551        state = new NetworkState[] { buildWifi() };
552
553        {
554            expectTime(currentTime);
555            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
556            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
557                    .andReturn(stats).atLeastOnce();
558
559            expectRemoveInterfaceQuota(TEST_IFACE);
560            expectSetInterfaceQuota(TEST_IFACE, 2048L);
561            expectRemoveInterfaceAlert(TEST_IFACE);
562            expectSetInterfaceAlert(TEST_IFACE, 1024L);
563
564            expectClearNotifications();
565            future = expectMeteredIfacesChanged(TEST_IFACE);
566
567            replay();
568            mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
569            future.get();
570            verifyAndReset();
571        }
572
573        // go over warning, which should kick notification
574        elapsedRealtime += MINUTE_IN_MILLIS;
575        currentTime = TIME_MAR_10 + elapsedRealtime;
576        stats = new NetworkStats(elapsedRealtime, 1)
577                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L);
578
579        {
580            expectTime(currentTime);
581            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
582                    .andReturn(stats).atLeastOnce();
583
584            expectForceUpdate();
585            expectClearNotifications();
586            tag = expectEnqueueNotification();
587
588            replay();
589            mNetworkObserver.limitReached(null, TEST_IFACE);
590            assertNotificationType(TYPE_WARNING, tag.getValue());
591            verifyAndReset();
592        }
593
594        // go over limit, which should kick notification and dialog
595        elapsedRealtime += MINUTE_IN_MILLIS;
596        currentTime = TIME_MAR_10 + elapsedRealtime;
597        stats = new NetworkStats(elapsedRealtime, 1)
598                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L);
599
600        {
601            expectTime(currentTime);
602            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
603                    .andReturn(stats).atLeastOnce();
604
605            expectForceUpdate();
606            expectClearNotifications();
607            tag = expectEnqueueNotification();
608
609            replay();
610            mNetworkObserver.limitReached(null, TEST_IFACE);
611            assertNotificationType(TYPE_LIMIT, tag.getValue());
612            verifyAndReset();
613        }
614
615        // now snooze policy, which should remove quota
616        elapsedRealtime += MINUTE_IN_MILLIS;
617        currentTime = TIME_MAR_10 + elapsedRealtime;
618
619        {
620            expectTime(currentTime);
621            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
622            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
623                    .andReturn(stats).atLeastOnce();
624
625            expectRemoveInterfaceQuota(TEST_IFACE);
626            expectRemoveInterfaceAlert(TEST_IFACE);
627
628            expectClearNotifications();
629            tag = expectEnqueueNotification();
630            future = expectMeteredIfacesChanged();
631
632            replay();
633            mService.snoozePolicy(sTemplateWifi);
634            future.get();
635            assertNotificationType(TYPE_LIMIT_SNOOZED, tag.getValue());
636            verifyAndReset();
637        }
638    }
639
640    private static long parseTime(String time) {
641        final Time result = new Time();
642        result.parse3339(time);
643        return result.toMillis(true);
644    }
645
646    private void setNetworkPolicies(NetworkPolicy... policies) {
647        mService.setNetworkPolicies(policies);
648    }
649
650    private static NetworkState buildWifi() {
651        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
652        info.setDetailedState(DetailedState.CONNECTED, null, null);
653        final LinkProperties prop = new LinkProperties();
654        prop.setInterfaceName(TEST_IFACE);
655        return new NetworkState(info, prop, null);
656    }
657
658    private void expectTime(long currentTime) throws Exception {
659        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
660        expect(mTime.hasCache()).andReturn(true).anyTimes();
661        expect(mTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
662        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
663        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
664    }
665
666    private void expectForceUpdate() throws Exception {
667        mStatsService.forceUpdate();
668        expectLastCall().atLeastOnce();
669    }
670
671    private void expectClearNotifications() throws Exception {
672        mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
673        expectLastCall().anyTimes();
674    }
675
676    private Capture<String> expectEnqueueNotification() throws Exception {
677        final Capture<String> tag = new Capture<String>();
678        mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag), anyInt(),
679                isA(Notification.class), isA(int[].class));
680        return tag;
681    }
682
683    private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
684        mNetworkManager.setInterfaceQuota(iface, quotaBytes);
685        expectLastCall().atLeastOnce();
686    }
687
688    private void expectRemoveInterfaceQuota(String iface) throws Exception {
689        mNetworkManager.removeInterfaceQuota(iface);
690        expectLastCall().atLeastOnce();
691    }
692
693    private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
694        mNetworkManager.setInterfaceAlert(iface, alertBytes);
695        expectLastCall().atLeastOnce();
696    }
697
698    private void expectRemoveInterfaceAlert(String iface) throws Exception {
699        mNetworkManager.removeInterfaceAlert(iface);
700        expectLastCall().atLeastOnce();
701    }
702
703    private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
704            throws Exception {
705        mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
706        expectLastCall().atLeastOnce();
707    }
708
709    private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
710        final FutureAnswer future = new FutureAnswer();
711        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
712        expectLastCall().andAnswer(future);
713        return future;
714    }
715
716    private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
717        final FutureAnswer future = new FutureAnswer();
718        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
719        expectLastCall().andAnswer(future);
720        return future;
721    }
722
723    private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
724        @Override
725        public Void get() throws InterruptedException, ExecutionException {
726            try {
727                return get(5, TimeUnit.SECONDS);
728            } catch (TimeoutException e) {
729                throw new RuntimeException(e);
730            }
731        }
732
733        @Override
734        public Void answer() {
735            set(null);
736            return null;
737        }
738    }
739
740    private static void assertNotificationType(int expected, String actualTag) {
741        assertEquals(
742                Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
743    }
744
745    private void replay() {
746        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
747                mNetworkManager, mTime, mConnManager, mNotifManager);
748    }
749
750    private void verifyAndReset() {
751        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
752                mNetworkManager, mTime, mConnManager, mNotifManager);
753        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
754                mNetworkManager, mTime, mConnManager, mNotifManager);
755    }
756}
757