NetworkPolicyManagerServiceTest.java revision 1b5a2a96f793211bfbd39aa29cc41031dfa23950
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.net.ConnectivityManager.CONNECTIVITY_ACTION;
20import static android.net.ConnectivityManager.TYPE_WIFI;
21import static android.net.NetworkPolicyManager.POLICY_NONE;
22import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
23import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
24import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
25import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
26import static android.net.NetworkStats.TAG_NONE;
27import static android.net.NetworkStats.UID_ALL;
28import static android.net.NetworkTemplate.MATCH_WIFI;
29import static org.easymock.EasyMock.anyInt;
30import static org.easymock.EasyMock.aryEq;
31import static org.easymock.EasyMock.capture;
32import static org.easymock.EasyMock.createMock;
33import static org.easymock.EasyMock.eq;
34import static org.easymock.EasyMock.expect;
35import static org.easymock.EasyMock.expectLastCall;
36import static org.easymock.EasyMock.isA;
37
38import android.app.IActivityManager;
39import android.app.INotificationManager;
40import android.app.IProcessObserver;
41import android.content.Intent;
42import android.content.pm.PackageManager;
43import android.net.ConnectivityManager;
44import android.net.IConnectivityManager;
45import android.net.INetworkPolicyListener;
46import android.net.INetworkStatsService;
47import android.net.LinkProperties;
48import android.net.NetworkInfo;
49import android.net.NetworkInfo.DetailedState;
50import android.net.NetworkPolicy;
51import android.net.NetworkState;
52import android.net.NetworkStats;
53import android.net.NetworkTemplate;
54import android.os.Binder;
55import android.os.IPowerManager;
56import android.test.AndroidTestCase;
57import android.test.mock.MockPackageManager;
58import android.test.suitebuilder.annotation.LargeTest;
59import android.test.suitebuilder.annotation.Suppress;
60import android.text.format.Time;
61import android.util.TrustedTime;
62
63import com.android.server.net.NetworkPolicyManagerService;
64
65import org.easymock.Capture;
66import org.easymock.EasyMock;
67
68import java.io.File;
69import java.util.concurrent.Future;
70
71/**
72 * Tests for {@link NetworkPolicyManagerService}.
73 */
74@LargeTest
75public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
76    private static final String TAG = "NetworkPolicyManagerServiceTest";
77
78    private static final long TEST_START = 1194220800000L;
79    private static final String TEST_IFACE = "test0";
80
81    private static NetworkTemplate sTemplateWifi = new NetworkTemplate(MATCH_WIFI, null);
82
83    private BroadcastInterceptingContext mServiceContext;
84    private File mPolicyDir;
85
86    private IActivityManager mActivityManager;
87    private IPowerManager mPowerManager;
88    private INetworkStatsService mStatsService;
89    private INetworkPolicyListener mPolicyListener;
90    private TrustedTime mTime;
91    private IConnectivityManager mConnManager;
92    private INotificationManager mNotifManager;
93
94    private NetworkPolicyManagerService mService;
95    private IProcessObserver mProcessObserver;
96
97    private Binder mStubBinder = new Binder();
98
99    private static final int UID_A = android.os.Process.FIRST_APPLICATION_UID + 800;
100    private static final int UID_B = android.os.Process.FIRST_APPLICATION_UID + 801;
101
102    private static final int PID_1 = 400;
103    private static final int PID_2 = 401;
104    private static final int PID_3 = 402;
105
106    @Override
107    public void setUp() throws Exception {
108        super.setUp();
109
110        // intercept various broadcasts, and pretend that uids have packages
111        mServiceContext = new BroadcastInterceptingContext(getContext()) {
112            @Override
113            public PackageManager getPackageManager() {
114                return new MockPackageManager() {
115                    @Override
116                    public String[] getPackagesForUid(int uid) {
117                        return new String[] { "com.example" };
118                    }
119                };
120            }
121        };
122
123        mPolicyDir = getContext().getFilesDir();
124
125        mActivityManager = createMock(IActivityManager.class);
126        mPowerManager = createMock(IPowerManager.class);
127        mStatsService = createMock(INetworkStatsService.class);
128        mPolicyListener = createMock(INetworkPolicyListener.class);
129        mTime = createMock(TrustedTime.class);
130        mConnManager = createMock(IConnectivityManager.class);
131        mNotifManager = createMock(INotificationManager.class);
132
133        mService = new NetworkPolicyManagerService(
134                mServiceContext, mActivityManager, mPowerManager, mStatsService, mTime, mPolicyDir);
135        mService.bindConnectivityManager(mConnManager);
136        mService.bindNotificationManager(mNotifManager);
137
138        // RemoteCallbackList needs a binder to use as key
139        expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
140        replay();
141        mService.registerListener(mPolicyListener);
142        verifyAndReset();
143
144        // catch the registered IProcessObserver during systemReady()
145        final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
146        mActivityManager.registerProcessObserver(capture(processObserver));
147        expectLastCall().atLeastOnce();
148
149        // expect to answer screen status during systemReady()
150        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
151        expectTime(System.currentTimeMillis());
152
153        replay();
154        mService.systemReady();
155        verifyAndReset();
156
157        mProcessObserver = processObserver.getValue();
158
159    }
160
161    @Override
162    public void tearDown() throws Exception {
163        for (File file : mPolicyDir.listFiles()) {
164            file.delete();
165        }
166
167        mServiceContext = null;
168        mPolicyDir = null;
169
170        mActivityManager = null;
171        mPowerManager = null;
172        mStatsService = null;
173        mPolicyListener = null;
174        mTime = null;
175
176        mService = null;
177        mProcessObserver = null;
178
179        super.tearDown();
180    }
181
182    @Suppress
183    public void testPolicyChangeTriggersBroadcast() throws Exception {
184        mService.setUidPolicy(UID_A, POLICY_NONE);
185
186        // change background policy and expect broadcast
187        final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
188                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
189
190        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
191
192        backgroundChanged.get();
193    }
194
195    public void testPidForegroundCombined() throws Exception {
196        // push all uid into background
197        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
198        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
199        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
200        assertFalse(mService.isUidForeground(UID_A));
201        assertFalse(mService.isUidForeground(UID_B));
202
203        // push one of the shared pids into foreground
204        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
205        assertTrue(mService.isUidForeground(UID_A));
206        assertFalse(mService.isUidForeground(UID_B));
207
208        // and swap another uid into foreground
209        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
210        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
211        assertFalse(mService.isUidForeground(UID_A));
212        assertTrue(mService.isUidForeground(UID_B));
213
214        // push both pid into foreground
215        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
216        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
217        assertTrue(mService.isUidForeground(UID_A));
218
219        // pull one out, should still be foreground
220        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
221        assertTrue(mService.isUidForeground(UID_A));
222
223        // pull final pid out, should now be background
224        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
225        assertFalse(mService.isUidForeground(UID_A));
226    }
227
228    public void testScreenChangesRules() throws Exception {
229        // push strict policy for foreground uid, verify ALLOW rule
230        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
231        replay();
232        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
233        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
234        verifyAndReset();
235
236        // now turn screen off and verify REJECT rule
237        expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
238        expectRulesChanged(UID_A, RULE_REJECT_METERED);
239        replay();
240        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
241        verifyAndReset();
242
243        // and turn screen back on, verify ALLOW rule restored
244        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
245        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
246        replay();
247        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
248        verifyAndReset();
249    }
250
251    public void testPolicyNone() throws Exception {
252        // POLICY_NONE should RULE_ALLOW in foreground
253        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
254        replay();
255        mService.setUidPolicy(UID_A, POLICY_NONE);
256        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
257        verifyAndReset();
258
259        // POLICY_NONE should RULE_ALLOW in background
260        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
261        replay();
262        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
263        verifyAndReset();
264    }
265
266    public void testPolicyReject() throws Exception {
267        // POLICY_REJECT should RULE_ALLOW in background
268        expectRulesChanged(UID_A, RULE_REJECT_METERED);
269        replay();
270        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
271        verifyAndReset();
272
273        // POLICY_REJECT should RULE_ALLOW in foreground
274        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
275        replay();
276        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
277        verifyAndReset();
278
279        // POLICY_REJECT should RULE_REJECT in background
280        expectRulesChanged(UID_A, RULE_REJECT_METERED);
281        replay();
282        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
283        verifyAndReset();
284    }
285
286    public void testPolicyRejectAddRemove() throws Exception {
287        // POLICY_NONE should have RULE_ALLOW in background
288        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
289        replay();
290        mService.setUidPolicy(UID_A, POLICY_NONE);
291        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
292        verifyAndReset();
293
294        // adding POLICY_REJECT should cause RULE_REJECT
295        expectRulesChanged(UID_A, RULE_REJECT_METERED);
296        replay();
297        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
298        verifyAndReset();
299
300        // removing POLICY_REJECT should return us to RULE_ALLOW
301        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
302        replay();
303        mService.setUidPolicy(UID_A, POLICY_NONE);
304        verifyAndReset();
305    }
306
307    public void testLastCycleBoundaryThisMonth() throws Exception {
308        // assume cycle day of "5th", which should be in same month
309        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
310        final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
311
312        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 5, 1024L, 1024L);
313        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
314        assertEquals(expectedCycle, actualCycle);
315    }
316
317    public void testLastCycleBoundaryLastMonth() throws Exception {
318        // assume cycle day of "20th", which should be in last month
319        final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
320        final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
321
322        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 20, 1024L, 1024L);
323        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
324        assertEquals(expectedCycle, actualCycle);
325    }
326
327    public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
328        // assume cycle day of "30th" in february; should go to january
329        final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
330        final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
331
332        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
333        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
334        assertEquals(expectedCycle, actualCycle);
335    }
336
337    public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
338        // assume cycle day of "30th" in february, which should clamp
339        final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
340        final long expectedCycle = parseTime("2007-03-01T00:00:00.000Z");
341
342        final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
343        final long actualCycle = computeLastCycleBoundary(currentTime, policy);
344        assertEquals(expectedCycle, actualCycle);
345    }
346
347    public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
348        long elapsedRealtime = 0;
349        NetworkState[] state = null;
350        NetworkStats stats = null;
351
352        final long TIME_FEB_15 = 1171497600000L;
353        final long TIME_MAR_10 = 1173484800000L;
354        final int CYCLE_DAY = 15;
355
356        // first, pretend that wifi network comes online. no policy active,
357        // which means we shouldn't push limit to interface.
358        state = new NetworkState[] { buildWifi() };
359        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
360        expectTime(TIME_MAR_10 + elapsedRealtime);
361        expectMeteredIfacesChanged();
362
363        replay();
364        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
365        verifyAndReset();
366
367        // now change cycle to be on 15th, and test in early march, to verify we
368        // pick cycle day in previous month.
369        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
370        expectTime(TIME_MAR_10 + elapsedRealtime);
371
372        // pretend that 512 bytes total have happened
373        stats = new NetworkStats(elapsedRealtime, 1)
374                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 256L);
375        expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
376                .andReturn(stats).atLeastOnce();
377
378        // expect that quota remaining should be 1536 bytes
379        // TODO: write up NetworkManagementService mock
380
381        expectClearNotifications();
382        expectMeteredIfacesChanged(TEST_IFACE);
383
384        replay();
385        setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L));
386        verifyAndReset();
387    }
388
389    private static long parseTime(String time) {
390        final Time result = new Time();
391        result.parse3339(time);
392        return result.toMillis(true);
393    }
394
395    private void setNetworkPolicies(NetworkPolicy... policies) {
396        mService.setNetworkPolicies(policies);
397    }
398
399    private static NetworkState buildWifi() {
400        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
401        info.setDetailedState(DetailedState.CONNECTED, null, null);
402        final LinkProperties prop = new LinkProperties();
403        prop.setInterfaceName(TEST_IFACE);
404        return new NetworkState(info, prop, null);
405    }
406
407    private void expectTime(long currentTime) throws Exception {
408        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
409        expect(mTime.hasCache()).andReturn(true).anyTimes();
410        expect(mTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
411        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
412        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
413    }
414
415    private void expectClearNotifications() throws Exception {
416        mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
417        expectLastCall().anyTimes();
418    }
419
420    private void expectRulesChanged(int uid, int policy) throws Exception {
421        mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
422        expectLastCall().atLeastOnce();
423    }
424
425    private void expectMeteredIfacesChanged(String... ifaces) throws Exception {
426        mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
427        expectLastCall().atLeastOnce();
428    }
429
430    private void replay() {
431        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
432                mConnManager, mNotifManager);
433    }
434
435    private void verifyAndReset() {
436        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
437                mConnManager, mNotifManager);
438        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
439                mConnManager, mNotifManager);
440    }
441}
442