blob: b2bede1914b091f64eeef5863869b5035bc00606 [file] [log] [blame]
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +01001/**
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17package android.app.usage.cts;
18
19import android.app.AppOpsManager;
20import android.app.usage.NetworkStatsManager;
21import android.app.usage.NetworkStats;
22import android.content.Context;
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +010023import android.net.ConnectivityManager;
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +010024import android.net.Network;
25import android.net.NetworkCapabilities;
26import android.net.NetworkInfo;
27import android.net.NetworkRequest;
28import android.os.ParcelFileDescriptor;
29import android.os.Process;
30import android.os.RemoteException;
31import android.test.InstrumentationTestCase;
32import android.util.Log;
33
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +010034import java.io.FileInputStream;
35import java.io.IOException;
36import java.io.InputStream;
37import java.io.InputStreamReader;
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +010038import java.net.URL;
39import java.text.MessageFormat;
40import javax.net.ssl.HttpsURLConnection;
41
42import libcore.io.IoUtils;
43import libcore.io.Streams;
44
45public class NetworkUsageStatsTest extends InstrumentationTestCase {
46 private static final String LOG_TAG = "NetworkUsageStatsTest";
47 private static final String APPOPS_SET_SHELL_COMMAND = "appops set {0} " +
48 AppOpsManager.OPSTR_GET_USAGE_STATS + " {1}";
49
50 private static final long MINUTE = 1000 * 60;
51
52 private static final int[] sNetworkTypesToTest = new int[] {
53 ConnectivityManager.TYPE_WIFI,
54 ConnectivityManager.TYPE_MOBILE,
55 };
56
57 // Order corresponds to sNetworkTypesToTest
58 private static final int[] sTransportTypesToTest = new int[] {
59 NetworkCapabilities.TRANSPORT_WIFI,
60 NetworkCapabilities.TRANSPORT_CELLULAR,
61 };
62
63 private NetworkStatsManager mNsm;
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +010064 private ConnectivityManager mCm;
65 private long mStartTime;
66 private long mEndTime;
67
68 private long mBytesRead;
69
70 private void exerciseRemoteHost(int transportType) throws Exception {
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +010071 final int timeout = 15000;
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +010072 mCm.requestNetwork(new NetworkRequest.Builder()
73 .addTransportType(transportType)
74 .build(), new ConnectivityManager.NetworkCallback() {
75 @Override
76 public void onAvailable(Network network) {
77 NetworkInfo networkInfo = mCm.getNetworkInfo(network);
78 if (networkInfo == null) {
79 Log.w(LOG_TAG, "Network info is null");
80 } else {
81 Log.w(LOG_TAG, "Network: " + networkInfo.toString());
82 }
83 InputStreamReader in = null;
84 HttpsURLConnection urlc = null;
85 String originalKeepAlive = System.getProperty("http.keepAlive");
86 System.setProperty("http.keepAlive", "false");
87 try {
88 urlc = (HttpsURLConnection) network.openConnection(new URL(
89 "https://www.google.com"));
90 urlc.setConnectTimeout(timeout);
91 urlc.setUseCaches(false);
92 urlc.connect();
93 boolean ping = urlc.getResponseCode() == 200;
94 if (ping) {
95 in = new InputStreamReader(
96 (InputStream) urlc.getContent());
97
98 mBytesRead = 0;
99 while (in.read() != -1) ++mBytesRead;
100 }
101 } catch (Exception e) {
102 Log.i(LOG_TAG, "Badness during exercising remote server: " + e);
103 } finally {
104 if (in != null) {
105 try {
106 in.close();
107 } catch (IOException e) {
108 // don't care
109 }
110 }
111 if (urlc != null) {
112 urlc.disconnect();
113 }
114 if (originalKeepAlive == null) {
115 System.clearProperty("http.keepAlive");
116 } else {
117 System.setProperty("http.keepAlive", originalKeepAlive);
118 }
119 }
120 }
121 });
122 try {
123 Thread.sleep(timeout);
124 } catch (InterruptedException e) {
125 }
126 }
127
128 @Override
129 protected void setUp() throws Exception {
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100130 super.setUp();
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100131 mNsm = (NetworkStatsManager) getInstrumentation().getContext()
132 .getSystemService(Context.NETWORK_STATS_SERVICE);
133
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100134 mCm = (ConnectivityManager) getInstrumentation().getContext()
135 .getSystemService(Context.CONNECTIVITY_SERVICE);
136 }
137
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100138 private void setAppOpsMode(String mode) throws Exception {
139 final String command = MessageFormat.format(APPOPS_SET_SHELL_COMMAND,
140 getInstrumentation().getContext().getPackageName(), mode);
141 ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
142 .executeShellCommand(command);
143 try {
144 Streams.readFully(new FileInputStream(pfd.getFileDescriptor()));
145 } finally {
146 IoUtils.closeQuietly(pfd.getFileDescriptor());
147 }
148 }
149
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100150 private boolean shouldTestThisNetworkType(int networkTypeIndex, long tolerance)
151 throws Exception {
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100152 NetworkInfo networkInfo = mCm.getNetworkInfo(sNetworkTypesToTest[networkTypeIndex]);
153 if (networkInfo == null || !networkInfo.isAvailable()) {
154 return false;
155 }
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100156 mStartTime = System.currentTimeMillis() - tolerance;
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100157 exerciseRemoteHost(sTransportTypesToTest[networkTypeIndex]);
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100158 mEndTime = System.currentTimeMillis() + tolerance;
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100159 return true;
160 }
161
162 public void testDeviceSummary() throws Exception {
163 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100164 if (!shouldTestThisNetworkType(i, MINUTE/2)) {
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100165 continue;
166 }
167 setAppOpsMode("allow");
168 NetworkStats.Bucket bucket = null;
169 try {
170 bucket = mNsm.querySummaryForDevice(
171 sNetworkTypesToTest[i], "", mStartTime, mEndTime);
172 } catch (RemoteException | SecurityException e) {
173 fail("testDeviceSummary fails with exception: " + e.toString());
174 }
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100175 assertNotNull(bucket);
176 assertTimestamps(bucket);
177 assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
178 assertEquals(bucket.getUid(), NetworkStats.Bucket.UID_ALL);
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100179 setAppOpsMode("deny");
180 try {
181 bucket = mNsm.querySummaryForDevice(
182 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime);
183 fail("negative testDeviceSummary fails: no exception thrown.");
184 } catch (RemoteException e) {
185 fail("testDeviceSummary fails with exception: " + e.toString());
186 } catch (SecurityException e) {
187 // expected outcome
188 }
189 }
190 }
191
192 public void testUserSummary() throws Exception {
193 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100194 if (!shouldTestThisNetworkType(i, MINUTE/2)) {
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100195 continue;
196 }
197 setAppOpsMode("allow");
198 NetworkStats.Bucket bucket = null;
199 try {
200 bucket = mNsm.querySummaryForUser(
201 sNetworkTypesToTest[i], "", mStartTime, mEndTime);
202 } catch (RemoteException | SecurityException e) {
203 fail("testUserSummary fails with exception: " + e.toString());
204 }
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100205 assertNotNull(bucket);
206 assertTimestamps(bucket);
207 assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
208 assertEquals(bucket.getUid(), NetworkStats.Bucket.UID_ALL);
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100209 setAppOpsMode("deny");
210 try {
211 bucket = mNsm.querySummaryForUser(
212 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime);
213 fail("negative testUserSummary fails: no exception thrown.");
214 } catch (RemoteException e) {
215 fail("testUserSummary fails with exception: " + e.toString());
216 } catch (SecurityException e) {
217 // expected outcome
218 }
219 }
220 }
221
222 public void testAppSummary() throws Exception {
223 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100224 if (!shouldTestThisNetworkType(i, MINUTE/2)) {
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100225 continue;
226 }
227 setAppOpsMode("allow");
228 NetworkStats result = null;
229 try {
230 result = mNsm.querySummary(
231 sNetworkTypesToTest[i], "", mStartTime, mEndTime);
232 assertTrue(result != null);
233 NetworkStats.Bucket bucket = new NetworkStats.Bucket();
234 long totalTxPackets = 0;
235 long totalRxPackets = 0;
236 long totalTxBytes = 0;
237 long totalRxBytes = 0;
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100238 while (result.hasNextBucket()) {
239 assertTrue(result.getNextBucket(bucket));
240 assertTimestamps(bucket);
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100241 if (bucket.getUid() == Process.myUid()) {
242 totalTxPackets += bucket.getTxPackets();
243 totalRxPackets += bucket.getRxPackets();
244 totalTxBytes += bucket.getTxBytes();
245 totalRxBytes += bucket.getRxBytes();
246 }
247 }
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100248 assertFalse(result.getNextBucket(bucket));
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100249 assertTrue("No Rx bytes usage for uid " + Process.myUid(), totalRxBytes > 0);
250 assertTrue("No Rx packets usage for uid " + Process.myUid(), totalRxPackets > 0);
251 assertTrue("No Tx bytes usage for uid " + Process.myUid(), totalTxBytes > 0);
252 assertTrue("No Tx packets usage for uid " + Process.myUid(), totalTxPackets > 0);
253 } catch (RemoteException | SecurityException e) {
254 fail("testAppSummary fails with exception: " + e.toString());
255 } finally {
256 if (result != null) {
257 result.close();
258 }
259 }
260 setAppOpsMode("deny");
261 try {
262 result = mNsm.querySummary(
263 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime);
264 fail("negative testAppSummary fails: no exception thrown.");
265 } catch (RemoteException e) {
266 fail("testAppSummary fails with exception: " + e.toString());
267 } catch (SecurityException e) {
268 // expected outcome
269 }
270 }
271 }
272
273 public void testAppDetails() throws Exception {
274 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100275 // Relatively large tolerance to accommodate for history bucket size.
276 if (!shouldTestThisNetworkType(i, MINUTE * 120)) {
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100277 continue;
278 }
279 setAppOpsMode("allow");
280 NetworkStats result = null;
281 try {
282 result = mNsm.queryDetails(
283 sNetworkTypesToTest[i], "", mStartTime, mEndTime);
284 assertTrue(result != null);
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100285 NetworkStats.Bucket bucket = new NetworkStats.Bucket();
286 long totalTxPackets = 0;
287 long totalRxPackets = 0;
288 long totalTxBytes = 0;
289 long totalRxBytes = 0;
290 while (result.hasNextBucket()) {
291 assertTrue(result.getNextBucket(bucket));
292 assertTimestamps(bucket);
293 assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
294 if (bucket.getUid() == Process.myUid()) {
295 totalTxPackets += bucket.getTxPackets();
296 totalRxPackets += bucket.getRxPackets();
297 totalTxBytes += bucket.getTxBytes();
298 totalRxBytes += bucket.getRxBytes();
299 }
300 }
301 assertFalse(result.getNextBucket(bucket));
302 assertTrue("No Rx bytes usage for uid " + Process.myUid(), totalRxBytes > 0);
303 assertTrue("No Rx packets usage for uid " + Process.myUid(), totalRxPackets > 0);
304 assertTrue("No Tx bytes usage for uid " + Process.myUid(), totalTxBytes > 0);
305 assertTrue("No Tx packets usage for uid " + Process.myUid(), totalTxPackets > 0);
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100306 } catch (RemoteException | SecurityException e) {
307 fail("testAppDetails fails with exception: " + e.toString());
308 } finally {
309 if (result != null) {
310 result.close();
311 }
312 }
313 setAppOpsMode("deny");
314 try {
315 result = mNsm.queryDetails(
316 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime);
317 fail("negative testAppDetails fails: no exception thrown.");
318 } catch (RemoteException e) {
319 fail("testAppDetails fails with exception: " + e.toString());
320 } catch (SecurityException e) {
321 // expected outcome
322 }
323 }
324 }
325
326 public void testUidDetails() throws Exception {
327 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100328 // Relatively large tolerance to accommodate for history bucket size.
329 if (!shouldTestThisNetworkType(i, MINUTE * 120)) {
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100330 continue;
331 }
332 setAppOpsMode("allow");
333 NetworkStats result = null;
334 try {
335 result = mNsm.queryDetailsForUid(
336 sNetworkTypesToTest[i], "", mStartTime, mEndTime, Process.myUid());
337 assertTrue(result != null);
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100338 NetworkStats.Bucket bucket = new NetworkStats.Bucket();
339 long totalTxPackets = 0;
340 long totalRxPackets = 0;
341 long totalTxBytes = 0;
342 long totalRxBytes = 0;
343 while (result.hasNextBucket()) {
344 assertTrue(result.getNextBucket(bucket));
345 assertTimestamps(bucket);
346 assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
347 assertEquals(bucket.getUid(), Process.myUid());
348 totalTxPackets += bucket.getTxPackets();
349 totalRxPackets += bucket.getRxPackets();
350 totalTxBytes += bucket.getTxBytes();
351 totalRxBytes += bucket.getRxBytes();
352 }
353 assertFalse(result.getNextBucket(bucket));
354 assertTrue("No Rx bytes usage for uid " + Process.myUid(), totalRxBytes > 0);
355 assertTrue("No Rx packets usage for uid " + Process.myUid(), totalRxPackets > 0);
356 assertTrue("No Tx bytes usage for uid " + Process.myUid(), totalTxBytes > 0);
357 assertTrue("No Tx packets usage for uid " + Process.myUid(), totalTxPackets > 0);
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100358 } catch (RemoteException | SecurityException e) {
359 fail("testUidDetails fails with exception: " + e.toString());
360 } finally {
361 if (result != null) {
362 result.close();
363 }
364 }
365 setAppOpsMode("deny");
366 try {
367 result = mNsm.queryDetailsForUid(
368 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime, Process.myUid());
369 fail("negative testUidDetails fails: no exception thrown.");
370 } catch (RemoteException e) {
371 fail("testUidDetails fails with exception: " + e.toString());
372 } catch (SecurityException e) {
373 // expected outcome
374 }
375 }
376 }
Zoltan Szatmary-Ban3f6dec12015-06-16 15:52:11 +0100377
378 private void assertTimestamps(final NetworkStats.Bucket bucket) {
379 assertTrue("Start timestamp " + bucket.getStartTimeStamp() + " is less than " +
380 mStartTime, bucket.getStartTimeStamp() >= mStartTime);
381 assertTrue("End timestamp " + bucket.getEndTimeStamp() + " is greater than " +
382 mEndTime, bucket.getEndTimeStamp() <= mEndTime);
383 }
Zoltan Szatmary-Ban8f002252015-05-06 09:33:58 +0100384}