NetworkStatsServiceTest.java revision d37948f6ed1667d077e0e3a38808f42f981ddcc2
1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/*
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Copyright (C) 2011 The Android Open Source Project
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
5a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch * you may not use this file except in compliance with the License.
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * You may obtain a copy of the License at
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Unless required by applicable law or agreed to in writing, software
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * distributed under the License is distributed on an "AS IS" BASIS,
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * See the License for the specific language governing permissions and
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * limitations under the License.
15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch */
16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)package com.android.server;
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.content.Intent.ACTION_UID_REMOVED;
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.content.Intent.EXTRA_UID;
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.net.ConnectivityManager.TYPE_MOBILE;
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import static android.net.ConnectivityManager.TYPE_WIFI;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.net.ConnectivityManager.TYPE_WIMAX;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.net.NetworkStats.IFACE_ALL;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.net.NetworkStats.TAG_NONE;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.net.NetworkStats.UID_ALL;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.net.NetworkTemplate.MATCH_WIFI;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.net.TrafficStats.UID_REMOVED;
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.text.format.DateUtils.DAY_IN_MILLIS;
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.text.format.DateUtils.HOUR_IN_MILLIS;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static android.text.format.DateUtils.WEEK_IN_MILLIS;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static com.android.server.net.NetworkStatsService.packUidAndTag;
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import static com.android.server.net.NetworkStatsService.unpackTag;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static com.android.server.net.NetworkStatsService.unpackUid;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static org.easymock.EasyMock.anyLong;
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static org.easymock.EasyMock.createMock;
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static org.easymock.EasyMock.eq;
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static org.easymock.EasyMock.expect;
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static org.easymock.EasyMock.expectLastCall;
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import static org.easymock.EasyMock.isA;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import android.app.AlarmManager;
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.app.IAlarmManager;
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.app.PendingIntent;
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.content.Intent;
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.net.IConnectivityManager;
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.net.LinkProperties;
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.net.NetworkInfo;
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import android.net.NetworkInfo.DetailedState;
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.net.NetworkState;
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.net.NetworkStats;
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.net.NetworkStatsHistory;
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.net.NetworkTemplate;
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.os.INetworkManagementService;
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.telephony.TelephonyManager;
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.test.AndroidTestCase;
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.test.suitebuilder.annotation.LargeTest;
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import android.util.TrustedTime;
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import com.android.server.net.NetworkStatsService;
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import org.easymock.EasyMock;
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import java.io.File;
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Tests for {@link NetworkStatsService}.
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)@LargeTest
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public class NetworkStatsServiceTest extends AndroidTestCase {
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static final String TAG = "NetworkStatsServiceTest";
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    private static final String TEST_IFACE = "test0";
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static final long TEST_START = 1194220800000L;
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static final String IMSI_1 = "310004";
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static final String IMSI_2 = "310260";
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static NetworkTemplate sTemplateWifi = new NetworkTemplate(MATCH_WIFI, null);
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static NetworkTemplate sTemplateImsi1 = new NetworkTemplate(MATCH_MOBILE_ALL, IMSI_1);
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static NetworkTemplate sTemplateImsi2 = new NetworkTemplate(MATCH_MOBILE_ALL, IMSI_2);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private static final int UID_RED = 1001;
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    private static final int UID_BLUE = 1002;
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    private static final int UID_GREEN = 1003;
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private BroadcastInterceptingContext mServiceContext;
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private File mStatsDir;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private INetworkManagementService mNetManager;
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private IAlarmManager mAlarmManager;
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private TrustedTime mTime;
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    private NetworkStatsSettings mSettings;
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private IConnectivityManager mConnManager;
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    private NetworkStatsService mService;
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    @Override
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    public void setUp() throws Exception {
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        super.setUp();
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mServiceContext = new BroadcastInterceptingContext(getContext());
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mStatsDir = getContext().getFilesDir();
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mNetManager = createMock(INetworkManagementService.class);
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mAlarmManager = createMock(IAlarmManager.class);
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mTime = createMock(TrustedTime.class);
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mSettings = createMock(NetworkStatsSettings.class);
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mConnManager = createMock(IConnectivityManager.class);
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        mService = new NetworkStatsService(
117a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                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        long[] total = null;
268
269        assertStatsFilesExist(false);
270
271        // pretend that wifi network comes online; service should ask about full
272        // network state, and poll any existing interfaces before updating.
273        expectTime(TEST_START + elapsedRealtime);
274        expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
275        expectNetworkState(buildWifiState());
276        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
277
278        replay();
279        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
280        verifyAndReset();
281
282        // modify some number on wifi, and trigger poll event
283        elapsedRealtime += 2 * HOUR_IN_MILLIS;
284        expectTime(TEST_START + elapsedRealtime);
285        expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
286        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
287                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 4L, 512L, 4L));
288        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
289
290        replay();
291        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
292
293        // verify service recorded history
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(HOUR_IN_MILLIS, history.getBucketDuration());
299        assertEquals(2, history.size());
300        verifyAndReset();
301
302        // now change bucket duration setting and trigger another poll with
303        // exact same values, which should resize existing buckets.
304        expectTime(TEST_START + elapsedRealtime);
305        expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS);
306        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
307        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
308
309        replay();
310        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
311
312        // verify identical stats, but spread across 4 buckets now
313        history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
314        total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
315        assertEquals(512L, total[0]);
316        assertEquals(512L, total[1]);
317        assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
318        assertEquals(4, history.size());
319        verifyAndReset();
320
321    }
322
323    public void testUidStatsAcrossNetworks() throws Exception {
324        long elapsedRealtime = 0;
325
326        // pretend first mobile network comes online
327        expectTime(TEST_START + elapsedRealtime);
328        expectDefaultSettings();
329        expectNetworkState(buildMobile3gState(IMSI_1));
330        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
331
332        replay();
333        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
334        verifyAndReset();
335
336        // create some traffic on first network
337        elapsedRealtime += HOUR_IN_MILLIS;
338        expectTime(TEST_START + elapsedRealtime);
339        expectDefaultSettings();
340        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
341                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 16L, 512L, 4L));
342        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 3)
343                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 12L, 512L, 4L)
344                .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L)
345                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 4L, 0L, 0L));
346
347        replay();
348        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
349
350        // verify service recorded history
351        assertNetworkTotal(sTemplateImsi1, 2048L, 512L);
352        assertNetworkTotal(sTemplateWifi, 0L, 0L);
353        assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L);
354        assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L);
355        verifyAndReset();
356
357        // now switch networks; this also tests that we're okay with interfaces
358        // disappearing, to verify we don't count backwards.
359        elapsedRealtime += HOUR_IN_MILLIS;
360        expectTime(TEST_START + elapsedRealtime);
361        expectDefaultSettings();
362        expectNetworkState(buildMobile3gState(IMSI_2));
363        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
364        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
365
366        replay();
367        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
368        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
369        verifyAndReset();
370
371        // create traffic on second network
372        elapsedRealtime += HOUR_IN_MILLIS;
373        expectTime(TEST_START + elapsedRealtime);
374        expectDefaultSettings();
375        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
376                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1L, 1024L, 8L));
377        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
378                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 1024L, 8L));
379
380        replay();
381        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
382
383        // verify original history still intact
384        assertNetworkTotal(sTemplateImsi1, 2048L, 512L);
385        assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L);
386        assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L);
387
388        // and verify new history also recorded under different template, which
389        // verifies that we didn't cross the streams.
390        assertNetworkTotal(sTemplateImsi2, 128L, 1024L);
391        assertNetworkTotal(sTemplateWifi, 0L, 0L);
392        assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1024L);
393        verifyAndReset();
394
395    }
396
397    public void testUidRemovedIsMoved() throws Exception {
398        long elapsedRealtime = 0;
399
400        // pretend that network comes online
401        expectTime(TEST_START + elapsedRealtime);
402        expectDefaultSettings();
403        expectNetworkState(buildWifiState());
404        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
405
406        replay();
407        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
408        verifyAndReset();
409
410        // create some traffic
411        elapsedRealtime += HOUR_IN_MILLIS;
412        expectTime(TEST_START + elapsedRealtime);
413        expectDefaultSettings();
414        expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
415                .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 258L, 544L, 34L));
416        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
417                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 16L, 1L, 16L, 1L)
418                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 258L, 512L, 32L)
419                .addValues(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 1L, 16L, 1L));
420
421        replay();
422        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
423
424        // verify service recorded history
425        assertNetworkTotal(sTemplateWifi, 4128L, 544L);
426        assertUidTotal(sTemplateWifi, UID_RED, 16L, 16L);
427        assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 512L);
428        assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L);
429        verifyAndReset();
430
431        // now pretend two UIDs are uninstalled, which should migrate stats to
432        // special "removed" bucket.
433        expectDefaultSettings();
434        replay();
435        final Intent intent = new Intent(ACTION_UID_REMOVED);
436        intent.putExtra(EXTRA_UID, UID_BLUE);
437        mServiceContext.sendBroadcast(intent);
438        intent.putExtra(EXTRA_UID, UID_RED);
439        mServiceContext.sendBroadcast(intent);
440
441        // existing uid and total should remain unchanged; but removed UID
442        // should be gone completely.
443        assertNetworkTotal(sTemplateWifi, 4128L, 544L);
444        assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L);
445        assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L);
446        assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L);
447        assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 528L);
448        verifyAndReset();
449
450    }
451
452    public void testUid3g4gCombinedByTemplate() throws Exception {
453        long elapsedRealtime = 0;
454
455        // pretend that network comes online
456        expectTime(TEST_START + elapsedRealtime);
457        expectDefaultSettings();
458        expectNetworkState(buildMobile3gState(IMSI_1));
459        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
460
461        replay();
462        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
463        verifyAndReset();
464
465        // create some traffic
466        elapsedRealtime += HOUR_IN_MILLIS;
467        expectTime(TEST_START + elapsedRealtime);
468        expectDefaultSettings();
469        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
470        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
471                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 8L, 1024L, 8L)
472                .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L));
473
474        replay();
475        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
476
477        // verify service recorded history
478        assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 1024L);
479        verifyAndReset();
480
481        // now switch over to 4g network
482        elapsedRealtime += HOUR_IN_MILLIS;
483        expectTime(TEST_START + elapsedRealtime);
484        expectDefaultSettings();
485        expectNetworkState(buildMobile4gState());
486        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
487        expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
488
489        replay();
490        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
491        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
492        verifyAndReset();
493
494        // create traffic on second network
495        elapsedRealtime += HOUR_IN_MILLIS;
496        expectTime(TEST_START + elapsedRealtime);
497        expectDefaultSettings();
498        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
499        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
500                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L));
501
502        replay();
503        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
504
505        // verify that ALL_MOBILE template combines both
506        assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 1280L);
507
508        verifyAndReset();
509
510    }
511
512    public void testPackedUidAndTag() throws Exception {
513        assertEquals(0x0000000000000000L, packUidAndTag(0, 0x0));
514        assertEquals(0x000003E900000000L, packUidAndTag(1001, 0x0));
515        assertEquals(0x000003E90000F00DL, packUidAndTag(1001, 0xF00D));
516
517        long packed;
518        packed = packUidAndTag(Integer.MAX_VALUE, Integer.MIN_VALUE);
519        assertEquals(Integer.MAX_VALUE, unpackUid(packed));
520        assertEquals(Integer.MIN_VALUE, unpackTag(packed));
521
522        packed = packUidAndTag(Integer.MIN_VALUE, Integer.MAX_VALUE);
523        assertEquals(Integer.MIN_VALUE, unpackUid(packed));
524        assertEquals(Integer.MAX_VALUE, unpackTag(packed));
525
526        packed = packUidAndTag(10005, 0xFFFFFFFF);
527        assertEquals(10005, unpackUid(packed));
528        assertEquals(0xFFFFFFFF, unpackTag(packed));
529
530    }
531
532    public void testSummaryForAllUid() throws Exception {
533        long elapsedRealtime = 0;
534
535        // pretend that network comes online
536        expectTime(TEST_START + elapsedRealtime);
537        expectDefaultSettings();
538        expectNetworkState(buildWifiState());
539        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
540
541        replay();
542        mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
543        verifyAndReset();
544
545        // create some traffic for two apps
546        elapsedRealtime += HOUR_IN_MILLIS;
547        expectTime(TEST_START + elapsedRealtime);
548        expectDefaultSettings();
549        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
550        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
551                .addValues(TEST_IFACE, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L)
552                .addValues(TEST_IFACE, UID_RED, 0xF00D, 10L, 1L, 10L, 1L)
553                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L));
554
555        replay();
556        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
557
558        // verify service recorded history
559        assertUidTotal(sTemplateWifi, UID_RED, 50L, 50L);
560        assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 512L);
561        verifyAndReset();
562
563        // now create more traffic in next hour, but only for one app
564        elapsedRealtime += HOUR_IN_MILLIS;
565        expectTime(TEST_START + elapsedRealtime);
566        expectDefaultSettings();
567        expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
568        expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
569                .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L));
570
571        replay();
572        mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
573
574        // first verify entire history present
575        NetworkStats stats = mService.getSummaryForAllUid(
576                sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
577        assertEquals(3, stats.size());
578        assertEntry(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L);
579        assertEntry(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L);
580        assertEntry(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L);
581
582        // now verify that recent history only contains one uid
583        final long currentTime = TEST_START + elapsedRealtime;
584        stats = mService.getSummaryForAllUid(
585                sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
586        assertEquals(1, stats.size());
587        assertEntry(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L);
588
589        verifyAndReset();
590    }
591
592    private void assertNetworkTotal(NetworkTemplate template, long rx, long tx) {
593        final NetworkStatsHistory history = mService.getHistoryForNetwork(template);
594        final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
595        assertEquals(rx, total[0]);
596        assertEquals(tx, total[1]);
597    }
598
599    private void assertUidTotal(NetworkTemplate template, int uid, long rx, long tx) {
600        final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE);
601        final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
602        assertEquals(rx, total[0]);
603        assertEquals(tx, total[1]);
604    }
605
606    private void expectSystemReady() throws Exception {
607        mAlarmManager.remove(isA(PendingIntent.class));
608        expectLastCall().anyTimes();
609
610        mAlarmManager.setInexactRepeating(
611                eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), isA(PendingIntent.class));
612        expectLastCall().atLeastOnce();
613    }
614
615    private void expectNetworkState(NetworkState... state) throws Exception {
616        expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
617    }
618
619    private void expectNetworkStatsSummary(NetworkStats summary) throws Exception {
620        expect(mNetManager.getNetworkStatsSummary()).andReturn(summary).atLeastOnce();
621    }
622
623    private void expectNetworkStatsDetail(NetworkStats detail) throws Exception {
624        expect(mNetManager.getNetworkStatsDetail()).andReturn(detail).atLeastOnce();
625    }
626
627    private void expectDefaultSettings() throws Exception {
628        expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
629    }
630
631    private void expectSettings(long persistThreshold, long bucketDuration, long maxHistory)
632            throws Exception {
633        expect(mSettings.getPollInterval()).andReturn(HOUR_IN_MILLIS).anyTimes();
634        expect(mSettings.getPersistThreshold()).andReturn(persistThreshold).anyTimes();
635        expect(mSettings.getNetworkBucketDuration()).andReturn(bucketDuration).anyTimes();
636        expect(mSettings.getNetworkMaxHistory()).andReturn(maxHistory).anyTimes();
637        expect(mSettings.getUidBucketDuration()).andReturn(bucketDuration).anyTimes();
638        expect(mSettings.getUidMaxHistory()).andReturn(maxHistory).anyTimes();
639        expect(mSettings.getTagMaxHistory()).andReturn(maxHistory).anyTimes();
640        expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes();
641    }
642
643    private void expectTime(long currentTime) throws Exception {
644        expect(mTime.forceRefresh()).andReturn(false).anyTimes();
645        expect(mTime.hasCache()).andReturn(true).anyTimes();
646        expect(mTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
647        expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
648        expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
649    }
650
651    private void assertStatsFilesExist(boolean exist) {
652        final File networkFile = new File(mStatsDir, "netstats.bin");
653        final File uidFile = new File(mStatsDir, "netstats_uid.bin");
654        if (exist) {
655            assertTrue(networkFile.exists());
656            assertTrue(uidFile.exists());
657        } else {
658            assertFalse(networkFile.exists());
659            assertFalse(uidFile.exists());
660        }
661    }
662
663    private static void assertEntry(NetworkStats stats, int i, String iface, int uid, int tag,
664            long rxBytes, long rxPackets, long txBytes, long txPackets) {
665        final NetworkStats.Entry entry = stats.getValues(i, null);
666        assertEquals(iface, entry.iface);
667        assertEquals(uid, entry.uid);
668        assertEquals(tag, entry.tag);
669        assertEquals(rxBytes, entry.rxBytes);
670        // TODO: enable testing packet counts once stored in history
671//        assertEquals(rxPackets, entry.rxPackets);
672        assertEquals(txBytes, entry.txBytes);
673//        assertEquals(txPackets, entry.txPackets);
674    }
675
676    private static NetworkState buildWifiState() {
677        final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
678        info.setDetailedState(DetailedState.CONNECTED, null, null);
679        final LinkProperties prop = new LinkProperties();
680        prop.setInterfaceName(TEST_IFACE);
681        return new NetworkState(info, prop, null);
682    }
683
684    private static NetworkState buildMobile3gState(String subscriberId) {
685        final NetworkInfo info = new NetworkInfo(
686                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UMTS, null, null);
687        info.setDetailedState(DetailedState.CONNECTED, null, null);
688        final LinkProperties prop = new LinkProperties();
689        prop.setInterfaceName(TEST_IFACE);
690        return new NetworkState(info, prop, null, subscriberId);
691    }
692
693    private static NetworkState buildMobile4gState() {
694        final NetworkInfo info = new NetworkInfo(TYPE_WIMAX, 0, null, null);
695        info.setDetailedState(DetailedState.CONNECTED, null, null);
696        final LinkProperties prop = new LinkProperties();
697        prop.setInterfaceName(TEST_IFACE);
698        return new NetworkState(info, prop, null);
699    }
700
701    private static NetworkStats buildEmptyStats(long elapsedRealtime) {
702        return new NetworkStats(elapsedRealtime, 0);
703    }
704
705    private void replay() {
706        EasyMock.replay(mNetManager, mAlarmManager, mTime, mSettings, mConnManager);
707    }
708
709    private void verifyAndReset() {
710        EasyMock.verify(mNetManager, mAlarmManager, mTime, mSettings, mConnManager);
711        EasyMock.reset(mNetManager, mAlarmManager, mTime, mSettings, mConnManager);
712    }
713}
714