ThrottleServiceTest.java revision bdfce2ec05a3e9ca6acd6711de6133e06f2446e6
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.NetworkStats.SET_DEFAULT;
20import static android.net.NetworkStats.TAG_NONE;
21import static android.net.NetworkStats.UID_ALL;
22import static org.easymock.EasyMock.createMock;
23import static org.easymock.EasyMock.eq;
24import static org.easymock.EasyMock.expect;
25import static org.easymock.EasyMock.expectLastCall;
26import static org.easymock.EasyMock.isA;
27import static org.easymock.EasyMock.replay;
28import static org.easymock.EasyMock.reset;
29import static org.easymock.EasyMock.verify;
30
31import android.content.ContentResolver;
32import android.content.Context;
33import android.content.Intent;
34import android.net.INetworkManagementEventObserver;
35import android.net.NetworkStats;
36import android.net.ThrottleManager;
37import android.os.IBinder;
38import android.os.INetworkManagementService;
39import android.os.ServiceManager;
40import android.os.SystemClock;
41import android.provider.Settings;
42import android.test.AndroidTestCase;
43import android.test.suitebuilder.annotation.LargeTest;
44import android.test.suitebuilder.annotation.Suppress;
45import android.text.format.DateUtils;
46import android.util.Log;
47import android.util.TrustedTime;
48
49import java.util.concurrent.Future;
50
51/**
52 * Tests for {@link ThrottleService}.
53 */
54@LargeTest
55public class ThrottleServiceTest extends AndroidTestCase {
56    private static final String TAG = "ThrottleServiceTest";
57
58    private static final long MB_IN_BYTES = 1024 * 1024;
59
60    private static final int TEST_KBITPS = 222;
61    private static final int TEST_RESET_DAY = 11;
62
63    private static final String TEST_IFACE = "test0";
64
65    private BroadcastInterceptingContext mWatchingContext;
66    private INetworkManagementService mMockNMService;
67    private TrustedTime mMockTime;
68
69    private ThrottleService mThrottleService;
70
71    @Override
72    public void setUp() throws Exception {
73        super.setUp();
74
75        mWatchingContext = new BroadcastInterceptingContext(getContext());
76
77        mMockNMService = createMock(INetworkManagementService.class);
78        mMockTime = createMock(TrustedTime.class);
79
80        mThrottleService = new ThrottleService(
81                mWatchingContext, mMockNMService, mMockTime, TEST_IFACE);
82    }
83
84    @Override
85    public void tearDown() throws Exception {
86        mWatchingContext = null;
87        mMockNMService = null;
88
89        mThrottleService.shutdown();
90        mThrottleService = null;
91
92        clearThrottlePolicy();
93
94        super.tearDown();
95    }
96
97    public void testNoPolicyNotThrottled() throws Exception {
98        expectTimeCurrent();
99        expectSystemReady();
100
101        // provide stats without policy, verify not throttled
102        expectGetInterfaceCounter(1 * MB_IN_BYTES, 2 * MB_IN_BYTES);
103        expectSetInterfaceThrottle(-1, -1);
104
105        replay(mMockTime, mMockNMService);
106        systemReady();
107        verify(mMockTime, mMockNMService);
108    }
109
110    public void testUnderLimitNotThrottled() throws Exception {
111        setThrottlePolicy(200 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
112
113        expectTimeCurrent();
114        expectSystemReady();
115
116        // provide stats under limits, and verify not throttled
117        expectGetInterfaceCounter(1 * MB_IN_BYTES, 2 * MB_IN_BYTES);
118        expectSetInterfaceThrottle(-1, -1);
119
120        replay(mMockTime, mMockNMService);
121        systemReady();
122        verify(mMockTime, mMockNMService);
123    }
124
125    public void testOverLimitThrottled() throws Exception {
126        setThrottlePolicy(200 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
127
128        expectTimeCurrent();
129        expectSystemReady();
130
131        // provide stats over limits, and verify throttled
132        expectGetInterfaceCounter(500 * MB_IN_BYTES, 600 * MB_IN_BYTES);
133        expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS);
134
135        replay(mMockTime, mMockNMService);
136        systemReady();
137        verify(mMockTime, mMockNMService);
138    }
139
140    public void testUnderThenOverLimitThrottled() throws Exception {
141        setThrottlePolicy(201 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
142
143        expectTimeCurrent();
144        expectSystemReady();
145
146        // provide stats right under 201MB limit, verify not throttled
147        expectGetInterfaceCounter(100 * MB_IN_BYTES, 100 * MB_IN_BYTES);
148        expectSetInterfaceThrottle(-1, -1);
149
150        replay(mMockTime, mMockNMService);
151        systemReady();
152        verify(mMockTime, mMockNMService);
153        reset(mMockTime, mMockNMService);
154
155        expectTimeCurrent();
156
157        // adjust usage to bump over limit, verify throttle kicks in
158        expectGetInterfaceCounter(105 * MB_IN_BYTES, 100 * MB_IN_BYTES);
159        expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS);
160
161        // and kick poll event which should throttle
162        replay(mMockTime, mMockNMService);
163        forceServicePoll();
164        verify(mMockTime, mMockNMService);
165    }
166
167    public void testUpdatedPolicyThrottled() throws Exception {
168        setThrottlePolicy(500 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
169
170        expectTimeCurrent();
171        expectSystemReady();
172
173        // provide stats under limit, verify not throttled
174        expectGetInterfaceCounter(50 * MB_IN_BYTES, 50 * MB_IN_BYTES);
175        expectSetInterfaceThrottle(-1, -1);
176
177        replay(mMockTime, mMockNMService);
178        systemReady();
179        verify(mMockTime, mMockNMService);
180        reset(mMockTime, mMockNMService);
181
182        expectTimeCurrent();
183
184        // provide same stats, but verify that modified policy will throttle
185        expectGetInterfaceCounter(50 * MB_IN_BYTES, 50 * MB_IN_BYTES);
186        expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS);
187
188        replay(mMockTime, mMockNMService);
189
190        // now adjust policy to bump usage over limit
191        setThrottlePolicy(5 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
192
193        // and wait for policy updated broadcast
194        mWatchingContext.nextBroadcastIntent(ThrottleManager.POLICY_CHANGED_ACTION).get();
195
196        verify(mMockTime, mMockNMService);
197    }
198
199    public void testWithPolicyOverLimitThrottledAndRemovedAfterCycle() throws Exception {
200        setThrottlePolicy(90 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY);
201
202        final long baseTime = System.currentTimeMillis();
203
204        expectTime(baseTime);
205        expectSystemReady();
206
207        // provide stats over limit, verify throttle kicks in
208        expectGetInterfaceCounter(50 * MB_IN_BYTES, 50 * MB_IN_BYTES);
209        expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS);
210
211        replay(mMockTime, mMockNMService);
212        systemReady();
213        verify(mMockTime, mMockNMService);
214        reset(mMockTime, mMockNMService);
215
216        // pretend that time has jumped forward two months
217        expectTime(baseTime + DateUtils.WEEK_IN_MILLIS * 8);
218
219        // provide slightly updated stats, but verify throttle is removed
220        expectGetInterfaceCounter(60 * MB_IN_BYTES, 60 * MB_IN_BYTES);
221        expectSetInterfaceThrottle(-1, -1);
222
223        // and kick poll event which should throttle
224        replay(mMockTime, mMockNMService);
225        forceServiceReset();
226        verify(mMockTime, mMockNMService);
227    }
228
229    @Suppress
230    public void testReturnStats() throws Exception {
231        final IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
232        final INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
233
234        // test is currently no-op, just exercises stats apis
235        Log.d(TAG, nmService.getNetworkStatsSummaryDev().toString());
236        Log.d(TAG, nmService.getNetworkStatsSummaryXt().toString());
237        Log.d(TAG, nmService.getNetworkStatsDetail().toString());
238    }
239
240    /**
241     * Persist the given {@link ThrottleService} policy into {@link Settings}.
242     */
243    public void setThrottlePolicy(long thresholdBytes, int valueKbitps, int resetDay) {
244        final ContentResolver resolver = getContext().getContentResolver();
245        Settings.Global.putLong(resolver, Settings.Global.THROTTLE_THRESHOLD_BYTES, thresholdBytes);
246        Settings.Global.putInt(resolver, Settings.Global.THROTTLE_VALUE_KBITSPS, valueKbitps);
247        Settings.Global.putInt(resolver, Settings.Global.THROTTLE_RESET_DAY, resetDay);
248    }
249
250    /**
251     * Clear any {@link ThrottleService} policy from {@link Settings}.
252     */
253    public void clearThrottlePolicy() {
254        final ContentResolver resolver = getContext().getContentResolver();
255        Settings.Global.putString(resolver, Settings.Global.THROTTLE_THRESHOLD_BYTES, null);
256        Settings.Global.putString(resolver, Settings.Global.THROTTLE_VALUE_KBITSPS, null);
257        Settings.Global.putString(resolver, Settings.Global.THROTTLE_RESET_DAY, null);
258    }
259
260    /**
261     * Expect any {@link TrustedTime} mock calls, and respond with
262     * {@link System#currentTimeMillis()}.
263     */
264    public void expectTimeCurrent() throws Exception {
265        expectTime(System.currentTimeMillis());
266    }
267
268    /**
269     * Expect any {@link TrustedTime} mock calls, and respond with the given
270     * time in response to {@link TrustedTime#currentTimeMillis()}.
271     */
272    public void expectTime(long currentTime) throws Exception {
273        expect(mMockTime.forceRefresh()).andReturn(false).anyTimes();
274        expect(mMockTime.hasCache()).andReturn(true).anyTimes();
275        expect(mMockTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
276        expect(mMockTime.getCacheAge()).andReturn(0L).anyTimes();
277        expect(mMockTime.getCacheCertainty()).andReturn(0L).anyTimes();
278    }
279
280    /**
281     * Expect {@link ThrottleService#systemReady()} generated calls, such as
282     * connecting with {@link NetworkManagementService} mock.
283     */
284    public void expectSystemReady() throws Exception {
285        mMockNMService.registerObserver(isA(INetworkManagementEventObserver.class));
286        expectLastCall().atLeastOnce();
287    }
288
289    /**
290     * Expect {@link NetworkManagementService#getNetworkStatsSummaryDev()} mock
291     * calls, responding with the given counter values.
292     */
293    public void expectGetInterfaceCounter(long rx, long tx) throws Exception {
294        // TODO: provide elapsedRealtime mock to match TimeAuthority
295        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
296        stats.addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, rx, 0L, tx, 0L, 0);
297
298        expect(mMockNMService.getNetworkStatsSummaryDev()).andReturn(stats).atLeastOnce();
299    }
300
301    /**
302     * Expect {@link NetworkManagementService#setInterfaceThrottle} mock call
303     * with the specified parameters.
304     */
305    public void expectSetInterfaceThrottle(int rx, int tx) throws Exception {
306        mMockNMService.setInterfaceThrottle(isA(String.class), eq(rx), eq(tx));
307        expectLastCall().atLeastOnce();
308    }
309
310    /**
311     * Dispatch {@link ThrottleService#systemReady()} and block until finished.
312     */
313    public void systemReady() throws Exception {
314        final Future<Intent> policyChanged = mWatchingContext.nextBroadcastIntent(
315                ThrottleManager.POLICY_CHANGED_ACTION);
316        final Future<Intent> pollAction = mWatchingContext.nextBroadcastIntent(
317                ThrottleManager.THROTTLE_POLL_ACTION);
318
319        mThrottleService.systemReady();
320
321        // wait for everything to settle; for policy to update and for first poll
322        policyChanged.get();
323        pollAction.get();
324    }
325
326    /**
327     * Dispatch {@link ThrottleService#dispatchPoll()} and block until finished.
328     */
329    public void forceServicePoll() throws Exception {
330        // during systemReady() service already pushed a sticky broadcast, so we
331        // need to skip the immediate and wait for the updated sticky.
332        final Future<Intent> pollAction = mWatchingContext.nextBroadcastIntent(
333                ThrottleManager.THROTTLE_POLL_ACTION);
334
335        mThrottleService.dispatchPoll();
336
337        pollAction.get();
338    }
339
340    /**
341     * Dispatch {@link ThrottleService#dispatchReset()} and block until finished.
342     */
343    public void forceServiceReset() throws Exception {
344        // during systemReady() service already pushed a sticky broadcast, so we
345        // need to skip the immediate and wait for the updated sticky.
346        final Future<Intent> pollAction = mWatchingContext.nextBroadcastIntent(
347                ThrottleManager.THROTTLE_POLL_ACTION);
348
349        mThrottleService.dispatchReset();
350
351        pollAction.get();
352    }
353}
354