blob: 4a58f885ff08a8e0770892687d1f85f9a7235a47 [file] [log] [blame]
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -07001/*
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.bandwidthtest;
18
19import android.content.Context;
20import android.net.ConnectivityManager;
21import android.net.NetworkInfo.State;
22import android.net.NetworkStats;
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -070023import android.net.NetworkStats.Entry;
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -070024import android.net.TrafficStats;
25import android.net.wifi.WifiManager;
26import android.os.Bundle;
27import android.os.Environment;
28import android.os.Process;
29import android.os.SystemClock;
30import android.telephony.TelephonyManager;
31import android.test.InstrumentationTestCase;
32import android.test.suitebuilder.annotation.LargeTest;
33import android.util.Log;
34
35import com.android.bandwidthtest.util.BandwidthTestUtil;
36import com.android.bandwidthtest.util.ConnectionUtil;
37
38import java.io.File;
39
40/**
41 * Test that downloads files from a test server and reports the bandwidth metrics collected.
42 */
43public class BandwidthTest extends InstrumentationTestCase {
44
45 private static final String LOG_TAG = "BandwidthTest";
46 private final static String PROF_LABEL = "PROF_";
47 private final static String PROC_LABEL = "PROC_";
48 private final static int INSTRUMENTATION_IN_PROGRESS = 2;
49
50 private final static String BASE_DIR =
51 Environment.getExternalStorageDirectory().getAbsolutePath();
52 private final static String TMP_FILENAME = "tmp.dat";
53 // Download 10.486 * 106 bytes (+ headers) from app engine test server.
54 private final int FILE_SIZE = 10485613;
55 private Context mContext;
56 private ConnectionUtil mConnectionUtil;
57 private TelephonyManager mTManager;
58 private int mUid;
59 private String mSsid;
60 private String mTestServer;
61 private String mDeviceId;
62 private BandwidthTestRunner mRunner;
63
64
65 @Override
66 protected void setUp() throws Exception {
67 super.setUp();
68 mRunner = (BandwidthTestRunner) getInstrumentation();
69 mSsid = mRunner.mSsid;
70 mTestServer = mRunner.mTestServer;
71 mContext = mRunner.getTargetContext();
72 mConnectionUtil = new ConnectionUtil(mContext);
73 mConnectionUtil.initialize();
74 Log.v(LOG_TAG, "Initialized mConnectionUtil");
75 mUid = Process.myUid();
76 mTManager = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
77 mDeviceId = mTManager.getDeviceId();
78 }
79
80 @Override
81 protected void tearDown() throws Exception {
82 mConnectionUtil.cleanUp();
83 super.tearDown();
84 }
85
86 /**
87 * Ensure that downloading on wifi reports reasonable stats.
88 */
89 @LargeTest
Jeff Sharkey163e6442011-10-31 16:37:52 -070090 public void testWifiDownload() throws Exception {
Tsu Chiang Chuanga8c57bf2012-02-01 15:24:51 -080091 mConnectionUtil.wifiTestInit();
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -080092 assertTrue("Could not connect to wifi!", setDeviceWifiAndAirplaneMode(mSsid));
93 downloadFile();
94 }
95
96 /**
97 * Ensure that downloading on mobile reports reasonable stats.
98 */
99 @LargeTest
100 public void testMobileDownload() throws Exception {
101 // As part of the setup we disconnected from wifi; make sure we are connected to mobile and
102 // that we have data.
103 assertTrue("Do not have mobile data!", hasMobileData());
104 downloadFile();
105 }
106
107 /**
108 * Helper method that downloads a file using http connection from a test server and reports the
109 * data usage stats to instrumentation out.
110 */
111 protected void downloadFile() throws Exception {
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700112 NetworkStats pre_test_stats = fetchDataFromProc(mUid);
113 String ts = Long.toString(System.currentTimeMillis());
114
115 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
116 mTestServer, FILE_SIZE, mDeviceId, ts);
117 TrafficStats.startDataProfiling(mContext);
118 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
119 assertTrue(BandwidthTestUtil.DownloadFromUrl(targetUrl, tmpSaveFile));
120 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700121 Log.d(LOG_TAG, prof_stats.toString());
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700122
123 NetworkStats post_test_stats = fetchDataFromProc(mUid);
124 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
125
126 // Output measurements to instrumentation out, so that it can be compared to that of
127 // the server.
128 Bundle results = new Bundle();
129 results.putString("device_id", mDeviceId);
130 results.putString("timestamp", ts);
131 results.putInt("size", FILE_SIZE);
Maxim Siniavineca766922013-11-04 16:12:01 -0800132 addStatsToResults(PROF_LABEL, prof_stats, results, mUid);
133 addStatsToResults(PROC_LABEL, proc_stats, results, mUid);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700134 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
135
136 // Clean up.
137 assertTrue(cleanUpFile(tmpSaveFile));
138 }
139
140 /**
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800141 * Ensure that uploading on wifi reports reasonable stats.
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700142 */
143 @LargeTest
Jeff Sharkey163e6442011-10-31 16:37:52 -0700144 public void testWifiUpload() throws Exception {
Tsu Chiang Chuanga8c57bf2012-02-01 15:24:51 -0800145 mConnectionUtil.wifiTestInit();
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700146 assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800147 uploadFile();
148 }
149
150 /**
151 * Ensure that uploading on wifi reports reasonable stats.
152 */
153 @LargeTest
154 public void testMobileUpload() throws Exception {
155 assertTrue(hasMobileData());
156 uploadFile();
157 }
158
159 /**
160 * Helper method that downloads a test file to upload. The stats reported to instrumentation out
161 * only include upload stats.
162 */
163 protected void uploadFile() throws Exception {
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700164 // Download a file from the server.
165 String ts = Long.toString(System.currentTimeMillis());
166 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
167 mTestServer, FILE_SIZE, mDeviceId, ts);
168 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
169 assertTrue(BandwidthTestUtil.DownloadFromUrl(targetUrl, tmpSaveFile));
170
171 ts = Long.toString(System.currentTimeMillis());
172 NetworkStats pre_test_stats = fetchDataFromProc(mUid);
173 TrafficStats.startDataProfiling(mContext);
174 assertTrue(BandwidthTestUtil.postFileToServer(mTestServer, mDeviceId, ts, tmpSaveFile));
175 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
176 Log.d(LOG_TAG, prof_stats.toString());
177 NetworkStats post_test_stats = fetchDataFromProc(mUid);
178 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
179
180 // Output measurements to instrumentation out, so that it can be compared to that of
181 // the server.
182 Bundle results = new Bundle();
183 results.putString("device_id", mDeviceId);
184 results.putString("timestamp", ts);
185 results.putInt("size", FILE_SIZE);
Maxim Siniavineca766922013-11-04 16:12:01 -0800186 addStatsToResults(PROF_LABEL, prof_stats, results, mUid);
187 addStatsToResults(PROC_LABEL, proc_stats, results, mUid);
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700188 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
189
190 // Clean up.
191 assertTrue(cleanUpFile(tmpSaveFile));
192 }
193
194 /**
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800195 * We want to make sure that if we use wifi and the Download Manager to download stuff,
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700196 * accounting still goes to the app making the call and that the numbers still make sense.
197 */
198 @LargeTest
Jeff Sharkey163e6442011-10-31 16:37:52 -0700199 public void testWifiDownloadWithDownloadManager() throws Exception {
Tsu Chiang Chuanga8c57bf2012-02-01 15:24:51 -0800200 mConnectionUtil.wifiTestInit();
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700201 assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800202 downloadFileUsingDownloadManager();
203 }
204
205 /**
206 * We want to make sure that if we use mobile data and the Download Manager to download stuff,
207 * accounting still goes to the app making the call and that the numbers still make sense.
208 */
209 @LargeTest
210 public void testMobileDownloadWithDownloadManager() throws Exception {
211 assertTrue(hasMobileData());
212 downloadFileUsingDownloadManager();
213 }
214
215 /**
216 * Helper method that downloads a file from a test server using the download manager and reports
217 * the stats to instrumentation out.
218 */
219 protected void downloadFileUsingDownloadManager() throws Exception {
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700220 // If we are using the download manager, then the data that is written to /proc/uid_stat/
221 // is accounted against download manager's uid, since it uses pre-ICS API.
222 int downloadManagerUid = mConnectionUtil.downloadManagerUid();
223 assertTrue(downloadManagerUid >= 0);
224 NetworkStats pre_test_stats = fetchDataFromProc(downloadManagerUid);
225 // start profiling
226 TrafficStats.startDataProfiling(mContext);
227 String ts = Long.toString(System.currentTimeMillis());
228 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
229 mTestServer, FILE_SIZE, mDeviceId, ts);
230 Log.v(LOG_TAG, "Download url: " + targetUrl);
231 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
232 assertTrue(mConnectionUtil.startDownloadAndWait(targetUrl, 500000));
233 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
234 NetworkStats post_test_stats = fetchDataFromProc(downloadManagerUid);
235 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700236 Log.d(LOG_TAG, prof_stats.toString());
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700237 // Output measurements to instrumentation out, so that it can be compared to that of
238 // the server.
239 Bundle results = new Bundle();
240 results.putString("device_id", mDeviceId);
241 results.putString("timestamp", ts);
242 results.putInt("size", FILE_SIZE);
Maxim Siniavineca766922013-11-04 16:12:01 -0800243 addStatsToResults(PROF_LABEL, prof_stats, results, mUid);
244 // remember to use download manager uid for proc stats
245 addStatsToResults(PROC_LABEL, proc_stats, results, downloadManagerUid);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700246 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
247
248 // Clean up.
249 assertTrue(cleanUpFile(tmpSaveFile));
250 }
251
252 /**
253 * Fetch network data from /proc/uid_stat/uid
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800254 *
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700255 * @return populated {@link NetworkStats}
256 */
257 public NetworkStats fetchDataFromProc(int uid) {
258 String root_filepath = "/proc/uid_stat/" + uid + "/";
259 File rcv_stat = new File (root_filepath + "tcp_rcv");
260 int rx = BandwidthTestUtil.parseIntValueFromFile(rcv_stat);
261 File snd_stat = new File (root_filepath + "tcp_snd");
262 int tx = BandwidthTestUtil.parseIntValueFromFile(snd_stat);
263 NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700264 stats.addValues(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
265 NetworkStats.TAG_NONE, rx, 0, tx, 0, 0);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700266 return stats;
267 }
268
269 /**
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800270 * Turn on Airplane mode and connect to the wifi.
271 *
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700272 * @param ssid of the wifi to connect to
273 * @return true if we successfully connected to a given network.
274 */
275 public boolean setDeviceWifiAndAirplaneMode(String ssid) {
276 mConnectionUtil.setAirplaneMode(mContext, true);
277 assertTrue(mConnectionUtil.connectToWifi(ssid));
278 assertTrue(mConnectionUtil.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
279 ConnectionUtil.LONG_TIMEOUT));
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800280 assertTrue(mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
281 State.CONNECTED, ConnectionUtil.LONG_TIMEOUT));
282 return mConnectionUtil.hasData();
283 }
284
285 /**
286 * Helper method to make sure we are connected to mobile data.
287 *
288 * @return true if we successfully connect to mobile data.
289 */
290 public boolean hasMobileData() {
Tsu Chiang Chuanga8c57bf2012-02-01 15:24:51 -0800291 assertTrue(mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
292 State.CONNECTED, ConnectionUtil.LONG_TIMEOUT));
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800293 assertTrue("Not connected to mobile", mConnectionUtil.isConnectedToMobile());
294 assertFalse("Still connected to wifi.", mConnectionUtil.isConnectedToWifi());
295 return mConnectionUtil.hasData();
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700296 }
297
298 /**
299 * Output the {@link NetworkStats} to Instrumentation out.
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800300 *
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700301 * @param label to attach to this given stats.
302 * @param stats {@link NetworkStats} to add.
303 * @param results {@link Bundle} to be added to.
Maxim Siniavineca766922013-11-04 16:12:01 -0800304 * @param uid for which to report the results.
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700305 */
Maxim Siniavineca766922013-11-04 16:12:01 -0800306 public void addStatsToResults(String label, NetworkStats stats, Bundle results, int uid){
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700307 if (results == null || results.isEmpty()) {
308 Log.e(LOG_TAG, "Empty bundle provided.");
309 return;
310 }
Maxim Siniavineca766922013-11-04 16:12:01 -0800311 Entry totalStats = null;
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700312 for (int i = 0; i < stats.size(); ++i) {
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700313 Entry statsEntry = stats.getValues(i, null);
314 // We are only interested in the all inclusive stats.
315 if (statsEntry.tag != 0) {
316 continue;
317 }
Maxim Siniavineca766922013-11-04 16:12:01 -0800318 // skip stats for other uids
319 if (statsEntry.uid != uid) {
320 continue;
321 }
322 if (totalStats == null || statsEntry.set == NetworkStats.SET_ALL) {
323 totalStats = statsEntry;
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700324 } else {
Maxim Siniavineca766922013-11-04 16:12:01 -0800325 totalStats.rxBytes += statsEntry.rxBytes;
326 totalStats.txBytes += statsEntry.txBytes;
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700327 }
328 }
Maxim Siniavineca766922013-11-04 16:12:01 -0800329 // Output merged stats to bundle.
330 results.putInt(label + "uid", totalStats.uid);
331 results.putLong(label + "tx", totalStats.txBytes);
332 results.putLong(label + "rx", totalStats.rxBytes);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700333 }
334
335 /**
336 * Remove file if it exists.
337 * @param file {@link File} to delete.
338 * @return true if successfully deleted the file.
339 */
340 private boolean cleanUpFile(File file) {
341 if (file.exists()) {
342 return file.delete();
343 }
344 return true;
345 }
Tsu Chiang Chuang287353a2011-11-10 10:13:14 -0800346}