blob: 5ee8fdd9b50ff803cfca968ca0c69d7040871802 [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;
23import android.net.TrafficStats;
24import android.net.wifi.WifiManager;
25import android.os.Bundle;
26import android.os.Environment;
27import android.os.Process;
28import android.os.SystemClock;
29import android.telephony.TelephonyManager;
30import android.test.InstrumentationTestCase;
31import android.test.suitebuilder.annotation.LargeTest;
32import android.util.Log;
33
34import com.android.bandwidthtest.util.BandwidthTestUtil;
35import com.android.bandwidthtest.util.ConnectionUtil;
36
37import java.io.File;
38
39/**
40 * Test that downloads files from a test server and reports the bandwidth metrics collected.
41 */
42public class BandwidthTest extends InstrumentationTestCase {
43
44 private static final String LOG_TAG = "BandwidthTest";
45 private final static String PROF_LABEL = "PROF_";
46 private final static String PROC_LABEL = "PROC_";
47 private final static int INSTRUMENTATION_IN_PROGRESS = 2;
48
49 private final static String BASE_DIR =
50 Environment.getExternalStorageDirectory().getAbsolutePath();
51 private final static String TMP_FILENAME = "tmp.dat";
52 // Download 10.486 * 106 bytes (+ headers) from app engine test server.
53 private final int FILE_SIZE = 10485613;
54 private Context mContext;
55 private ConnectionUtil mConnectionUtil;
56 private TelephonyManager mTManager;
57 private int mUid;
58 private String mSsid;
59 private String mTestServer;
60 private String mDeviceId;
61 private BandwidthTestRunner mRunner;
62
63
64 @Override
65 protected void setUp() throws Exception {
66 super.setUp();
67 mRunner = (BandwidthTestRunner) getInstrumentation();
68 mSsid = mRunner.mSsid;
69 mTestServer = mRunner.mTestServer;
70 mContext = mRunner.getTargetContext();
71 mConnectionUtil = new ConnectionUtil(mContext);
72 mConnectionUtil.initialize();
73 Log.v(LOG_TAG, "Initialized mConnectionUtil");
74 mUid = Process.myUid();
75 mTManager = (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
76 mDeviceId = mTManager.getDeviceId();
77 }
78
79 @Override
80 protected void tearDown() throws Exception {
81 mConnectionUtil.cleanUp();
82 super.tearDown();
83 }
84
85 /**
86 * Ensure that downloading on wifi reports reasonable stats.
87 */
88 @LargeTest
89 public void testWifiDownload() {
90 assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
91 NetworkStats pre_test_stats = fetchDataFromProc(mUid);
92 String ts = Long.toString(System.currentTimeMillis());
93
94 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
95 mTestServer, FILE_SIZE, mDeviceId, ts);
96 TrafficStats.startDataProfiling(mContext);
97 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
98 assertTrue(BandwidthTestUtil.DownloadFromUrl(targetUrl, tmpSaveFile));
99 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
100
101 NetworkStats post_test_stats = fetchDataFromProc(mUid);
102 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
103
104 // Output measurements to instrumentation out, so that it can be compared to that of
105 // the server.
106 Bundle results = new Bundle();
107 results.putString("device_id", mDeviceId);
108 results.putString("timestamp", ts);
109 results.putInt("size", FILE_SIZE);
110 AddStatsToResults(PROF_LABEL, prof_stats, results);
111 AddStatsToResults(PROC_LABEL, proc_stats, results);
112 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
113
114 // Clean up.
115 assertTrue(cleanUpFile(tmpSaveFile));
116 }
117
118 /**
119 * We want to make sure that if we use the Download Manager to download stuff,
120 * accounting still goes to the app making the call and that the numbers still make sense.
121 */
122 @LargeTest
123 public void testWifiDownloadWithDownloadManager() {
124 assertTrue(setDeviceWifiAndAirplaneMode(mSsid));
125 // If we are using the download manager, then the data that is written to /proc/uid_stat/
126 // is accounted against download manager's uid, since it uses pre-ICS API.
127 int downloadManagerUid = mConnectionUtil.downloadManagerUid();
128 assertTrue(downloadManagerUid >= 0);
129 NetworkStats pre_test_stats = fetchDataFromProc(downloadManagerUid);
130 // start profiling
131 TrafficStats.startDataProfiling(mContext);
132 String ts = Long.toString(System.currentTimeMillis());
133 String targetUrl = BandwidthTestUtil.buildDownloadUrl(
134 mTestServer, FILE_SIZE, mDeviceId, ts);
135 Log.v(LOG_TAG, "Download url: " + targetUrl);
136 File tmpSaveFile = new File(BASE_DIR + File.separator + TMP_FILENAME);
137 assertTrue(mConnectionUtil.startDownloadAndWait(targetUrl, 500000));
138 NetworkStats prof_stats = TrafficStats.stopDataProfiling(mContext);
139 NetworkStats post_test_stats = fetchDataFromProc(downloadManagerUid);
140 NetworkStats proc_stats = post_test_stats.subtract(pre_test_stats);
141
142 // Output measurements to instrumentation out, so that it can be compared to that of
143 // the server.
144 Bundle results = new Bundle();
145 results.putString("device_id", mDeviceId);
146 results.putString("timestamp", ts);
147 results.putInt("size", FILE_SIZE);
148 AddStatsToResults(PROF_LABEL, prof_stats, results);
149 AddStatsToResults(PROC_LABEL, proc_stats, results);
150 getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results);
151
152 // Clean up.
153 assertTrue(cleanUpFile(tmpSaveFile));
154 }
155
156 /**
157 * Fetch network data from /proc/uid_stat/uid
158 * @return populated {@link NetworkStats}
159 */
160 public NetworkStats fetchDataFromProc(int uid) {
161 String root_filepath = "/proc/uid_stat/" + uid + "/";
162 File rcv_stat = new File (root_filepath + "tcp_rcv");
163 int rx = BandwidthTestUtil.parseIntValueFromFile(rcv_stat);
164 File snd_stat = new File (root_filepath + "tcp_snd");
165 int tx = BandwidthTestUtil.parseIntValueFromFile(snd_stat);
166 NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700167 stats.addValues(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
168 NetworkStats.TAG_NONE, rx, 0, tx, 0, 0);
Tsu Chiang Chuang33f86992011-07-27 15:51:49 -0700169 return stats;
170 }
171
172 /**
173 * Turn on Airplane mode and connect to the wifi
174 * @param ssid of the wifi to connect to
175 * @return true if we successfully connected to a given network.
176 */
177 public boolean setDeviceWifiAndAirplaneMode(String ssid) {
178 mConnectionUtil.setAirplaneMode(mContext, true);
179 assertTrue(mConnectionUtil.connectToWifi(ssid));
180 assertTrue(mConnectionUtil.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
181 ConnectionUtil.LONG_TIMEOUT));
182 return mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
183 ConnectionUtil.LONG_TIMEOUT);
184 }
185
186 /**
187 * Output the {@link NetworkStats} to Instrumentation out.
188 * @param label to attach to this given stats.
189 * @param stats {@link NetworkStats} to add.
190 * @param results {@link Bundle} to be added to.
191 */
192 public void AddStatsToResults(String label, NetworkStats stats, Bundle results){
193 if (results == null || results.isEmpty()) {
194 Log.e(LOG_TAG, "Empty bundle provided.");
195 return;
196 }
197 for (int i = 0; i < stats.size(); ++i) {
198 android.net.NetworkStats.Entry entry = stats.getValues(i, null);
199 results.putInt(label + "uid", entry.uid);
200 results.putString(label + "iface", entry.iface);
201 results.putInt(label + "tag", entry.tag);
202 results.putLong(label + "tx", entry.txBytes);
203 results.putLong(label + "rx", entry.rxBytes);
204 }
205 }
206
207 /**
208 * Remove file if it exists.
209 * @param file {@link File} to delete.
210 * @return true if successfully deleted the file.
211 */
212 private boolean cleanUpFile(File file) {
213 if (file.exists()) {
214 return file.delete();
215 }
216 return true;
217 }
218}