NetworkStatsServiceTest.java revision 434962e44ea93b1c4d216c55f636a435bf54aa54
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.content.Intent.ACTION_UID_REMOVED;
20import static android.content.Intent.EXTRA_UID;
21import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
22import static android.net.ConnectivityManager.TYPE_MOBILE;
23import static android.net.ConnectivityManager.TYPE_WIFI;
24import static android.net.ConnectivityManager.TYPE_WIMAX;
25import static android.net.NetworkStats.IFACE_ALL;
26import static android.net.NetworkStats.TAG_NONE;
27import static android.net.NetworkStats.UID_ALL;
28import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
29import static android.net.NetworkTemplate.MATCH_WIFI;
30import static android.net.TrafficStats.UID_REMOVED;
31import static android.text.format.DateUtils.DAY_IN_MILLIS;
32import static android.text.format.DateUtils.HOUR_IN_MILLIS;
33import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
34import static android.text.format.DateUtils.WEEK_IN_MILLIS;
35import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
36import static com.android.server.net.NetworkStatsService.packUidAndTag;
37import static com.android.server.net.NetworkStatsService.unpackTag;
38import static com.android.server.net.NetworkStatsService.unpackUid;
39import static org.easymock.EasyMock.anyLong;
40import static org.easymock.EasyMock.createMock;
41import static org.easymock.EasyMock.eq;
42import static org.easymock.EasyMock.expect;
43import static org.easymock.EasyMock.expectLastCall;
44import static org.easymock.EasyMock.isA;
45
46import android.app.AlarmManager;
47import android.app.IAlarmManager;
48import android.app.PendingIntent;
49import android.content.Intent;
50import android.net.IConnectivityManager;
51import android.net.LinkProperties;
52import android.net.NetworkInfo;
53import android.net.NetworkInfo.DetailedState;
54import android.net.NetworkState;
55import android.net.NetworkStats;
56import android.net.NetworkStatsHistory;
57import android.net.NetworkTemplate;
58import android.os.INetworkManagementService;
59import android.telephony.TelephonyManager;
60import android.test.AndroidTestCase;
61import android.test.suitebuilder.annotation.LargeTest;
62import android.util.TrustedTime;
63
64import com.android.server.net.NetworkStatsService;
65import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
66
67import org.easymock.EasyMock;
68
69import java.io.File;
70
71/**
72 * Tests for {@link NetworkStatsService}.
73 */
74@LargeTest
75public class NetworkStatsServiceTest extends AndroidTestCase {
76    private static final String TAG = "NetworkStatsServiceTest";
77
78    private static final String TEST_IFACE = "test0";
79    private static final long TEST_START = 1194220800000L;
80
81    private static final String IMSI_1 = "310004";
82    private static final String IMSI_2 = "310260";
83
84    private static NetworkTemplate sTemplateWifi = new NetworkTemplate(MATCH_WIFI, null);
85    private static NetworkTemplate sTemplateImsi1 = new NetworkTemplate(MATCH_MOBILE_ALL, IMSI_1);
86    private static NetworkTemplate sTemplateImsi2 = new NetworkTemplate(MATCH_MOBILE_ALL, IMSI_2);
87
88    private static final int UID_RED = 1001;
89    private static final int UID_BLUE = 1002;
90    private static final int UID_GREEN = 1003;
91
92    private BroadcastInterceptingContext mServiceContext;
93    private File mStatsDir;
94
95    private INetworkManagementService mNetManager;
96    private IAlarmManager mAlarmManager;
97    private TrustedTime mTime;
98    private NetworkStatsSettings mSettings;
99    private IConnectivityManager mConnManager;
100
101    private NetworkStatsService mService;
102
103    @Override
104    public void setUp() throws Exception {
105        super.setUp();
106
107        mServiceContext = new BroadcastInterceptingContext(getContext());
108        mStatsDir = getContext().getFilesDir();
109
110        mNetManager = createMock(INetworkManagementService.class);
111        mAlarmManager = createMock(IAlarmManager.class);
112        mTime = createMock(TrustedTime.class);
113        mSettings = createMock(NetworkStatsSettings.class);
114        mConnManager = createMock(IConnectivityManager.class);
115
116        mService = new NetworkStatsService(
117                mServiceContext, mNetManager, mAlarmManager, mTime, mStatsDir, mSettings);
118        mService.bindConnectivityManager(mConnManager);
119
120        expectDefaultSettings();
121        expectSystemReady();
122
123        replay();
124        mService.systemReady();
125        verifyAndReset();
126
127    }
128
129    @Override
130    public void tearDown() throws Exception {
131        for (File file : mStatsDir.listFiles()) {
132            file.delete();
133        }
134
135        mServiceContext = null;
136        mStatsDir = null;
137
138        mNetManager = null;
139        mAlarmManager = null;
140        mTime = null;
141        mSettings = null;
142        mConnManager = null;
143
144        mService = null;
145
146        super.tearDown();
147    }
148
149    public void testNetworkStatsWifi() throws Exception {
150        long elapsedRealtime = 0;
151
152        // pretend that wifi network comes online; service should ask about full
153        // network state, and poll any existing interfaces before updating.
154        expectTime(TEST_START + elapsedRealtime);
155        expectDefaultSettings();
156        expectNetworkState(buildWifiState());
157        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
158
159        replay();
160        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
161
162        // verify service has empty history for wifi
163        assertNetworkTotal(sTemplateWifi, 0L, 0L);
164        verifyAndReset();
165
166        // modify some number on wifi, and trigger poll event
167        elapsedRealtime += HOUR_IN_MILLIS;
168        expectTime(TEST_START + elapsedRealtime);
169        expectDefaultSettings();
170        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
171                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 1L, 2048L, 2L));
172        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
173
174        replay();
175        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
176
177        // verify service recorded history
178        assertNetworkTotal(sTemplateWifi, 1024L, 2048L);
179        verifyAndReset();
180
181        // and bump forward again, with counters going higher. this is
182        // important, since polling should correctly subtract last snapshot.
183        elapsedRealtime += DAY_IN_MILLIS;
184        expectTime(TEST_START + elapsedRealtime);
185        expectDefaultSettings();
186        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
187                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 4L, 8192L, 8L));
188        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
189
190        replay();
191        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
192
193        // verify service recorded history
194        assertNetworkTotal(sTemplateWifi, 4096L, 8192L);
195        verifyAndReset();
196
197    }
198
199    public void testStatsRebootPersist() throws Exception {
200        long elapsedRealtime = 0;
201        assertStatsFilesExist(false);
202
203        // pretend that wifi network comes online; service should ask about full
204        // network state, and poll any existing interfaces before updating.
205        expectTime(TEST_START + elapsedRealtime);
206        expectDefaultSettings();
207        expectNetworkState(buildWifiState());
208        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
209
210        replay();
211        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
212
213        // verify service has empty history for wifi
214        assertNetworkTotal(sTemplateWifi, 0L, 0L);
215        verifyAndReset();
216
217        // modify some number on wifi, and trigger poll event
218        elapsedRealtime += HOUR_IN_MILLIS;
219        expectTime(TEST_START + elapsedRealtime);
220        expectDefaultSettings();
221        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
222                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 8L, 2048L, 16L));
223        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 2)
224                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L)
225                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 128L, 1L));
226
227        replay();
228        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
229
230        // verify service recorded history
231        assertNetworkTotal(sTemplateWifi, 1024L, 2048L);
232        assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L);
233        assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L);
234        verifyAndReset();
235
236        // graceful shutdown system, which should trigger persist of stats, and
237        // clear any values in memory.
238        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SHUTDOWN));
239
240        // talk with zombie service to assert stats have gone; and assert that
241        // we persisted them to file.
242        expectDefaultSettings();
243        replay();
244        assertNetworkTotal(sTemplateWifi, 0L, 0L);
245        verifyAndReset();
246
247        assertStatsFilesExist(true);
248
249        // boot through serviceReady() again
250        expectDefaultSettings();
251        expectSystemReady();
252
253        replay();
254        mService.systemReady();
255
256        // after systemReady(), we should have historical stats loaded again
257        assertNetworkTotal(sTemplateWifi, 1024L, 2048L);
258        assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L);
259        assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L);
260        verifyAndReset();
261
262    }
263
264    public void testStatsBucketResize() throws Exception {
265        long elapsedRealtime = 0;
266        NetworkStatsHistory history = null;
267
268        assertStatsFilesExist(false);
269
270        // pretend that wifi network comes online; service should ask about full
271        // network state, and poll any existing interfaces before updating.
272        expectTime(TEST_START + elapsedRealtime);
273        expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
274        expectNetworkState(buildWifiState());
275        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
276
277        replay();
278        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
279        verifyAndReset();
280
281        // modify some number on wifi, and trigger poll event
282        elapsedRealtime += 2 * HOUR_IN_MILLIS;
283        expectTime(TEST_START + elapsedRealtime);
284        expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
285        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
286                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 4L, 512L, 4L));
287        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
288
289        replay();
290        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
291
292        // verify service recorded history
293        history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
294        assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L);
295        assertEquals(HOUR_IN_MILLIS, history.getBucketDuration());
296        assertEquals(2, history.size());
297        verifyAndReset();
298
299        // now change bucket duration setting and trigger another poll with
300        // exact same values, which should resize existing buckets.
301        expectTime(TEST_START + elapsedRealtime);
302        expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS);
303        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
304        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
305
306        replay();
307        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
308
309        // verify identical stats, but spread across 4 buckets now
310        history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
311        assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L);
312        assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
313        assertEquals(4, history.size());
314        verifyAndReset();
315
316    }
317
318    public void testUidStatsAcrossNetworks() throws Exception {
319        long elapsedRealtime = 0;
320
321        // pretend first mobile network comes online
322        expectTime(TEST_START + elapsedRealtime);
323        expectDefaultSettings();
324        expectNetworkState(buildMobile3gState(IMSI_1));
325        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
326
327        replay();
328        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
329        verifyAndReset();
330
331        // create some traffic on first network
332        elapsedRealtime += HOUR_IN_MILLIS;
333        expectTime(TEST_START + elapsedRealtime);
334        expectDefaultSettings();
335        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
336                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 16L, 512L, 4L));
337        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 3)
338                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 12L, 512L, 4L)
339                .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L)
340                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 4L, 0L, 0L));
341
342        replay();
343        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
344
345        // verify service recorded history
346        assertNetworkTotal(sTemplateImsi1, 2048L, 512L);
347        assertNetworkTotal(sTemplateWifi, 0L, 0L);
348        assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L);
349        assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L);
350        verifyAndReset();
351
352        // now switch networks; this also tests that we're okay with interfaces
353        // disappearing, to verify we don't count backwards.
354        elapsedRealtime += HOUR_IN_MILLIS;
355        expectTime(TEST_START + elapsedRealtime);
356        expectDefaultSettings();
357        expectNetworkState(buildMobile3gState(IMSI_2));
358        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
359        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
360
361        replay();
362        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
363        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
364        verifyAndReset();
365
366        // create traffic on second network
367        elapsedRealtime += HOUR_IN_MILLIS;
368        expectTime(TEST_START + elapsedRealtime);
369        expectDefaultSettings();
370        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
371                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1L, 1024L, 8L));
372        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
373                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 1024L, 8L));
374
375        replay();
376        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
377
378        // verify original history still intact
379        assertNetworkTotal(sTemplateImsi1, 2048L, 512L);
380        assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L);
381        assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L);
382
383        // and verify new history also recorded under different template, which
384        // verifies that we didn't cross the streams.
385        assertNetworkTotal(sTemplateImsi2, 128L, 1024L);
386        assertNetworkTotal(sTemplateWifi, 0L, 0L);
387        assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1024L);
388        verifyAndReset();
389
390    }
391
392    public void testUidRemovedIsMoved() throws Exception {
393        long elapsedRealtime = 0;
394
395        // pretend that network comes online
396        expectTime(TEST_START + elapsedRealtime);
397        expectDefaultSettings();
398        expectNetworkState(buildWifiState());
399        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
400
401        replay();
402        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
403        verifyAndReset();
404
405        // create some traffic
406        elapsedRealtime += HOUR_IN_MILLIS;
407        expectTime(TEST_START + elapsedRealtime);
408        expectDefaultSettings();
409        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
410                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 258L, 544L, 34L));
411        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
412                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 16L, 1L, 16L, 1L)
413                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 258L, 512L, 32L)
414                .addValues(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 1L, 16L, 1L));
415
416        replay();
417        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
418
419        // verify service recorded history
420        assertNetworkTotal(sTemplateWifi, 4128L, 544L);
421        assertUidTotal(sTemplateWifi, UID_RED, 16L, 16L);
422        assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 512L);
423        assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L);
424        verifyAndReset();
425
426        // now pretend two UIDs are uninstalled, which should migrate stats to
427        // special "removed" bucket.
428        expectDefaultSettings();
429        replay();
430        final Intent intent = new Intent(ACTION_UID_REMOVED);
431        intent.putExtra(EXTRA_UID, UID_BLUE);
432        mServiceContext.sendBroadcast(intent);
433        intent.putExtra(EXTRA_UID, UID_RED);
434        mServiceContext.sendBroadcast(intent);
435
436        // existing uid and total should remain unchanged; but removed UID
437        // should be gone completely.
438        assertNetworkTotal(sTemplateWifi, 4128L, 544L);
439        assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L);
440        assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L);
441        assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L);
442        assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 528L);
443        verifyAndReset();
444
445    }
446
447    public void testUid3g4gCombinedByTemplate() throws Exception {
448        long elapsedRealtime = 0;
449
450        // pretend that network comes online
451        expectTime(TEST_START + elapsedRealtime);
452        expectDefaultSettings();
453        expectNetworkState(buildMobile3gState(IMSI_1));
454        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
455
456        replay();
457        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
458        verifyAndReset();
459
460        // create some traffic
461        elapsedRealtime += HOUR_IN_MILLIS;
462        expectTime(TEST_START + elapsedRealtime);
463        expectDefaultSettings();
464        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
465        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
466                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 8L, 1024L, 8L)
467                .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L));
468
469        replay();
470        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
471
472        // verify service recorded history
473        assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 1024L);
474        verifyAndReset();
475
476        // now switch over to 4g network
477        elapsedRealtime += HOUR_IN_MILLIS;
478        expectTime(TEST_START + elapsedRealtime);
479        expectDefaultSettings();
480        expectNetworkState(buildMobile4gState());
481        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
482        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
483
484        replay();
485        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
486        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
487        verifyAndReset();
488
489        // create traffic on second network
490        elapsedRealtime += HOUR_IN_MILLIS;
491        expectTime(TEST_START + elapsedRealtime);
492        expectDefaultSettings();
493        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
494        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
495                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L));
496
497        replay();
498        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
499
500        // verify that ALL_MOBILE template combines both
501        assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 1280L);
502
503        verifyAndReset();
504
505    }
506
507    public void testPackedUidAndTag() throws Exception {
508        assertEquals(0x0000000000000000L, packUidAndTag(0, 0x0));
509        assertEquals(0x000003E900000000L, packUidAndTag(1001, 0x0));
510        assertEquals(0x000003E90000F00DL, packUidAndTag(1001, 0xF00D));
511
512        long packed;
513        packed = packUidAndTag(Integer.MAX_VALUE, Integer.MIN_VALUE);
514        assertEquals(Integer.MAX_VALUE, unpackUid(packed));
515        assertEquals(Integer.MIN_VALUE, unpackTag(packed));
516
517        packed = packUidAndTag(Integer.MIN_VALUE, Integer.MAX_VALUE);
518        assertEquals(Integer.MIN_VALUE, unpackUid(packed));
519        assertEquals(Integer.MAX_VALUE, unpackTag(packed));
520
521        packed = packUidAndTag(10005, 0xFFFFFFFF);
522        assertEquals(10005, unpackUid(packed));
523        assertEquals(0xFFFFFFFF, unpackTag(packed));
524
525    }
526
527    public void testSummaryForAllUid() throws Exception {
528        long elapsedRealtime = 0;
529
530        // pretend that network comes online
531        expectTime(TEST_START + elapsedRealtime);
532        expectDefaultSettings();
533        expectNetworkState(buildWifiState());
534        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
535
536        replay();
537        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
538        verifyAndReset();
539
540        // create some traffic for two apps
541        elapsedRealtime += HOUR_IN_MILLIS;
542        expectTime(TEST_START + elapsedRealtime);
543        expectDefaultSettings();
544        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
545        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
546                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L)
547                .addValues(TEST_IFACE, UID_RED, 0xF00D, 10L, 1L, 10L, 1L)
548                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L));
549
550        replay();
551        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
552
553        // verify service recorded history
554        assertUidTotal(sTemplateWifi, UID_RED, 50L, 50L);
555        assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 512L);
556        verifyAndReset();
557
558        // now create more traffic in next hour, but only for one app
559        elapsedRealtime += HOUR_IN_MILLIS;
560        expectTime(TEST_START + elapsedRealtime);
561        expectDefaultSettings();
562        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
563        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
564                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L));
565
566        replay();
567        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
568
569        // first verify entire history present
570        NetworkStats stats = mService.getSummaryForAllUid(
571                sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
572        assertEquals(3, stats.size());
573        assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L);
574        assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L);
575        assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L);
576
577        // now verify that recent history only contains one uid
578        final long currentTime = TEST_START + elapsedRealtime;
579        stats = mService.getSummaryForAllUid(
580                sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
581        assertEquals(1, stats.size());
582        assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L);
583
584        verifyAndReset();
585    }
586
587    private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long txBytes) {
588        final NetworkStatsHistory history = mService.getHistoryForNetwork(template);
589        assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes);
590    }
591
592    private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long txBytes) {
593        final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE);
594        assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes);
595    }
596
597    private void expectSystemReady() throws Exception {
598        mAlarmManager.remove(isA(PendingIntent.class));
599        expectLastCall().anyTimes();
600
601        mAlarmManager.setInexactRepeating(
602                eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), isA(PendingIntent.class));
603        expectLastCall().atLeastOnce();
604    }
605
606    private void expectNetworkState(NetworkState... state) throws Exception {
607        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
608    }
609
610    private void expectNetworkStatsSummary(NetworkStats summary) throws Exception {
611        expect(mNetManager.getNetworkStatsSummary()).andReturn(summary).atLeastOnce();
612    }
613
614    private void expectNetworkStatsDetail(NetworkStats detail) throws Exception {
615        expect(mNetManager.getNetworkStatsDetail()).andReturn(detail).atLeastOnce();
616    }
617
618    private void expectDefaultSettings() throws Exception {
619        expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
620    }
621
622    private void expectSettings(long persistThreshold, long bucketDuration, long maxHistory)
623            throws Exception {
624        expect(mSettings.getPollInterval()).andReturn(HOUR_IN_MILLIS).anyTimes();
625        expect(mSettings.getPersistThreshold()).andReturn(persistThreshold).anyTimes();
626        expect(mSettings.getNetworkBucketDuration()).andReturn(bucketDuration).anyTimes();
627        expect(mSettings.getNetworkMaxHistory()).andReturn(maxHistory).anyTimes();
628        expect(mSettings.getUidBucketDuration()).andReturn(bucketDuration).anyTimes();
629        expect(mSettings.getUidMaxHistory()).andReturn(maxHistory).anyTimes();
630        expect(mSettings.getTagMaxHistory()).andReturn(maxHistory).anyTimes();
631        expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes();
632    }
633
634    private void expectTime(long currentTime) throws Exception {
635        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
636        expect(mTime.hasCache()).andReturn(true).anyTimes();
637        expect(mTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
638        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
639        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
640    }
641
642    private void assertStatsFilesExist(boolean exist) {
643        final File networkFile = new File(mStatsDir, "netstats.bin");
644        final File uidFile = new File(mStatsDir, "netstats_uid.bin");
645        if (exist) {
646            assertTrue(networkFile.exists());
647            assertTrue(uidFile.exists());
648        } else {
649            assertFalse(networkFile.exists());
650            assertFalse(uidFile.exists());
651        }
652    }
653
654    private static void assertValues(NetworkStats stats, int i, String iface, int uid, int tag,
655            long rxBytes, long rxPackets, long txBytes, long txPackets) {
656        final NetworkStats.Entry entry = stats.getValues(i, null);
657        assertEquals(iface, entry.iface);
658        assertEquals(uid, entry.uid);
659        assertEquals(tag, entry.tag);
660        assertEquals(rxBytes, entry.rxBytes);
661        // TODO: enable testing packet counts once stored in history
662//        assertEquals(rxPackets, entry.rxPackets);
663        assertEquals(txBytes, entry.txBytes);
664//        assertEquals(txPackets, entry.txPackets);
665    }
666
667    private static void assertValues(
668            NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) {
669        final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
670        assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
671        assertEquals("unexpected txBytes", txBytes, entry.txBytes);
672    }
673
674    private static NetworkState buildWifiState() {
675        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
676        info.setDetailedState(DetailedState.CONNECTED, null, null);
677        final LinkProperties prop = new LinkProperties();
678        prop.setInterfaceName(TEST_IFACE);
679        return new NetworkState(info, prop, null);
680    }
681
682    private static NetworkState buildMobile3gState(String subscriberId) {
683        final NetworkInfo info = new NetworkInfo(
684                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UMTS, null, null);
685        info.setDetailedState(DetailedState.CONNECTED, null, null);
686        final LinkProperties prop = new LinkProperties();
687        prop.setInterfaceName(TEST_IFACE);
688        return new NetworkState(info, prop, null, subscriberId);
689    }
690
691    private static NetworkState buildMobile4gState() {
692        final NetworkInfo info = new NetworkInfo(TYPE_WIMAX, 0, null, null);
693        info.setDetailedState(DetailedState.CONNECTED, null, null);
694        final LinkProperties prop = new LinkProperties();
695        prop.setInterfaceName(TEST_IFACE);
696        return new NetworkState(info, prop, null);
697    }
698
699    private static NetworkStats buildEmptyStats(long elapsedRealtime) {
700        return new NetworkStats(elapsedRealtime, 0);
701    }
702
703    private void replay() {
704        EasyMock.replay(mNetManager, mAlarmManager, mTime, mSettings, mConnManager);
705    }
706
707    private void verifyAndReset() {
708        EasyMock.verify(mNetManager, mAlarmManager, mTime, mSettings, mConnManager);
709        EasyMock.reset(mNetManager, mAlarmManager, mTime, mSettings, mConnManager);
710    }
711}
712