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