blob: c3ba83453138114aad1cca965e66b47c5155e3c3 [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;
23import android.content.pm.PackageManager;
24import android.net.ConnectivityManager;
25import android.net.LocalServerSocket;
26import android.net.LocalSocket;
27import android.net.Network;
28import android.net.NetworkCapabilities;
29import android.net.NetworkInfo;
30import android.net.NetworkRequest;
31import android.os.ParcelFileDescriptor;
32import android.os.Process;
33import android.os.RemoteException;
34import android.test.InstrumentationTestCase;
35import android.util.Log;
36
37import dalvik.system.SocketTagger;
38
39import java.io.FileInputStream;
40import java.io.IOException;
41import java.io.InputStream;
42import java.io.InputStreamReader;
43import java.io.OutputStream;
44import java.net.InetAddress;
45import java.net.Socket;
46import java.net.ServerSocket;
47import java.net.URL;
48import java.text.MessageFormat;
49import javax.net.ssl.HttpsURLConnection;
50
51import libcore.io.IoUtils;
52import libcore.io.Streams;
53
54public class NetworkUsageStatsTest extends InstrumentationTestCase {
55 private static final String LOG_TAG = "NetworkUsageStatsTest";
56 private static final String APPOPS_SET_SHELL_COMMAND = "appops set {0} " +
57 AppOpsManager.OPSTR_GET_USAGE_STATS + " {1}";
58
59 private static final long MINUTE = 1000 * 60;
60
61 private static final int[] sNetworkTypesToTest = new int[] {
62 ConnectivityManager.TYPE_WIFI,
63 ConnectivityManager.TYPE_MOBILE,
64 };
65
66 // Order corresponds to sNetworkTypesToTest
67 private static final int[] sTransportTypesToTest = new int[] {
68 NetworkCapabilities.TRANSPORT_WIFI,
69 NetworkCapabilities.TRANSPORT_CELLULAR,
70 };
71
72 private NetworkStatsManager mNsm;
73 private PackageManager mPm;
74 private ConnectivityManager mCm;
75 private long mStartTime;
76 private long mEndTime;
77
78 private long mBytesRead;
79
80 private void exerciseRemoteHost(int transportType) throws Exception {
81 final int timeout = 60000;
82 mCm.requestNetwork(new NetworkRequest.Builder()
83 .addTransportType(transportType)
84 .build(), new ConnectivityManager.NetworkCallback() {
85 @Override
86 public void onAvailable(Network network) {
87 NetworkInfo networkInfo = mCm.getNetworkInfo(network);
88 if (networkInfo == null) {
89 Log.w(LOG_TAG, "Network info is null");
90 } else {
91 Log.w(LOG_TAG, "Network: " + networkInfo.toString());
92 }
93 InputStreamReader in = null;
94 HttpsURLConnection urlc = null;
95 String originalKeepAlive = System.getProperty("http.keepAlive");
96 System.setProperty("http.keepAlive", "false");
97 try {
98 urlc = (HttpsURLConnection) network.openConnection(new URL(
99 "https://www.google.com"));
100 urlc.setConnectTimeout(timeout);
101 urlc.setUseCaches(false);
102 urlc.connect();
103 boolean ping = urlc.getResponseCode() == 200;
104 if (ping) {
105 in = new InputStreamReader(
106 (InputStream) urlc.getContent());
107
108 mBytesRead = 0;
109 while (in.read() != -1) ++mBytesRead;
110 }
111 } catch (Exception e) {
112 Log.i(LOG_TAG, "Badness during exercising remote server: " + e);
113 } finally {
114 if (in != null) {
115 try {
116 in.close();
117 } catch (IOException e) {
118 // don't care
119 }
120 }
121 if (urlc != null) {
122 urlc.disconnect();
123 }
124 if (originalKeepAlive == null) {
125 System.clearProperty("http.keepAlive");
126 } else {
127 System.setProperty("http.keepAlive", originalKeepAlive);
128 }
129 }
130 }
131 });
132 try {
133 Thread.sleep(timeout);
134 } catch (InterruptedException e) {
135 }
136 }
137
138 @Override
139 protected void setUp() throws Exception {
140 mNsm = (NetworkStatsManager) getInstrumentation().getContext()
141 .getSystemService(Context.NETWORK_STATS_SERVICE);
142
143 mPm = getInstrumentation().getContext().getPackageManager();
144 mCm = (ConnectivityManager) getInstrumentation().getContext()
145 .getSystemService(Context.CONNECTIVITY_SERVICE);
146 }
147
148 @Override
149 protected void tearDown() throws Exception {
150 super.tearDown();
151 }
152
153 private void setAppOpsMode(String mode) throws Exception {
154 final String command = MessageFormat.format(APPOPS_SET_SHELL_COMMAND,
155 getInstrumentation().getContext().getPackageName(), mode);
156 ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
157 .executeShellCommand(command);
158 try {
159 Streams.readFully(new FileInputStream(pfd.getFileDescriptor()));
160 } finally {
161 IoUtils.closeQuietly(pfd.getFileDescriptor());
162 }
163 }
164
165 private boolean shouldTestThisNetworkType(int networkTypeIndex) throws Exception {
166 NetworkInfo networkInfo = mCm.getNetworkInfo(sNetworkTypesToTest[networkTypeIndex]);
167 if (networkInfo == null || !networkInfo.isAvailable()) {
168 return false;
169 }
170 mStartTime = System.currentTimeMillis() - MINUTE/2;
171 exerciseRemoteHost(sTransportTypesToTest[networkTypeIndex]);
172 mEndTime = System.currentTimeMillis() + MINUTE/2;
173 return true;
174 }
175
176 public void testDeviceSummary() throws Exception {
177 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
178 if (!shouldTestThisNetworkType(i)) {
179 continue;
180 }
181 setAppOpsMode("allow");
182 NetworkStats.Bucket bucket = null;
183 try {
184 bucket = mNsm.querySummaryForDevice(
185 sNetworkTypesToTest[i], "", mStartTime, mEndTime);
186 } catch (RemoteException | SecurityException e) {
187 fail("testDeviceSummary fails with exception: " + e.toString());
188 }
189 assertTrue(bucket != null);
190 setAppOpsMode("deny");
191 try {
192 bucket = mNsm.querySummaryForDevice(
193 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime);
194 fail("negative testDeviceSummary fails: no exception thrown.");
195 } catch (RemoteException e) {
196 fail("testDeviceSummary fails with exception: " + e.toString());
197 } catch (SecurityException e) {
198 // expected outcome
199 }
200 }
201 }
202
203 public void testUserSummary() throws Exception {
204 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
205 if (!shouldTestThisNetworkType(i)) {
206 continue;
207 }
208 setAppOpsMode("allow");
209 NetworkStats.Bucket bucket = null;
210 try {
211 bucket = mNsm.querySummaryForUser(
212 sNetworkTypesToTest[i], "", mStartTime, mEndTime);
213 } catch (RemoteException | SecurityException e) {
214 fail("testUserSummary fails with exception: " + e.toString());
215 }
216 assertTrue(bucket != null);
217 setAppOpsMode("deny");
218 try {
219 bucket = mNsm.querySummaryForUser(
220 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime);
221 fail("negative testUserSummary fails: no exception thrown.");
222 } catch (RemoteException e) {
223 fail("testUserSummary fails with exception: " + e.toString());
224 } catch (SecurityException e) {
225 // expected outcome
226 }
227 }
228 }
229
230 public void testAppSummary() throws Exception {
231 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
232 if (!shouldTestThisNetworkType(i)) {
233 continue;
234 }
235 setAppOpsMode("allow");
236 NetworkStats result = null;
237 try {
238 result = mNsm.querySummary(
239 sNetworkTypesToTest[i], "", mStartTime, mEndTime);
240 assertTrue(result != null);
241 NetworkStats.Bucket bucket = new NetworkStats.Bucket();
242 long totalTxPackets = 0;
243 long totalRxPackets = 0;
244 long totalTxBytes = 0;
245 long totalRxBytes = 0;
246 while (result.getNextBucket(bucket)) {
247 if (bucket.getUid() == Process.myUid()) {
248 totalTxPackets += bucket.getTxPackets();
249 totalRxPackets += bucket.getRxPackets();
250 totalTxBytes += bucket.getTxBytes();
251 totalRxBytes += bucket.getRxBytes();
252 }
253 }
254 assertTrue("No Rx bytes usage for uid " + Process.myUid(), totalRxBytes > 0);
255 assertTrue("No Rx packets usage for uid " + Process.myUid(), totalRxPackets > 0);
256 assertTrue("No Tx bytes usage for uid " + Process.myUid(), totalTxBytes > 0);
257 assertTrue("No Tx packets usage for uid " + Process.myUid(), totalTxPackets > 0);
258 } catch (RemoteException | SecurityException e) {
259 fail("testAppSummary fails with exception: " + e.toString());
260 } finally {
261 if (result != null) {
262 result.close();
263 }
264 }
265 setAppOpsMode("deny");
266 try {
267 result = mNsm.querySummary(
268 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime);
269 fail("negative testAppSummary fails: no exception thrown.");
270 } catch (RemoteException e) {
271 fail("testAppSummary fails with exception: " + e.toString());
272 } catch (SecurityException e) {
273 // expected outcome
274 }
275 }
276 }
277
278 public void testAppDetails() throws Exception {
279 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
280 if (!shouldTestThisNetworkType(i)) {
281 continue;
282 }
283 setAppOpsMode("allow");
284 NetworkStats result = null;
285 try {
286 result = mNsm.queryDetails(
287 sNetworkTypesToTest[i], "", mStartTime, mEndTime);
288 assertTrue(result != null);
289 } catch (RemoteException | SecurityException e) {
290 fail("testAppDetails fails with exception: " + e.toString());
291 } finally {
292 if (result != null) {
293 result.close();
294 }
295 }
296 setAppOpsMode("deny");
297 try {
298 result = mNsm.queryDetails(
299 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime);
300 fail("negative testAppDetails fails: no exception thrown.");
301 } catch (RemoteException e) {
302 fail("testAppDetails fails with exception: " + e.toString());
303 } catch (SecurityException e) {
304 // expected outcome
305 }
306 }
307 }
308
309 public void testUidDetails() throws Exception {
310 for (int i = 0; i < sNetworkTypesToTest.length; ++i) {
311 if (!shouldTestThisNetworkType(i)) {
312 continue;
313 }
314 setAppOpsMode("allow");
315 NetworkStats result = null;
316 try {
317 result = mNsm.queryDetailsForUid(
318 sNetworkTypesToTest[i], "", mStartTime, mEndTime, Process.myUid());
319 assertTrue(result != null);
320 } catch (RemoteException | SecurityException e) {
321 fail("testUidDetails fails with exception: " + e.toString());
322 } finally {
323 if (result != null) {
324 result.close();
325 }
326 }
327 setAppOpsMode("deny");
328 try {
329 result = mNsm.queryDetailsForUid(
330 ConnectivityManager.TYPE_WIFI, "", mStartTime, mEndTime, Process.myUid());
331 fail("negative testUidDetails fails: no exception thrown.");
332 } catch (RemoteException e) {
333 fail("testUidDetails fails with exception: " + e.toString());
334 } catch (SecurityException e) {
335 // expected outcome
336 }
337 }
338 }
339}