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