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