blob: 4b42f4ae9888209e095cdb6d376be91681cf39ee [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
Michael Groover6d20d752018-10-01 16:14:50 -070019import android.app.UiAutomation;
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -070020import android.content.Context;
21import android.net.ConnectivityManager;
22import android.net.NetworkInfo.State;
23import android.net.NetworkStats;
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -070024import android.net.NetworkStats.Entry;
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -070025import android.net.TrafficStats;
26import android.net.wifi.WifiManager;
27import android.os.Bundle;
28import android.os.Environment;
29import android.os.Process;
30import android.os.SystemClock;
31import android.telephony.TelephonyManager;
32import android.test.InstrumentationTestCase;
33import android.test.suitebuilder.annotation.LargeTest;
34import android.util.Log;
35
36import com.android.bandwidthtest.util.BandwidthTestUtil;
37import com.android.bandwidthtest.util.ConnectionUtil;
38
39import java.io.File;
40
41/**
42 * Test that downloads files from a test server and reports the bandwidth metrics collected.
43 */
44public class BandwidthTest extends InstrumentationTestCase {
45
46 private static final String LOG_TAG = "BandwidthTest";
47 private final static String PROF_LABEL = "PROF_";
48 private final static String PROC_LABEL = "PROC_";
49 private final static int INSTRUMENTATION_IN_PROGRESS = 2;
50
51 private final static String BASE_DIR =
52 Environment.getExternalStorageDirectory().getAbsolutePath();
53 private final static String TMP_FILENAME = "tmp.dat";
54 // Download 10.486 * 106 bytes (+ headers) from app engine test server.
55 private final int FILE_SIZE = 10485613;
56 private Context mContext;
57 private ConnectionUtil mConnectionUtil;
58 private TelephonyManager mTManager;
59 private int mUid;
60 private String mSsid;
61 private String mTestServer;
62 private String mDeviceId;
63 private BandwidthTestRunner mRunner;
64
65
66 @Override
67 protected void setUp() throws Exception {
68 super.setUp();
69 mRunner = (BandwidthTestRunner) getInstrumentation();
70 mSsid = mRunner.mSsid;
71 mTestServer = mRunner.mTestServer;
72 mContext = mRunner.getTargetContext();
73 mConnectionUtil = new ConnectionUtil(mContext);
74 mConnectionUtil.initialize();
75 Log.v(LOG_TAG, "Initialized mConnectionUtil");
76 mUid = Process.myUid();
77 mTManager = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
Michael Groover6d20d752018-10-01 16:14:50 -070078 final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
79 try {
80 uiAutomation.adoptShellPermissionIdentity();
81 mDeviceId = mTManager.getDeviceId();
82 } finally {
83 uiAutomation.dropShellPermissionIdentity();
84 }
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -070085 }
86
87 @Override
88 protected void tearDown() throws Exception {
89 mConnectionUtil.cleanUp();
90 super.tearDown();
91 }
92
93 /**
94 * Ensure that downloading on wifi reports reasonable stats.
95 */
96 @LargeTest
Jeff Sharkey163e6442011-10-31 16:37:52 -070097 public void testWifiDownload() throws Exception {
Tsu Chiang Chuanga8c57bf2012-02-01 15:24:51 -080098 mConnectionUtil.wifiTestInit();
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -080099 assertTrue("Could not connect to wifi!", setDeviceWifiAndAirplaneMode(mSsid));
100 downloadFile();
101 }
102
103 /**
104 * Ensure that downloading on mobile reports reasonable stats.
105 */
106 @LargeTest
107 public void testMobileDownload() throws Exception {
108 // As part of the setup we disconnected from wifi; make sure we are connected to mobile and
109 // that we have data.
110 assertTrue("Do not have mobile data!", hasMobileData());
111 downloadFile();
112 }
113
114 /**
115 * Helper method that downloads a file using http connection from a test server and reports the
116 * data usage stats to instrumentation out.
117 */
118 protected void downloadFile() throws Exception {
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700119 NetworkStats pre_test_stats = fetchDataFromProc(mUid);
120 String ts = Long.toString(System.currentTimeMillis());
121
122 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
123 mTestServer, FILE_SIZE, mDeviceId, ts);
124 TrafficStats.startDataProfiling(mContext);
125 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
126 assertTrue(BandwidthTestUtil.DownloadFromUrl(targetUrl, tmpSaveFile));
127 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700128 Log.d(LOG_TAG, prof_stats.toString());
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700129
130 NetworkStats post_test_stats = fetchDataFromProc(mUid);
131 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
132
133 // Output measurements to instrumentation out, so that it can be compared to that of
134 // the server.
135 Bundle results = new Bundle();
136 results.putString("device_id", mDeviceId);
137 results.putString("timestamp", ts);
138 results.putInt("size", FILE_SIZE);
Maxim Siniavineca766922013-11-04 16:12:01 -0800139 addStatsToResults(PROF_LABEL, prof_stats, results, mUid);
140 addStatsToResults(PROC_LABEL, proc_stats, results, mUid);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700141 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
142
143 // Clean up.
144 assertTrue(cleanUpFile(tmpSaveFile));
145 }
146
147 /**
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800148 * Ensure that uploading on wifi reports reasonable stats.
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700149 */
150 @LargeTest
Jeff Sharkey163e6442011-10-31 16:37:52 -0700151 public void testWifiUpload() throws Exception {
Tsu Chiang Chuanga8c57bf2012-02-01 15:24:51 -0800152 mConnectionUtil.wifiTestInit();
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700153 assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800154 uploadFile();
155 }
156
157 /**
158 * Ensure that uploading on wifi reports reasonable stats.
159 */
160 @LargeTest
161 public void testMobileUpload() throws Exception {
162 assertTrue(hasMobileData());
163 uploadFile();
164 }
165
166 /**
167 * Helper method that downloads a test file to upload. The stats reported to instrumentation out
168 * only include upload stats.
169 */
170 protected void uploadFile() throws Exception {
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700171 // Download a file from the server.
172 String ts = Long.toString(System.currentTimeMillis());
173 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
174 mTestServer, FILE_SIZE, mDeviceId, ts);
175 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
176 assertTrue(BandwidthTestUtil.DownloadFromUrl(targetUrl, tmpSaveFile));
177
178 ts = Long.toString(System.currentTimeMillis());
179 NetworkStats pre_test_stats = fetchDataFromProc(mUid);
180 TrafficStats.startDataProfiling(mContext);
181 assertTrue(BandwidthTestUtil.postFileToServer(mTestServer, mDeviceId, ts, tmpSaveFile));
182 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
183 Log.d(LOG_TAG, prof_stats.toString());
184 NetworkStats post_test_stats = fetchDataFromProc(mUid);
185 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
186
187 // Output measurements to instrumentation out, so that it can be compared to that of
188 // the server.
189 Bundle results = new Bundle();
190 results.putString("device_id", mDeviceId);
191 results.putString("timestamp", ts);
192 results.putInt("size", FILE_SIZE);
Maxim Siniavineca766922013-11-04 16:12:01 -0800193 addStatsToResults(PROF_LABEL, prof_stats, results, mUid);
194 addStatsToResults(PROC_LABEL, proc_stats, results, mUid);
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700195 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
196
197 // Clean up.
198 assertTrue(cleanUpFile(tmpSaveFile));
199 }
200
201 /**
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800202 * 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 -0700203 * accounting still goes to the app making the call and that the numbers still make sense.
204 */
205 @LargeTest
Jeff Sharkey163e6442011-10-31 16:37:52 -0700206 public void testWifiDownloadWithDownloadManager() throws Exception {
Tsu Chiang Chuanga8c57bf2012-02-01 15:24:51 -0800207 mConnectionUtil.wifiTestInit();
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700208 assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800209 downloadFileUsingDownloadManager();
210 }
211
212 /**
213 * We want to make sure that if we use mobile data and the Download Manager to download stuff,
214 * accounting still goes to the app making the call and that the numbers still make sense.
215 */
216 @LargeTest
217 public void testMobileDownloadWithDownloadManager() throws Exception {
218 assertTrue(hasMobileData());
219 downloadFileUsingDownloadManager();
220 }
221
222 /**
223 * Helper method that downloads a file from a test server using the download manager and reports
224 * the stats to instrumentation out.
225 */
226 protected void downloadFileUsingDownloadManager() throws Exception {
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700227 // If we are using the download manager, then the data that is written to /proc/uid_stat/
228 // is accounted against download manager's uid, since it uses pre-ICS API.
229 int downloadManagerUid = mConnectionUtil.downloadManagerUid();
230 assertTrue(downloadManagerUid >= 0);
231 NetworkStats pre_test_stats = fetchDataFromProc(downloadManagerUid);
232 // start profiling
233 TrafficStats.startDataProfiling(mContext);
234 String ts = Long.toString(System.currentTimeMillis());
235 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
236 mTestServer, FILE_SIZE, mDeviceId, ts);
237 Log.v(LOG_TAG, "Download url: " + targetUrl);
238 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
239 assertTrue(mConnectionUtil.startDownloadAndWait(targetUrl, 500000));
240 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
241 NetworkStats post_test_stats = fetchDataFromProc(downloadManagerUid);
242 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700243 Log.d(LOG_TAG, prof_stats.toString());
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700244 // Output measurements to instrumentation out, so that it can be compared to that of
245 // the server.
246 Bundle results = new Bundle();
247 results.putString("device_id", mDeviceId);
248 results.putString("timestamp", ts);
249 results.putInt("size", FILE_SIZE);
Maxim Siniavineca766922013-11-04 16:12:01 -0800250 addStatsToResults(PROF_LABEL, prof_stats, results, mUid);
251 // remember to use download manager uid for proc stats
252 addStatsToResults(PROC_LABEL, proc_stats, results, downloadManagerUid);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700253 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
254
255 // Clean up.
256 assertTrue(cleanUpFile(tmpSaveFile));
257 }
258
259 /**
260 * Fetch network data from /proc/uid_stat/uid
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800261 *
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700262 * @return populated {@link NetworkStats}
263 */
264 public NetworkStats fetchDataFromProc(int uid) {
265 String root_filepath = "/proc/uid_stat/" + uid + "/";
266 File rcv_stat = new File (root_filepath + "tcp_rcv");
267 int rx = BandwidthTestUtil.parseIntValueFromFile(rcv_stat);
268 File snd_stat = new File (root_filepath + "tcp_snd");
269 int tx = BandwidthTestUtil.parseIntValueFromFile(snd_stat);
270 NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
junyulai88f89a02020-03-13 19:04:17 +0800271 stats.insertEntry(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700272 NetworkStats.TAG_NONE, rx, 0, tx, 0, 0);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700273 return stats;
274 }
275
276 /**
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800277 * Turn on Airplane mode and connect to the wifi.
278 *
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700279 * @param ssid of the wifi to connect to
280 * @return true if we successfully connected to a given network.
281 */
282 public boolean setDeviceWifiAndAirplaneMode(String ssid) {
283 mConnectionUtil.setAirplaneMode(mContext, true);
284 assertTrue(mConnectionUtil.connectToWifi(ssid));
285 assertTrue(mConnectionUtil.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
286 ConnectionUtil.LONG_TIMEOUT));
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800287 assertTrue(mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
288 State.CONNECTED, ConnectionUtil.LONG_TIMEOUT));
289 return mConnectionUtil.hasData();
290 }
291
292 /**
293 * Helper method to make sure we are connected to mobile data.
294 *
295 * @return true if we successfully connect to mobile data.
296 */
297 public boolean hasMobileData() {
Tsu Chiang Chuanga8c57bf2012-02-01 15:24:51 -0800298 assertTrue(mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_MOBILE,
299 State.CONNECTED, ConnectionUtil.LONG_TIMEOUT));
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800300 assertTrue("Not connected to mobile", mConnectionUtil.isConnectedToMobile());
301 assertFalse("Still connected to wifi.", mConnectionUtil.isConnectedToWifi());
302 return mConnectionUtil.hasData();
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700303 }
304
305 /**
306 * Output the {@link NetworkStats} to Instrumentation out.
Tsu Chiang Chuang212efac2011-11-07 11:52:08 -0800307 *
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700308 * @param label to attach to this given stats.
309 * @param stats {@link NetworkStats} to add.
310 * @param results {@link Bundle} to be added to.
Maxim Siniavineca766922013-11-04 16:12:01 -0800311 * @param uid for which to report the results.
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700312 */
Maxim Siniavineca766922013-11-04 16:12:01 -0800313 public void addStatsToResults(String label, NetworkStats stats, Bundle results, int uid){
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700314 if (results == null || results.isEmpty()) {
315 Log.e(LOG_TAG, "Empty bundle provided.");
316 return;
317 }
Maxim Siniavineca766922013-11-04 16:12:01 -0800318 Entry totalStats = null;
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700319 for (int i = 0; i < stats.size(); ++i) {
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700320 Entry statsEntry = stats.getValues(i, null);
321 // We are only interested in the all inclusive stats.
322 if (statsEntry.tag != 0) {
323 continue;
324 }
Maxim Siniavineca766922013-11-04 16:12:01 -0800325 // skip stats for other uids
326 if (statsEntry.uid != uid) {
327 continue;
328 }
329 if (totalStats == null || statsEntry.set == NetworkStats.SET_ALL) {
330 totalStats = statsEntry;
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700331 } else {
Maxim Siniavineca766922013-11-04 16:12:01 -0800332 totalStats.rxBytes += statsEntry.rxBytes;
333 totalStats.txBytes += statsEntry.txBytes;
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700334 }
335 }
Maxim Siniavineca766922013-11-04 16:12:01 -0800336 // Output merged stats to bundle.
337 results.putInt(label + "uid", totalStats.uid);
338 results.putLong(label + "tx", totalStats.txBytes);
339 results.putLong(label + "rx", totalStats.rxBytes);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700340 }
341
342 /**
343 * Remove file if it exists.
344 * @param file {@link File} to delete.
345 * @return true if successfully deleted the file.
346 */
347 private boolean cleanUpFile(File file) {
348 if (file.exists()) {
349 return file.delete();
350 }
351 return true;
352 }
Tsu Chiang Chuang287353a2011-11-10 10:13:14 -0800353}