BandwidthTest.java revision 33f869951fde247927e66c3aa4ab86fc61f783ad
1/* 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); 167 stats.addValues(NetworkStats.IFACE_ALL, uid, NetworkStats.TAG_NONE, rx, 0, tx, 0); 168 return stats; 169 } 170 171 /** 172 * Turn on Airplane mode and connect to the wifi 173 * @param ssid of the wifi to connect to 174 * @return true if we successfully connected to a given network. 175 */ 176 public boolean setDeviceWifiAndAirplaneMode(String ssid) { 177 mConnectionUtil.setAirplaneMode(mContext, true); 178 assertTrue(mConnectionUtil.connectToWifi(ssid)); 179 assertTrue(mConnectionUtil.waitForWifiState(WifiManager.WIFI_STATE_ENABLED, 180 ConnectionUtil.LONG_TIMEOUT)); 181 return mConnectionUtil.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED, 182 ConnectionUtil.LONG_TIMEOUT); 183 } 184 185 /** 186 * Output the {@link NetworkStats} to Instrumentation out. 187 * @param label to attach to this given stats. 188 * @param stats {@link NetworkStats} to add. 189 * @param results {@link Bundle} to be added to. 190 */ 191 public void AddStatsToResults(String label, NetworkStats stats, Bundle results){ 192 if (results == null || results.isEmpty()) { 193 Log.e(LOG_TAG, "Empty bundle provided."); 194 return; 195 } 196 for (int i = 0; i < stats.size(); ++i) { 197 android.net.NetworkStats.Entry entry = stats.getValues(i, null); 198 results.putInt(label + "uid", entry.uid); 199 results.putString(label + "iface", entry.iface); 200 results.putInt(label + "tag", entry.tag); 201 results.putLong(label + "tx", entry.txBytes); 202 results.putLong(label + "rx", entry.rxBytes); 203 } 204 } 205 206 /** 207 * Remove file if it exists. 208 * @param file {@link File} to delete. 209 * @return true if successfully deleted the file. 210 */ 211 private boolean cleanUpFile(File file) { 212 if (file.exists()) { 213 return file.delete(); 214 } 215 return true; 216 } 217}