NetworkPolicyManagerServiceTest.java revision a63ba59260cd1bb3f5c16e395ace45a61f1d4461
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        replay();
201        mService.systemReady();
202        verifyAndReset();
203
204        mProcessObserver = processObserver.getValue();
205        mNetworkObserver = networkObserver.getValue();
206
207    }
208
209    @Override
210    public void tearDown() throws Exception {
211        for (File file : mPolicyDir.listFiles()) {
212            file.delete();
213        }
214
215        mServiceContext = null;
216        mPolicyDir = null;
217
218        mActivityManager = null;
219        mPowerManager = null;
220        mStatsService = null;
221        mPolicyListener = null;
222        mTime = null;
223
224        mService = null;
225        mProcessObserver = null;
226
227        super.tearDown();
228    }
229
230    @Suppress
231    public void testPolicyChangeTriggersBroadcast() throws Exception {
232        mService.setUidPolicy(UID_A, POLICY_NONE);
233
234        // change background policy and expect broadcast
235        final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
236                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
237
238        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
239
240        backgroundChanged.get();
241    }
242
243    public void testPidForegroundCombined() throws Exception {
244        // push all uid into background
245        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
246        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
247        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
248        assertFalse(mService.isUidForeground(UID_A));
249        assertFalse(mService.isUidForeground(UID_B));
250
251        // push one of the shared pids into foreground
252        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
253        assertTrue(mService.isUidForeground(UID_A));
254        assertFalse(mService.isUidForeground(UID_B));
255
256        // and swap another uid into foreground
257        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
258        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
259        assertFalse(mService.isUidForeground(UID_A));
260        assertTrue(mService.isUidForeground(UID_B));
261
262        // push both pid into foreground
263        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
264        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
265        assertTrue(mService.isUidForeground(UID_A));
266
267        // pull one out, should still be foreground
268        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
269        assertTrue(mService.isUidForeground(UID_A));
270
271        // pull final pid out, should now be background
272        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
273        assertFalse(mService.isUidForeground(UID_A));
274    }
275
276    public void testScreenChangesRules() throws Exception {
277        Future<Void> future;
278
279        expectSetUidNetworkRules(UID_A, false);
280        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
281        replay();
282        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
283        future.get();
284        verifyAndReset();
285
286        // push strict policy for foreground uid, verify ALLOW rule
287        expectSetUidNetworkRules(UID_A, false);
288        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
289        replay();
290        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
291        future.get();
292        verifyAndReset();
293
294        // now turn screen off and verify REJECT rule
295        expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
296        expectSetUidNetworkRules(UID_A, true);
297        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
298        replay();
299        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
300        future.get();
301        verifyAndReset();
302
303        // and turn screen back on, verify ALLOW rule restored
304        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
305        expectSetUidNetworkRules(UID_A, false);
306        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
307        replay();
308        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
309        future.get();
310        verifyAndReset();
311    }
312
313    public void testPolicyNone() throws Exception {
314        Future<Void> future;
315
316        expectSetUidNetworkRules(UID_A, false);
317        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
318        replay();
319        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
320        future.get();
321        verifyAndReset();
322
323        // POLICY_NONE should RULE_ALLOW in foreground
324        expectSetUidNetworkRules(UID_A, false);
325        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
326        replay();
327        mService.setUidPolicy(UID_A, POLICY_NONE);
328        future.get();
329        verifyAndReset();
330
331        // POLICY_NONE should RULE_ALLOW in background
332        expectSetUidNetworkRules(UID_A, false);
333        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
334        replay();
335        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
336        future.get();
337        verifyAndReset();
338    }
339
340    public void testPolicyReject() throws Exception {
341        Future<Void> future;
342
343        // POLICY_REJECT should RULE_ALLOW in background
344        expectSetUidNetworkRules(UID_A, true);
345        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
346        replay();
347        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
348        future.get();
349        verifyAndReset();
350
351        // POLICY_REJECT should RULE_ALLOW in foreground
352        expectSetUidNetworkRules(UID_A, false);
353        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
354        replay();
355        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
356        future.get();
357        verifyAndReset();
358
359        // POLICY_REJECT should RULE_REJECT in background
360        expectSetUidNetworkRules(UID_A, true);
361        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
362        replay();
363        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
364        future.get();
365        verifyAndReset();
366    }
367
368    public void testPolicyRejectAddRemove() throws Exception {
369        Future<Void> future;
370
371        // POLICY_NONE should have RULE_ALLOW in background
372        expectSetUidNetworkRules(UID_A, false);
373        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
374        replay();
375        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
376        mService.setUidPolicy(UID_A, POLICY_NONE);
377        future.get();
378        verifyAndReset();
379
380        // adding POLICY_REJECT should cause RULE_REJECT
381        expectSetUidNetworkRules(UID_A, true);
382        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
383        replay();
384        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
385        future.get();
386        verifyAndReset();
387
388        // removing POLICY_REJECT should return us to RULE_ALLOW
389        expectSetUidNetworkRules(UID_A, false);
390        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
391        replay();
392        mService.setUidPolicy(UID_A, POLICY_NONE);
393        future.get();
394        verifyAndReset();
395    }
396
397    public void testLastCycleBoundaryThisMonth() throws Exception {
398        // assume cycle day of "5th", which should be in same month
399        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
400        final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
401
402        final NetworkPolicy policy = new NetworkPolicy(
403                sTemplateWifi, 5, 1024L, 1024L, SNOOZE_NEVER);
404        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
405        assertEquals(expectedCycle, actualCycle);
406    }
407
408    public void testLastCycleBoundaryLastMonth() throws Exception {
409        // assume cycle day of "20th", which should be in last month
410        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
411        final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
412
413        final NetworkPolicy policy = new NetworkPolicy(
414                sTemplateWifi, 20, 1024L, 1024L, SNOOZE_NEVER);
415        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
416        assertEquals(expectedCycle, actualCycle);
417    }
418
419    public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
420        // assume cycle day of "30th" in february; should go to january
421        final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
422        final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
423
424        final NetworkPolicy policy = new NetworkPolicy(
425                sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
426        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
427        assertEquals(expectedCycle, actualCycle);
428    }
429
430    public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
431        // assume cycle day of "30th" in february, which should clamp
432        final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
433        final long expectedCycle = parseTime("2007-03-01T00:00:00.000Z");
434
435        final NetworkPolicy policy = new NetworkPolicy(
436                sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
437        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
438        assertEquals(expectedCycle, actualCycle);
439    }
440
441    public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
442        long elapsedRealtime = 0;
443        NetworkState[] state = null;
444        NetworkStats stats = null;
445        Future<Void> future;
446
447        final long TIME_FEB_15 = 1171497600000L;
448        final long TIME_MAR_10 = 1173484800000L;
449        final int CYCLE_DAY = 15;
450
451        // first, pretend that wifi network comes online. no policy active,
452        // which means we shouldn't push limit to interface.
453        state = new NetworkState[] { buildWifi() };
454        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
455        expectTime(TIME_MAR_10 + elapsedRealtime);
456        expectClearNotifications();
457        future = expectMeteredIfacesChanged();
458
459        replay();
460        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
461        future.get();
462        verifyAndReset();
463
464        // now change cycle to be on 15th, and test in early march, to verify we
465        // pick cycle day in previous month.
466        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
467        expectTime(TIME_MAR_10 + elapsedRealtime);
468
469        // pretend that 512 bytes total have happened
470        stats = new NetworkStats(elapsedRealtime, 1)
471                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L, 11);
472        expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
473                .andReturn(stats).atLeastOnce();
474
475        // TODO: consider making strongly ordered mock
476        expectRemoveInterfaceQuota(TEST_IFACE);
477        expectSetInterfaceQuota(TEST_IFACE, 1536L);
478        expectRemoveInterfaceAlert(TEST_IFACE);
479        expectSetInterfaceAlert(TEST_IFACE, 512L);
480
481        expectClearNotifications();
482        future = expectMeteredIfacesChanged(TEST_IFACE);
483
484        replay();
485        setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L, SNOOZE_NEVER));
486        future.get();
487        verifyAndReset();
488    }
489
490    public void testUidRemovedPolicyCleared() throws Exception {
491        Future<Void> future;
492
493        // POLICY_REJECT should RULE_REJECT in background
494        expectSetUidNetworkRules(UID_A, true);
495        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
496        replay();
497        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
498        future.get();
499        verifyAndReset();
500
501        // uninstall should clear RULE_REJECT
502        expectSetUidNetworkRules(UID_A, false);
503        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
504        replay();
505        final Intent intent = new Intent(ACTION_UID_REMOVED);
506        intent.putExtra(EXTRA_UID, UID_A);
507        mServiceContext.sendBroadcast(intent);
508        future.get();
509        verifyAndReset();
510    }
511
512    public void testOverWarningLimitNotification() throws Exception {
513        long elapsedRealtime = 0;
514        long currentTime = 0;
515        NetworkState[] state = null;
516        NetworkStats stats = null;
517        Future<Void> future;
518        Capture<String> tag;
519
520        final long TIME_FEB_15 = 1171497600000L;
521        final long TIME_MAR_10 = 1173484800000L;
522        final int CYCLE_DAY = 15;
523
524        // assign wifi policy
525        elapsedRealtime = 0;
526        currentTime = TIME_MAR_10 + elapsedRealtime;
527        state = new NetworkState[] {};
528
529        {
530            expectTime(currentTime);
531            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
532
533            expectClearNotifications();
534            future = expectMeteredIfacesChanged();
535
536            replay();
537            setNetworkPolicies(
538                    new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L, SNOOZE_NEVER));
539            future.get();
540            verifyAndReset();
541        }
542
543        // bring up wifi network
544        elapsedRealtime += MINUTE_IN_MILLIS;
545        currentTime = TIME_MAR_10 + elapsedRealtime;
546        stats = new NetworkStats(elapsedRealtime, 1)
547                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0);
548        state = new NetworkState[] { buildWifi() };
549
550        {
551            expectTime(currentTime);
552            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
553            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
554                    .andReturn(stats).atLeastOnce();
555
556            expectRemoveInterfaceQuota(TEST_IFACE);
557            expectSetInterfaceQuota(TEST_IFACE, 2048L);
558            expectRemoveInterfaceAlert(TEST_IFACE);
559            expectSetInterfaceAlert(TEST_IFACE, 1024L);
560
561            expectClearNotifications();
562            future = expectMeteredIfacesChanged(TEST_IFACE);
563
564            replay();
565            mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
566            future.get();
567            verifyAndReset();
568        }
569
570        // go over warning, which should kick notification
571        elapsedRealtime += MINUTE_IN_MILLIS;
572        currentTime = TIME_MAR_10 + elapsedRealtime;
573        stats = new NetworkStats(elapsedRealtime, 1)
574                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L, 11);
575
576        {
577            expectTime(currentTime);
578            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
579                    .andReturn(stats).atLeastOnce();
580
581            expectForceUpdate();
582            expectClearNotifications();
583            tag = expectEnqueueNotification();
584
585            replay();
586            mNetworkObserver.limitReached(null, TEST_IFACE);
587            assertNotificationType(TYPE_WARNING, tag.getValue());
588            verifyAndReset();
589        }
590
591        // go over limit, which should kick notification and dialog
592        elapsedRealtime += MINUTE_IN_MILLIS;
593        currentTime = TIME_MAR_10 + elapsedRealtime;
594        stats = new NetworkStats(elapsedRealtime, 1)
595                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L, 22);
596
597        {
598            expectTime(currentTime);
599            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
600                    .andReturn(stats).atLeastOnce();
601
602            expectForceUpdate();
603            expectClearNotifications();
604            tag = expectEnqueueNotification();
605
606            replay();
607            mNetworkObserver.limitReached(null, TEST_IFACE);
608            assertNotificationType(TYPE_LIMIT, tag.getValue());
609            verifyAndReset();
610        }
611
612        // now snooze policy, which should remove quota
613        elapsedRealtime += MINUTE_IN_MILLIS;
614        currentTime = TIME_MAR_10 + elapsedRealtime;
615
616        {
617            expectTime(currentTime);
618            expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
619            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
620                    .andReturn(stats).atLeastOnce();
621
622            expectRemoveInterfaceQuota(TEST_IFACE);
623            expectRemoveInterfaceAlert(TEST_IFACE);
624
625            expectClearNotifications();
626            tag = expectEnqueueNotification();
627            future = expectMeteredIfacesChanged();
628
629            replay();
630            mService.snoozePolicy(sTemplateWifi);
631            future.get();
632            assertNotificationType(TYPE_LIMIT_SNOOZED, tag.getValue());
633            verifyAndReset();
634        }
635    }
636
637    private static long parseTime(String time) {
638        final Time result = new Time();
639        result.parse3339(time);
640        return result.toMillis(true);
641    }
642
643    private void setNetworkPolicies(NetworkPolicy... policies) {
644        mService.setNetworkPolicies(policies);
645    }
646
647    private static NetworkState buildWifi() {
648        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
649        info.setDetailedState(DetailedState.CONNECTED, null, null);
650        final LinkProperties prop = new LinkProperties();
651        prop.setInterfaceName(TEST_IFACE);
652        return new NetworkState(info, prop, null);
653    }
654
655    private void expectTime(long currentTime) throws Exception {
656        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
657        expect(mTime.hasCache()).andReturn(true).anyTimes();
658        expect(mTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
659        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
660        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
661    }
662
663    private void expectForceUpdate() throws Exception {
664        mStatsService.forceUpdate();
665        expectLastCall().atLeastOnce();
666    }
667
668    private void expectClearNotifications() throws Exception {
669        mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
670        expectLastCall().anyTimes();
671    }
672
673    private Capture<String> expectEnqueueNotification() throws Exception {
674        final Capture<String> tag = new Capture<String>();
675        mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag), anyInt(),
676                isA(Notification.class), isA(int[].class));
677        return tag;
678    }
679
680    private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
681        mNetworkManager.setInterfaceQuota(iface, quotaBytes);
682        expectLastCall().atLeastOnce();
683    }
684
685    private void expectRemoveInterfaceQuota(String iface) throws Exception {
686        mNetworkManager.removeInterfaceQuota(iface);
687        expectLastCall().atLeastOnce();
688    }
689
690    private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
691        mNetworkManager.setInterfaceAlert(iface, alertBytes);
692        expectLastCall().atLeastOnce();
693    }
694
695    private void expectRemoveInterfaceAlert(String iface) throws Exception {
696        mNetworkManager.removeInterfaceAlert(iface);
697        expectLastCall().atLeastOnce();
698    }
699
700    private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
701            throws Exception {
702        mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
703        expectLastCall().atLeastOnce();
704    }
705
706    private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
707        final FutureAnswer future = new FutureAnswer();
708        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
709        expectLastCall().andAnswer(future);
710        return future;
711    }
712
713    private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
714        final FutureAnswer future = new FutureAnswer();
715        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
716        expectLastCall().andAnswer(future);
717        return future;
718    }
719
720    private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
721        @Override
722        public Void get() throws InterruptedException, ExecutionException {
723            try {
724                return get(5, TimeUnit.SECONDS);
725            } catch (TimeoutException e) {
726                throw new RuntimeException(e);
727            }
728        }
729
730        @Override
731        public Void answer() {
732            set(null);
733            return null;
734        }
735    }
736
737    private static void assertNotificationType(int expected, String actualTag) {
738        assertEquals(
739                Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
740    }
741
742    private void replay() {
743        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
744                mNetworkManager, mTime, mConnManager, mNotifManager);
745    }
746
747    private void verifyAndReset() {
748        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
749                mNetworkManager, mTime, mConnManager, mNotifManager);
750        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
751                mNetworkManager, mTime, mConnManager, mNotifManager);
752    }
753}
754