NetworkPolicyManagerServiceTest.java revision 50fd36d7c38c40b087c8f3e3172478abe0c051d9
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        replay();
183        mService.systemReady();
184        verifyAndReset();
185
186        mProcessObserver = processObserver.getValue();
187
188    }
189
190    @Override
191    public void tearDown() throws Exception {
192        for (File file : mPolicyDir.listFiles()) {
193            file.delete();
194        }
195
196        mServiceContext = null;
197        mPolicyDir = null;
198
199        mActivityManager = null;
200        mPowerManager = null;
201        mStatsService = null;
202        mPolicyListener = null;
203        mTime = null;
204
205        mService = null;
206        mProcessObserver = null;
207
208        super.tearDown();
209    }
210
211    @Suppress
212    public void testPolicyChangeTriggersBroadcast() throws Exception {
213        mService.setUidPolicy(UID_A, POLICY_NONE);
214
215        // change background policy and expect broadcast
216        final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
217                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
218
219        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
220
221        backgroundChanged.get();
222    }
223
224    public void testPidForegroundCombined() throws Exception {
225        // push all uid into background
226        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
227        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
228        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
229        assertFalse(mService.isUidForeground(UID_A));
230        assertFalse(mService.isUidForeground(UID_B));
231
232        // push one of the shared pids into foreground
233        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
234        assertTrue(mService.isUidForeground(UID_A));
235        assertFalse(mService.isUidForeground(UID_B));
236
237        // and swap another uid into foreground
238        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
239        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
240        assertFalse(mService.isUidForeground(UID_A));
241        assertTrue(mService.isUidForeground(UID_B));
242
243        // push both pid into foreground
244        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
245        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
246        assertTrue(mService.isUidForeground(UID_A));
247
248        // pull one out, should still be foreground
249        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
250        assertTrue(mService.isUidForeground(UID_A));
251
252        // pull final pid out, should now be background
253        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
254        assertFalse(mService.isUidForeground(UID_A));
255    }
256
257    public void testScreenChangesRules() throws Exception {
258        Future<Void> future;
259
260        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
261        replay();
262        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
263        future.get();
264        verifyAndReset();
265
266        // push strict policy for foreground uid, verify ALLOW rule
267        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
268        replay();
269        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
270        future.get();
271        verifyAndReset();
272
273        // now turn screen off and verify REJECT rule
274        expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
275        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
276        replay();
277        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
278        future.get();
279        verifyAndReset();
280
281        // and turn screen back on, verify ALLOW rule restored
282        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
283        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
284        replay();
285        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
286        future.get();
287        verifyAndReset();
288    }
289
290    public void testPolicyNone() throws Exception {
291        Future<Void> future;
292
293        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
294        replay();
295        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
296        future.get();
297        verifyAndReset();
298
299        // POLICY_NONE should RULE_ALLOW in foreground
300        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
301        replay();
302        mService.setUidPolicy(UID_A, POLICY_NONE);
303        future.get();
304        verifyAndReset();
305
306        // POLICY_NONE should RULE_ALLOW in background
307        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
308        replay();
309        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
310        future.get();
311        verifyAndReset();
312    }
313
314    public void testPolicyReject() throws Exception {
315        Future<Void> future;
316
317        // POLICY_REJECT should RULE_ALLOW in background
318        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
319        replay();
320        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
321        future.get();
322        verifyAndReset();
323
324        // POLICY_REJECT should RULE_ALLOW in foreground
325        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
326        replay();
327        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
328        future.get();
329        verifyAndReset();
330
331        // POLICY_REJECT should RULE_REJECT in background
332        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
333        replay();
334        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
335        future.get();
336        verifyAndReset();
337    }
338
339    public void testPolicyRejectAddRemove() throws Exception {
340        Future<Void> future;
341
342        // POLICY_NONE should have RULE_ALLOW in background
343        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
344        replay();
345        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
346        mService.setUidPolicy(UID_A, POLICY_NONE);
347        future.get();
348        verifyAndReset();
349
350        // adding POLICY_REJECT should cause RULE_REJECT
351        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
352        replay();
353        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
354        future.get();
355        verifyAndReset();
356
357        // removing POLICY_REJECT should return us to RULE_ALLOW
358        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
359        replay();
360        mService.setUidPolicy(UID_A, POLICY_NONE);
361        future.get();
362        verifyAndReset();
363    }
364
365    public void testLastCycleBoundaryThisMonth() throws Exception {
366        // assume cycle day of "5th", which should be in same month
367        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
368        final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
369
370        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 5, 1024L, 1024L);
371        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
372        assertEquals(expectedCycle, actualCycle);
373    }
374
375    public void testLastCycleBoundaryLastMonth() throws Exception {
376        // assume cycle day of "20th", which should be in last month
377        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
378        final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
379
380        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 20, 1024L, 1024L);
381        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
382        assertEquals(expectedCycle, actualCycle);
383    }
384
385    public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
386        // assume cycle day of "30th" in february; should go to january
387        final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
388        final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
389
390        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
391        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
392        assertEquals(expectedCycle, actualCycle);
393    }
394
395    public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
396        // assume cycle day of "30th" in february, which should clamp
397        final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
398        final long expectedCycle = parseTime("2007-03-01T00:00:00.000Z");
399
400        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
401        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
402        assertEquals(expectedCycle, actualCycle);
403    }
404
405    public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
406        long elapsedRealtime = 0;
407        NetworkState[] state = null;
408        NetworkStats stats = null;
409        Future<Void> future;
410
411        final long TIME_FEB_15 = 1171497600000L;
412        final long TIME_MAR_10 = 1173484800000L;
413        final int CYCLE_DAY = 15;
414
415        // first, pretend that wifi network comes online. no policy active,
416        // which means we shouldn't push limit to interface.
417        state = new NetworkState[] { buildWifi() };
418        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
419        expectTime(TIME_MAR_10 + elapsedRealtime);
420        future = expectMeteredIfacesChanged();
421
422        replay();
423        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
424        future.get();
425        verifyAndReset();
426
427        // now change cycle to be on 15th, and test in early march, to verify we
428        // pick cycle day in previous month.
429        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
430        expectTime(TIME_MAR_10 + elapsedRealtime);
431
432        // pretend that 512 bytes total have happened
433        stats = new NetworkStats(elapsedRealtime, 1)
434                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 256L);
435        expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
436                .andReturn(stats).atLeastOnce();
437
438        // expect that quota remaining should be 1536 bytes
439        // TODO: write up NetworkManagementService mock
440
441        expectClearNotifications();
442        future = expectMeteredIfacesChanged(TEST_IFACE);
443
444        replay();
445        setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L));
446        future.get();
447        verifyAndReset();
448    }
449
450    public void testUidRemovedPolicyCleared() throws Exception {
451        Future<Void> future;
452
453        // POLICY_REJECT should RULE_REJECT in background
454        future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
455        replay();
456        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
457        future.get();
458        verifyAndReset();
459
460        // uninstall should clear RULE_REJECT
461        future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
462        replay();
463        final Intent intent = new Intent(ACTION_UID_REMOVED);
464        intent.putExtra(EXTRA_UID, UID_A);
465        mServiceContext.sendBroadcast(intent);
466        future.get();
467        verifyAndReset();
468    }
469
470    private static long parseTime(String time) {
471        final Time result = new Time();
472        result.parse3339(time);
473        return result.toMillis(true);
474    }
475
476    private void setNetworkPolicies(NetworkPolicy... policies) {
477        mService.setNetworkPolicies(policies);
478    }
479
480    private static NetworkState buildWifi() {
481        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
482        info.setDetailedState(DetailedState.CONNECTED, null, null);
483        final LinkProperties prop = new LinkProperties();
484        prop.setInterfaceName(TEST_IFACE);
485        return new NetworkState(info, prop, null);
486    }
487
488    private void expectTime(long currentTime) throws Exception {
489        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
490        expect(mTime.hasCache()).andReturn(true).anyTimes();
491        expect(mTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
492        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
493        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
494    }
495
496    private void expectClearNotifications() throws Exception {
497        mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
498        expectLastCall().anyTimes();
499    }
500
501    private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
502        final FutureAnswer future = new FutureAnswer();
503        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
504        expectLastCall().andAnswer(future);
505        return future;
506    }
507
508    private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
509        final FutureAnswer future = new FutureAnswer();
510        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
511        expectLastCall().andAnswer(future);
512        return future;
513    }
514
515    private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
516        @Override
517        public Void get() throws InterruptedException, ExecutionException {
518            try {
519                return get(5, TimeUnit.SECONDS);
520            } catch (TimeoutException e) {
521                throw new RuntimeException(e);
522            }
523        }
524
525        @Override
526        public Void answer() {
527            set(null);
528            return null;
529        }
530    }
531
532    private void replay() {
533        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
534                mNetworkManagement, mTime, mConnManager, mNotifManager);
535    }
536
537    private void verifyAndReset() {
538        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
539                mNetworkManagement, mTime, mConnManager, mNotifManager);
540        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
541                mNetworkManagement, mTime, mConnManager, mNotifManager);
542    }
543}
544