blob: 0cc883fe56ea35c7d02bf9729a98a44a7bd4e75e [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;
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -070039import java.util.HashMap;
40import java.util.Map;
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -070041
42/**
43 * Test that downloads files from a test server and reports the bandwidth metrics collected.
44 */
45public class BandwidthTest extends InstrumentationTestCase {
46
47 private static final String LOG_TAG = "BandwidthTest";
48 private final static String PROF_LABEL = "PROF_";
49 private final static String PROC_LABEL = "PROC_";
50 private final static int INSTRUMENTATION_IN_PROGRESS = 2;
51
52 private final static String BASE_DIR =
53 Environment.getExternalStorageDirectory().getAbsolutePath();
54 private final static String TMP_FILENAME = "tmp.dat";
55 // Download 10.486 * 106 bytes (+ headers) from app engine test server.
56 private final int FILE_SIZE = 10485613;
57 private Context mContext;
58 private ConnectionUtil mConnectionUtil;
59 private TelephonyManager mTManager;
60 private int mUid;
61 private String mSsid;
62 private String mTestServer;
63 private String mDeviceId;
64 private BandwidthTestRunner mRunner;
65
66
67 @Override
68 protected void setUp() throws Exception {
69 super.setUp();
70 mRunner = (BandwidthTestRunner) getInstrumentation();
71 mSsid = mRunner.mSsid;
72 mTestServer = mRunner.mTestServer;
73 mContext = mRunner.getTargetContext();
74 mConnectionUtil = new ConnectionUtil(mContext);
75 mConnectionUtil.initialize();
76 Log.v(LOG_TAG, "Initialized mConnectionUtil");
77 mUid = Process.myUid();
78 mTManager = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
79 mDeviceId = mTManager.getDeviceId();
80 }
81
82 @Override
83 protected void tearDown() throws Exception {
84 mConnectionUtil.cleanUp();
85 super.tearDown();
86 }
87
88 /**
89 * Ensure that downloading on wifi reports reasonable stats.
90 */
91 @LargeTest
Jeff Sharkey163e6442011-10-31 16:37:52 -070092 public void testWifiDownload() throws Exception {
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -070093 assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
94 NetworkStats pre_test_stats = fetchDataFromProc(mUid);
95 String ts = Long.toString(System.currentTimeMillis());
96
97 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
98 mTestServer, FILE_SIZE, mDeviceId, ts);
99 TrafficStats.startDataProfiling(mContext);
100 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
101 assertTrue(BandwidthTestUtil.DownloadFromUrl(targetUrl, tmpSaveFile));
102 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700103 Log.d(LOG_TAG, prof_stats.toString());
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700104
105 NetworkStats post_test_stats = fetchDataFromProc(mUid);
106 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
107
108 // Output measurements to instrumentation out, so that it can be compared to that of
109 // the server.
110 Bundle results = new Bundle();
111 results.putString("device_id", mDeviceId);
112 results.putString("timestamp", ts);
113 results.putInt("size", FILE_SIZE);
114 AddStatsToResults(PROF_LABEL, prof_stats, results);
115 AddStatsToResults(PROC_LABEL, proc_stats, results);
116 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
117
118 // Clean up.
119 assertTrue(cleanUpFile(tmpSaveFile));
120 }
121
122 /**
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700123 * Ensure that downloading on wifi reports reasonable stats.
124 */
125 @LargeTest
Jeff Sharkey163e6442011-10-31 16:37:52 -0700126 public void testWifiUpload() throws Exception {
Tsu Chiang Chuange8886852011-09-14 16:10:12 -0700127 assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
128 // Download a file from the server.
129 String ts = Long.toString(System.currentTimeMillis());
130 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
131 mTestServer, FILE_SIZE, mDeviceId, ts);
132 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
133 assertTrue(BandwidthTestUtil.DownloadFromUrl(targetUrl, tmpSaveFile));
134
135 ts = Long.toString(System.currentTimeMillis());
136 NetworkStats pre_test_stats = fetchDataFromProc(mUid);
137 TrafficStats.startDataProfiling(mContext);
138 assertTrue(BandwidthTestUtil.postFileToServer(mTestServer, mDeviceId, ts, tmpSaveFile));
139 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
140 Log.d(LOG_TAG, prof_stats.toString());
141 NetworkStats post_test_stats = fetchDataFromProc(mUid);
142 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
143
144 // Output measurements to instrumentation out, so that it can be compared to that of
145 // the server.
146 Bundle results = new Bundle();
147 results.putString("device_id", mDeviceId);
148 results.putString("timestamp", ts);
149 results.putInt("size", FILE_SIZE);
150 AddStatsToResults(PROF_LABEL, prof_stats, results);
151 AddStatsToResults(PROC_LABEL, proc_stats, results);
152 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
153
154 // Clean up.
155 assertTrue(cleanUpFile(tmpSaveFile));
156 }
157
158 /**
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700159 * We want to make sure that if we use the Download Manager to download stuff,
160 * accounting still goes to the app making the call and that the numbers still make sense.
161 */
162 @LargeTest
Jeff Sharkey163e6442011-10-31 16:37:52 -0700163 public void testWifiDownloadWithDownloadManager() throws Exception {
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700164 assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
165 // If we are using the download manager, then the data that is written to /proc/uid_stat/
166 // is accounted against download manager's uid, since it uses pre-ICS API.
167 int downloadManagerUid = mConnectionUtil.downloadManagerUid();
168 assertTrue(downloadManagerUid >= 0);
169 NetworkStats pre_test_stats = fetchDataFromProc(downloadManagerUid);
170 // start profiling
171 TrafficStats.startDataProfiling(mContext);
172 String ts = Long.toString(System.currentTimeMillis());
173 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
174 mTestServer, FILE_SIZE, mDeviceId, ts);
175 Log.v(LOG_TAG, "Download url: " + targetUrl);
176 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
177 assertTrue(mConnectionUtil.startDownloadAndWait(targetUrl, 500000));
178 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
179 NetworkStats post_test_stats = fetchDataFromProc(downloadManagerUid);
180 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700181 Log.d(LOG_TAG, prof_stats.toString());
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700182 // Output measurements to instrumentation out, so that it can be compared to that of
183 // the server.
184 Bundle results = new Bundle();
185 results.putString("device_id", mDeviceId);
186 results.putString("timestamp", ts);
187 results.putInt("size", FILE_SIZE);
188 AddStatsToResults(PROF_LABEL, prof_stats, results);
189 AddStatsToResults(PROC_LABEL, proc_stats, results);
190 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
191
192 // Clean up.
193 assertTrue(cleanUpFile(tmpSaveFile));
194 }
195
196 /**
197 * Fetch network data from /proc/uid_stat/uid
198 * @return populated {@link NetworkStats}
199 */
200 public NetworkStats fetchDataFromProc(int uid) {
201 String root_filepath = "/proc/uid_stat/" + uid + "/";
202 File rcv_stat = new File (root_filepath + "tcp_rcv");
203 int rx = BandwidthTestUtil.parseIntValueFromFile(rcv_stat);
204 File snd_stat = new File (root_filepath + "tcp_snd");
205 int tx = BandwidthTestUtil.parseIntValueFromFile(snd_stat);
206 NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700207 stats.addValues(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
208 NetworkStats.TAG_NONE, rx, 0, tx, 0, 0);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700209 return stats;
210 }
211
212 /**
213 * Turn on Airplane mode and connect to the wifi
214 * @param ssid of the wifi to connect to
215 * @return true if we successfully connected to a given network.
216 */
217 public boolean setDeviceWifiAndAirplaneMode(String ssid) {
218 mConnectionUtil.setAirplaneMode(mContext, true);
219 assertTrue(mConnectionUtil.connectToWifi(ssid));
220 assertTrue(mConnectionUtil.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
221 ConnectionUtil.LONG_TIMEOUT));
222 return mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
223 ConnectionUtil.LONG_TIMEOUT);
224 }
225
226 /**
227 * Output the {@link NetworkStats} to Instrumentation out.
228 * @param label to attach to this given stats.
229 * @param stats {@link NetworkStats} to add.
230 * @param results {@link Bundle} to be added to.
231 */
232 public void AddStatsToResults(String label, NetworkStats stats, Bundle results){
233 if (results == null || results.isEmpty()) {
234 Log.e(LOG_TAG, "Empty bundle provided.");
235 return;
236 }
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700237 // Merge stats across all sets.
238 Map<Integer, Entry> totalStats = new HashMap<Integer, Entry>();
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700239 for (int i = 0; i < stats.size(); ++i) {
Tsu Chiang Chuang6951b1b2011-08-17 16:21:58 -0700240 Entry statsEntry = stats.getValues(i, null);
241 // We are only interested in the all inclusive stats.
242 if (statsEntry.tag != 0) {
243 continue;
244 }
245 Entry mapEntry = null;
246 if (totalStats.containsKey(statsEntry.uid)) {
247 mapEntry = totalStats.get(statsEntry.uid);
248 switch (statsEntry.set) {
249 case NetworkStats.SET_ALL:
250 mapEntry.rxBytes = statsEntry.rxBytes;
251 mapEntry.txBytes = statsEntry.txBytes;
252 break;
253 case NetworkStats.SET_DEFAULT:
254 case NetworkStats.SET_FOREGROUND:
255 mapEntry.rxBytes += statsEntry.rxBytes;
256 mapEntry.txBytes += statsEntry.txBytes;
257 break;
258 default:
259 Log.w(LOG_TAG, "Invalid state found in NetworkStats.");
260 }
261 } else {
262 totalStats.put(statsEntry.uid, statsEntry);
263 }
264 }
265 // Ouput merged stats to bundle.
266 for (Entry entry : totalStats.values()) {
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700267 results.putInt(label + "uid", entry.uid);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700268 results.putLong(label + "tx", entry.txBytes);
269 results.putLong(label + "rx", entry.rxBytes);
270 }
271 }
272
273 /**
274 * Remove file if it exists.
275 * @param file {@link File} to delete.
276 * @return true if successfully deleted the file.
277 */
278 private boolean cleanUpFile(File file) {
279 if (file.exists()) {
280 return file.delete();
281 }
282 return true;
283 }
284}