NetworkStatsServiceTest.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.NetworkStats.TAG_NONE;
22import static android.net.NetworkStats.UID_ALL;
23import static android.net.NetworkTemplate.MATCH_WIFI;
24import static android.text.format.DateUtils.DAY_IN_MILLIS;
25import static android.text.format.DateUtils.HOUR_IN_MILLIS;
26import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
27import static android.text.format.DateUtils.WEEK_IN_MILLIS;
28import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
29import static org.easymock.EasyMock.anyLong;
30import static org.easymock.EasyMock.createMock;
31import static org.easymock.EasyMock.eq;
32import static org.easymock.EasyMock.expect;
33import static org.easymock.EasyMock.expectLastCall;
34import static org.easymock.EasyMock.isA;
35
36import android.app.AlarmManager;
37import android.app.IAlarmManager;
38import android.app.PendingIntent;
39import android.content.Intent;
40import android.net.IConnectivityManager;
41import android.net.LinkProperties;
42import android.net.NetworkInfo;
43import android.net.NetworkInfo.DetailedState;
44import android.net.NetworkState;
45import android.net.NetworkStats;
46import android.net.NetworkStatsHistory;
47import android.net.NetworkTemplate;
48import android.os.INetworkManagementService;
49import android.test.AndroidTestCase;
50import android.test.suitebuilder.annotation.LargeTest;
51import android.util.TrustedTime;
52
53import com.android.server.net.NetworkStatsService;
54import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
55
56import org.easymock.EasyMock;
57
58import java.io.File;
59
60/**
61 * Tests for {@link NetworkStatsService}.
62 */
63@LargeTest
64public class NetworkStatsServiceTest extends AndroidTestCase {
65    private static final String TAG = "NetworkStatsServiceTest";
66
67    private static final String TEST_IFACE = "test0";
68    private static final long TEST_START = 1194220800000L;
69
70    private static NetworkTemplate sTemplateWifi = new NetworkTemplate(MATCH_WIFI, null);
71
72    private static final int TEST_UID_1 = 1001;
73    private static final int TEST_UID_2 = 1002;
74
75    private BroadcastInterceptingContext mServiceContext;
76    private File mStatsDir;
77
78    private INetworkManagementService mNetManager;
79    private IAlarmManager mAlarmManager;
80    private TrustedTime mTime;
81    private NetworkStatsSettings mSettings;
82    private IConnectivityManager mConnManager;
83
84    private NetworkStatsService mService;
85
86    @Override
87    public void setUp() throws Exception {
88        super.setUp();
89
90        mServiceContext = new BroadcastInterceptingContext(getContext());
91        mStatsDir = getContext().getFilesDir();
92
93        mNetManager = createMock(INetworkManagementService.class);
94        mAlarmManager = createMock(IAlarmManager.class);
95        mTime = createMock(TrustedTime.class);
96        mSettings = createMock(NetworkStatsSettings.class);
97        mConnManager = createMock(IConnectivityManager.class);
98
99        mService = new NetworkStatsService(
100                mServiceContext, mNetManager, mAlarmManager, mTime, mStatsDir, mSettings);
101        mService.bindConnectivityManager(mConnManager);
102
103        expectDefaultSettings();
104        expectSystemReady();
105
106        replay();
107        mService.systemReady();
108        verifyAndReset();
109
110    }
111
112    @Override
113    public void tearDown() throws Exception {
114        for (File file : mStatsDir.listFiles()) {
115            file.delete();
116        }
117
118        mServiceContext = null;
119        mStatsDir = null;
120
121        mNetManager = null;
122        mAlarmManager = null;
123        mTime = null;
124
125        mService = null;
126
127        super.tearDown();
128    }
129
130    public void testSummaryStatsWifi() throws Exception {
131        long elapsedRealtime = 0;
132
133        // pretend that wifi network comes online; service should ask about full
134        // network state, and poll any existing interfaces before updating.
135        expectTime(TEST_START + elapsedRealtime);
136        expectDefaultSettings();
137        expectNetworkState(buildWifiState());
138        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
139
140        replay();
141        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
142
143        // verify service has empty history for wifi
144        assertNetworkTotal(sTemplateWifi, 0L, 0L);
145        verifyAndReset();
146
147        // modify some number on wifi, and trigger poll event
148        elapsedRealtime += HOUR_IN_MILLIS;
149        expectTime(TEST_START + elapsedRealtime);
150        expectDefaultSettings();
151        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
152                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 2048L));
153        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
154
155        replay();
156        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
157
158        // verify service recorded history
159        assertNetworkTotal(sTemplateWifi, 1024L, 2048L);
160        verifyAndReset();
161
162        // and bump forward again, with counters going higher. this is
163        // important, since polling should correctly subtract last snapshot.
164        elapsedRealtime += DAY_IN_MILLIS;
165        expectTime(TEST_START + elapsedRealtime);
166        expectDefaultSettings();
167        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
168                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 8192L));
169        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
170
171        replay();
172        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
173
174        // verify service recorded history
175        assertNetworkTotal(sTemplateWifi, 4096L, 8192L);
176        verifyAndReset();
177
178    }
179
180    public void testStatsRebootPersist() throws Exception {
181        long elapsedRealtime = 0;
182        assertStatsFilesExist(false);
183
184        // pretend that wifi network comes online; service should ask about full
185        // network state, and poll any existing interfaces before updating.
186        expectTime(TEST_START + elapsedRealtime);
187        expectDefaultSettings();
188        expectNetworkState(buildWifiState());
189        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
190
191        replay();
192        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
193
194        // verify service has empty history for wifi
195        assertNetworkTotal(sTemplateWifi, 0L, 0L);
196        verifyAndReset();
197
198        // modify some number on wifi, and trigger poll event
199        elapsedRealtime += HOUR_IN_MILLIS;
200        expectTime(TEST_START + elapsedRealtime);
201        expectDefaultSettings();
202        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
203                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 2048L));
204        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 2)
205                .addEntry(TEST_IFACE, TEST_UID_1, TAG_NONE, 512L, 256L)
206                .addEntry(TEST_IFACE, TEST_UID_2, TAG_NONE, 128L, 128L));
207
208        replay();
209        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
210
211        // verify service recorded history
212        assertNetworkTotal(sTemplateWifi, 1024L, 2048L);
213        assertUidTotal(sTemplateWifi, TEST_UID_1, 512L, 256L);
214        assertUidTotal(sTemplateWifi, TEST_UID_2, 128L, 128L);
215        verifyAndReset();
216
217        // graceful shutdown system, which should trigger persist of stats, and
218        // clear any values in memory.
219        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SHUTDOWN));
220
221        // talk with zombie service to assert stats have gone; and assert that
222        // we persisted them to file.
223        expectDefaultSettings();
224        replay();
225        assertNetworkTotal(sTemplateWifi, 0L, 0L);
226        verifyAndReset();
227
228        assertStatsFilesExist(true);
229
230        // boot through serviceReady() again
231        expectDefaultSettings();
232        expectSystemReady();
233
234        replay();
235        mService.systemReady();
236
237        // after systemReady(), we should have historical stats loaded again
238        assertNetworkTotal(sTemplateWifi, 1024L, 2048L);
239        assertUidTotal(sTemplateWifi, TEST_UID_1, 512L, 256L);
240        assertUidTotal(sTemplateWifi, TEST_UID_2, 128L, 128L);
241        verifyAndReset();
242
243    }
244
245    public void testStatsBucketResize() throws Exception {
246        long elapsedRealtime = 0;
247        NetworkStatsHistory history = null;
248        long[] total = null;
249
250        assertStatsFilesExist(false);
251
252        // pretend that wifi network comes online; service should ask about full
253        // network state, and poll any existing interfaces before updating.
254        expectTime(TEST_START + elapsedRealtime);
255        expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
256        expectNetworkState(buildWifiState());
257        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
258
259        replay();
260        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
261        verifyAndReset();
262
263        // modify some number on wifi, and trigger poll event
264        elapsedRealtime += 2 * HOUR_IN_MILLIS;
265        expectTime(TEST_START + elapsedRealtime);
266        expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
267        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
268                .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 512L));
269        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
270
271        replay();
272        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
273
274        // verify service recorded history
275        history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
276        total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
277        assertEquals(512L, total[0]);
278        assertEquals(512L, total[1]);
279        assertEquals(HOUR_IN_MILLIS, history.bucketDuration);
280        assertEquals(2, history.bucketCount);
281        verifyAndReset();
282
283        // now change bucket duration setting and trigger another poll with
284        // exact same values, which should resize existing buckets.
285        expectTime(TEST_START + elapsedRealtime);
286        expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS);
287        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
288        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
289
290        replay();
291        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
292
293        // verify identical stats, but spread across 4 buckets now
294        history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
295        total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
296        assertEquals(512L, total[0]);
297        assertEquals(512L, total[1]);
298        assertEquals(30 * MINUTE_IN_MILLIS, history.bucketDuration);
299        assertEquals(4, history.bucketCount);
300        verifyAndReset();
301
302    }
303
304    private void assertNetworkTotal(NetworkTemplate template, long rx, long tx) {
305        final NetworkStatsHistory history = mService.getHistoryForNetwork(template);
306        final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
307        assertEquals(rx, total[0]);
308        assertEquals(tx, total[1]);
309    }
310
311    private void assertUidTotal(NetworkTemplate template, int uid, long rx, long tx) {
312        final NetworkStatsHistory history = mService.getHistoryForUid(template, uid);
313        final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
314        assertEquals(rx, total[0]);
315        assertEquals(tx, total[1]);
316    }
317
318    private void expectSystemReady() throws Exception {
319        mAlarmManager.remove(isA(PendingIntent.class));
320        expectLastCall().anyTimes();
321
322        mAlarmManager.setInexactRepeating(
323                eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), isA(PendingIntent.class));
324        expectLastCall().atLeastOnce();
325    }
326
327    private void expectNetworkState(NetworkState... state) throws Exception {
328        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
329    }
330
331    private void expectNetworkStatsSummary(NetworkStats summary) throws Exception {
332        expect(mNetManager.getNetworkStatsSummary()).andReturn(summary).atLeastOnce();
333    }
334
335    private void expectNetworkStatsDetail(NetworkStats detail) throws Exception {
336        expect(mNetManager.getNetworkStatsDetail()).andReturn(detail).atLeastOnce();
337    }
338
339    private void expectDefaultSettings() throws Exception {
340        expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
341    }
342
343    private void expectSettings(long persistThreshold, long bucketDuration, long maxHistory)
344            throws Exception {
345        expect(mSettings.getPollInterval()).andReturn(HOUR_IN_MILLIS).anyTimes();
346        expect(mSettings.getPersistThreshold()).andReturn(persistThreshold).anyTimes();
347        expect(mSettings.getNetworkBucketDuration()).andReturn(bucketDuration).anyTimes();
348        expect(mSettings.getNetworkMaxHistory()).andReturn(maxHistory).anyTimes();
349        expect(mSettings.getUidBucketDuration()).andReturn(bucketDuration).anyTimes();
350        expect(mSettings.getUidMaxHistory()).andReturn(maxHistory).anyTimes();
351        expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes();
352    }
353
354    private void expectTime(long currentTime) throws Exception {
355        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
356        expect(mTime.hasCache()).andReturn(true).anyTimes();
357        expect(mTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
358        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
359        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
360    }
361
362    private void assertStatsFilesExist(boolean exist) {
363        final File summaryFile = new File(mStatsDir, "netstats.bin");
364        final File detailFile = new File(mStatsDir, "netstats_uid.bin");
365        if (exist) {
366            assertTrue(summaryFile.exists());
367            assertTrue(detailFile.exists());
368        } else {
369            assertFalse(summaryFile.exists());
370            assertFalse(detailFile.exists());
371        }
372    }
373
374    private static NetworkState buildWifiState() {
375        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
376        info.setDetailedState(DetailedState.CONNECTED, null, null);
377        final LinkProperties prop = new LinkProperties();
378        prop.setInterfaceName(TEST_IFACE);
379        return new NetworkState(info, prop, null);
380    }
381
382    private static NetworkStats buildEmptyStats(long elapsedRealtime) {
383        return new NetworkStats(elapsedRealtime, 0);
384    }
385
386    private void replay() {
387        EasyMock.replay(mNetManager, mAlarmManager, mTime, mSettings, mConnManager);
388    }
389
390    private void verifyAndReset() {
391        EasyMock.verify(mNetManager, mAlarmManager, mTime, mSettings, mConnManager);
392        EasyMock.reset(mNetManager, mAlarmManager, mTime, mSettings, mConnManager);
393    }
394}
395