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