NetworkPolicyManagerServiceTest.java revision d37948f6ed1667d077e0e3a38808f42f981ddcc2
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.NetworkPolicyManager.POLICY_NONE;
24import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
25import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
26import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
27import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
28import static android.net.NetworkStats.TAG_NONE;
29import static android.net.NetworkStats.UID_ALL;
30import static android.net.NetworkTemplate.MATCH_WIFI;
31import static org.easymock.EasyMock.anyInt;
32import static org.easymock.EasyMock.aryEq;
33import static org.easymock.EasyMock.capture;
34import static org.easymock.EasyMock.createMock;
35import static org.easymock.EasyMock.eq;
36import static org.easymock.EasyMock.expect;
37import static org.easymock.EasyMock.expectLastCall;
38import static org.easymock.EasyMock.isA;
39
40import android.app.IActivityManager;
41import android.app.INotificationManager;
42import android.app.IProcessObserver;
43import android.content.Intent;
44import android.content.pm.PackageInfo;
45import android.content.pm.PackageManager;
46import android.content.pm.Signature;
47import android.net.ConnectivityManager;
48import android.net.IConnectivityManager;
49import android.net.INetworkPolicyListener;
50import android.net.INetworkStatsService;
51import android.net.LinkProperties;
52import android.net.NetworkInfo;
53import android.net.NetworkInfo.DetailedState;
54import android.net.NetworkPolicy;
55import android.net.NetworkState;
56import android.net.NetworkStats;
57import android.net.NetworkTemplate;
58import android.os.Binder;
59import android.os.INetworkManagementService;
60import android.os.IPowerManager;
61import android.test.AndroidTestCase;
62import android.test.mock.MockPackageManager;
63import android.test.suitebuilder.annotation.LargeTest;
64import android.test.suitebuilder.annotation.Suppress;
65import android.text.format.Time;
66import android.util.TrustedTime;
67
68import com.android.server.net.NetworkPolicyManagerService;
69import com.google.common.util.concurrent.AbstractFuture;
70
71import org.easymock.Capture;
72import org.easymock.EasyMock;
73import org.easymock.IAnswer;
74
75import java.io.File;
76import java.util.concurrent.ExecutionException;
77import java.util.concurrent.Future;
78import java.util.concurrent.TimeUnit;
79import java.util.concurrent.TimeoutException;
80
81/**
82 * Tests for {@link NetworkPolicyManagerService}.
83 */
84@LargeTest
85public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
86    private static final String TAG = "NetworkPolicyManagerServiceTest";
87
88    private static final long TEST_START = 1194220800000L;
89    private static final String TEST_IFACE = "test0";
90
91    private static NetworkTemplate sTemplateWifi = new NetworkTemplate(MATCH_WIFI, null);
92
93    private BroadcastInterceptingContext mServiceContext;
94    private File mPolicyDir;
95
96    private IActivityManager mActivityManager;
97    private IPowerManager mPowerManager;
98    private INetworkStatsService mStatsService;
99    private INetworkManagementService mNetworkManagement;
100    private INetworkPolicyListener mPolicyListener;
101    private TrustedTime mTime;
102    private IConnectivityManager mConnManager;
103    private INotificationManager mNotifManager;
104
105    private NetworkPolicyManagerService mService;
106    private IProcessObserver mProcessObserver;
107
108    private Binder mStubBinder = new Binder();
109
110    private static final int UID_A = android.os.Process.FIRST_APPLICATION_UID + 800;
111    private static final int UID_B = android.os.Process.FIRST_APPLICATION_UID + 801;
112
113    private static final int PID_1 = 400;
114    private static final int PID_2 = 401;
115    private static final int PID_3 = 402;
116
117    @Override
118    public void setUp() throws Exception {
119        super.setUp();
120
121        // intercept various broadcasts, and pretend that uids have packages
122        mServiceContext = new BroadcastInterceptingContext(getContext()) {
123            @Override
124            public PackageManager getPackageManager() {
125                return new MockPackageManager() {
126                    @Override
127                    public String[] getPackagesForUid(int uid) {
128                        return new String[] { "com.example" };
129                    }
130
131                    @Override
132                    public PackageInfo getPackageInfo(String packageName, int flags) {
133                        final PackageInfo info = new PackageInfo();
134                        final Signature signature;
135                        if ("android".equals(packageName)) {
136                            signature = new Signature("F00D");
137                        } else {
138                            signature = new Signature("DEAD");
139                        }
140                        info.signatures = new Signature[] { signature };
141                        return info;
142                    }
143                };
144            }
145        };
146
147        mPolicyDir = getContext().getFilesDir();
148        for (File file : mPolicyDir.listFiles()) {
149            file.delete();
150        }
151
152        mActivityManager = createMock(IActivityManager.class);
153        mPowerManager = createMock(IPowerManager.class);
154        mStatsService = createMock(INetworkStatsService.class);
155        mNetworkManagement = createMock(INetworkManagementService.class);
156        mPolicyListener = createMock(INetworkPolicyListener.class);
157        mTime = createMock(TrustedTime.class);
158        mConnManager = createMock(IConnectivityManager.class);
159        mNotifManager = createMock(INotificationManager.class);
160
161        mService = new NetworkPolicyManagerService(
162                mServiceContext, mActivityManager, mPowerManager, mStatsService,
163                mNetworkManagement, mTime, mPolicyDir);
164        mService.bindConnectivityManager(mConnManager);
165        mService.bindNotificationManager(mNotifManager);
166
167        // RemoteCallbackList needs a binder to use as key
168        expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
169        replay();
170        mService.registerListener(mPolicyListener);
171        verifyAndReset();
172
173        // catch the registered IProcessObserver during systemReady()
174        final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
175        mActivityManager.registerProcessObserver(capture(processObserver));
176        expectLastCall().atLeastOnce();
177
178        // expect to answer screen status during systemReady()
179        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
180        expectTime(System.currentTimeMillis());
181
182        // default behavior is background data enabled
183        expect(mConnManager.getBackgroundDataSetting()).andReturn(true);
184
185        replay();
186        mService.systemReady();
187        verifyAndReset();
188
189        mProcessObserver = processObserver.getValue();
190
191    }
192
193    @Override
194    public void tearDown() throws Exception {
195        for (File file : mPolicyDir.listFiles()) {
196            file.delete();
197        }
198
199        mServiceContext = null;
200        mPolicyDir = null;
201
202        mActivityManager = null;
203        mPowerManager = null;
204        mStatsService = null;
205        mPolicyListener = null;
206        mTime = null;
207
208        mService = null;
209        mProcessObserver = null;
210
211        super.tearDown();
212    }
213
214    @Suppress
215    public void testPolicyChangeTriggersBroadcast() throws Exception {
216        mService.setUidPolicy(UID_A, POLICY_NONE);
217
218        // change background policy and expect broadcast
219        final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
220                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
221
222        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
223
224        backgroundChanged.get();
225    }
226
227    public void testPidForegroundCombined() throws Exception {
228        // push all uid into background
229        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
230        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
231        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
232        assertFalse(mService.isUidForeground(UID_A));
233        assertFalse(mService.isUidForeground(UID_B));
234
235        // push one of the shared pids into foreground
236        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
237        assertTrue(mService.isUidForeground(UID_A));
238        assertFalse(mService.isUidForeground(UID_B));
239
240        // and swap another uid into foreground
241        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
242        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
243        assertFalse(mService.isUidForeground(UID_A));
244        assertTrue(mService.isUidForeground(UID_B));
245
246        // push both pid into foreground
247        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
248        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
249        assertTrue(mService.isUidForeground(UID_A));
250
251        // pull one out, should still be foreground
252        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
253        assertTrue(mService.isUidForeground(UID_A));
254
255        // pull final pid out, should now be background
256        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
257        assertFalse(mService.isUidForeground(UID_A));
258    }
259
260    public void testScreenChangesRules() throws Exception {
261        Future<Void> future;
262
263        expectSetUidNetworkRules(UID_A, false);
264        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
265        replay();
266        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
267        future.get();
268        verifyAndReset();
269
270        // push strict policy for foreground uid, verify ALLOW rule
271        expectSetUidNetworkRules(UID_A, false);
272        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
273        replay();
274        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
275        future.get();
276        verifyAndReset();
277
278        // now turn screen off and verify REJECT rule
279        expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
280        expectSetUidNetworkRules(UID_A, true);
281        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
282        replay();
283        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
284        future.get();
285        verifyAndReset();
286
287        // and turn screen back on, verify ALLOW rule restored
288        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
289        expectSetUidNetworkRules(UID_A, false);
290        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
291        replay();
292        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
293        future.get();
294        verifyAndReset();
295    }
296
297    public void testPolicyNone() throws Exception {
298        Future<Void> future;
299
300        expectSetUidNetworkRules(UID_A, false);
301        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
302        replay();
303        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
304        future.get();
305        verifyAndReset();
306
307        // POLICY_NONE should RULE_ALLOW in foreground
308        expectSetUidNetworkRules(UID_A, false);
309        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
310        replay();
311        mService.setUidPolicy(UID_A, POLICY_NONE);
312        future.get();
313        verifyAndReset();
314
315        // POLICY_NONE should RULE_ALLOW in background
316        expectSetUidNetworkRules(UID_A, false);
317        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
318        replay();
319        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
320        future.get();
321        verifyAndReset();
322    }
323
324    public void testPolicyReject() throws Exception {
325        Future<Void> future;
326
327        // POLICY_REJECT should RULE_ALLOW in background
328        expectSetUidNetworkRules(UID_A, true);
329        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
330        replay();
331        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
332        future.get();
333        verifyAndReset();
334
335        // POLICY_REJECT should RULE_ALLOW in foreground
336        expectSetUidNetworkRules(UID_A, false);
337        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
338        replay();
339        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
340        future.get();
341        verifyAndReset();
342
343        // POLICY_REJECT should RULE_REJECT in background
344        expectSetUidNetworkRules(UID_A, true);
345        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
346        replay();
347        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
348        future.get();
349        verifyAndReset();
350    }
351
352    public void testPolicyRejectAddRemove() throws Exception {
353        Future<Void> future;
354
355        // POLICY_NONE should have RULE_ALLOW in background
356        expectSetUidNetworkRules(UID_A, false);
357        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
358        replay();
359        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
360        mService.setUidPolicy(UID_A, POLICY_NONE);
361        future.get();
362        verifyAndReset();
363
364        // adding POLICY_REJECT should cause RULE_REJECT
365        expectSetUidNetworkRules(UID_A, true);
366        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
367        replay();
368        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
369        future.get();
370        verifyAndReset();
371
372        // removing POLICY_REJECT should return us to RULE_ALLOW
373        expectSetUidNetworkRules(UID_A, false);
374        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
375        replay();
376        mService.setUidPolicy(UID_A, POLICY_NONE);
377        future.get();
378        verifyAndReset();
379    }
380
381    public void testLastCycleBoundaryThisMonth() throws Exception {
382        // assume cycle day of "5th", which should be in same month
383        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
384        final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
385
386        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 5, 1024L, 1024L);
387        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
388        assertEquals(expectedCycle, actualCycle);
389    }
390
391    public void testLastCycleBoundaryLastMonth() throws Exception {
392        // assume cycle day of "20th", which should be in last month
393        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
394        final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
395
396        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 20, 1024L, 1024L);
397        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
398        assertEquals(expectedCycle, actualCycle);
399    }
400
401    public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
402        // assume cycle day of "30th" in february; should go to january
403        final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
404        final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
405
406        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
407        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
408        assertEquals(expectedCycle, actualCycle);
409    }
410
411    public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
412        // assume cycle day of "30th" in february, which should clamp
413        final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
414        final long expectedCycle = parseTime("2007-03-01T00:00:00.000Z");
415
416        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
417        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
418        assertEquals(expectedCycle, actualCycle);
419    }
420
421    public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
422        long elapsedRealtime = 0;
423        NetworkState[] state = null;
424        NetworkStats stats = null;
425        Future<Void> future;
426
427        final long TIME_FEB_15 = 1171497600000L;
428        final long TIME_MAR_10 = 1173484800000L;
429        final int CYCLE_DAY = 15;
430
431        // first, pretend that wifi network comes online. no policy active,
432        // which means we shouldn't push limit to interface.
433        state = new NetworkState[] { buildWifi() };
434        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
435        expectTime(TIME_MAR_10 + elapsedRealtime);
436        future = expectMeteredIfacesChanged();
437
438        replay();
439        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
440        future.get();
441        verifyAndReset();
442
443        // now change cycle to be on 15th, and test in early march, to verify we
444        // pick cycle day in previous month.
445        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
446        expectTime(TIME_MAR_10 + elapsedRealtime);
447
448        // pretend that 512 bytes total have happened
449        stats = new NetworkStats(elapsedRealtime, 1)
450                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L);
451        expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
452                .andReturn(stats).atLeastOnce();
453
454        // TODO: consider making strongly ordered mock
455        expectRemoveInterfaceQuota(TEST_IFACE);
456        expectSetInterfaceQuota(TEST_IFACE, 1536L);
457
458        expectClearNotifications();
459        future = expectMeteredIfacesChanged(TEST_IFACE);
460
461        replay();
462        setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L));
463        future.get();
464        verifyAndReset();
465    }
466
467    public void testUidRemovedPolicyCleared() throws Exception {
468        Future<Void> future;
469
470        // POLICY_REJECT should RULE_REJECT in background
471        expectSetUidNetworkRules(UID_A, true);
472        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
473        replay();
474        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
475        future.get();
476        verifyAndReset();
477
478        // uninstall should clear RULE_REJECT
479        expectSetUidNetworkRules(UID_A, false);
480        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
481        replay();
482        final Intent intent = new Intent(ACTION_UID_REMOVED);
483        intent.putExtra(EXTRA_UID, UID_A);
484        mServiceContext.sendBroadcast(intent);
485        future.get();
486        verifyAndReset();
487    }
488
489    private static long parseTime(String time) {
490        final Time result = new Time();
491        result.parse3339(time);
492        return result.toMillis(true);
493    }
494
495    private void setNetworkPolicies(NetworkPolicy... policies) {
496        mService.setNetworkPolicies(policies);
497    }
498
499    private static NetworkState buildWifi() {
500        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
501        info.setDetailedState(DetailedState.CONNECTED, null, null);
502        final LinkProperties prop = new LinkProperties();
503        prop.setInterfaceName(TEST_IFACE);
504        return new NetworkState(info, prop, null);
505    }
506
507    private void expectTime(long currentTime) throws Exception {
508        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
509        expect(mTime.hasCache()).andReturn(true).anyTimes();
510        expect(mTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
511        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
512        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
513    }
514
515    private void expectClearNotifications() throws Exception {
516        mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
517        expectLastCall().anyTimes();
518    }
519
520    private void expectSetInterfaceQuota(String iface, long quota) throws Exception {
521        mNetworkManagement.setInterfaceQuota(iface, quota);
522        expectLastCall().atLeastOnce();
523    }
524
525    private void expectRemoveInterfaceQuota(String iface) throws Exception {
526        mNetworkManagement.removeInterfaceQuota(iface);
527        expectLastCall().atLeastOnce();
528    }
529
530    private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
531            throws Exception {
532        mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
533        expectLastCall().atLeastOnce();
534    }
535
536    private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
537        final FutureAnswer future = new FutureAnswer();
538        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
539        expectLastCall().andAnswer(future);
540        return future;
541    }
542
543    private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
544        final FutureAnswer future = new FutureAnswer();
545        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
546        expectLastCall().andAnswer(future);
547        return future;
548    }
549
550    private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
551        @Override
552        public Void get() throws InterruptedException, ExecutionException {
553            try {
554                return get(5, TimeUnit.SECONDS);
555            } catch (TimeoutException e) {
556                throw new RuntimeException(e);
557            }
558        }
559
560        @Override
561        public Void answer() {
562            set(null);
563            return null;
564        }
565    }
566
567    private void replay() {
568        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
569                mNetworkManagement, mTime, mConnManager, mNotifManager);
570    }
571
572    private void verifyAndReset() {
573        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
574                mNetworkManagement, mTime, mConnManager, mNotifManager);
575        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
576                mNetworkManagement, mTime, mConnManager, mNotifManager);
577    }
578}
579