1 /* 2 * Copyright (C) 2012 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 17 package com.android.tradefed.utils.wifi; 18 import android.app.Activity; 19 import android.app.Instrumentation; 20 import android.content.Context; 21 import android.net.wifi.WifiInfo; 22 import android.net.wifi.WifiManager; 23 import android.os.Bundle; 24 import android.text.TextUtils; 25 import android.util.Log; 26 27 import com.android.tradefed.utils.wifi.WifiConnector.WifiException; 28 29 /** 30 * An instrumentation class to manipulate Wi-Fi services on device. 31 * <p/> 32 * adb shell am instrument -e method (method name) -e arg1 val1 -e arg2 val2 -e arg3 val3 33 * -w com.android.tradefed.utils.wifi/.WifiUtils 34 */ 35 public class WifiUtil extends Instrumentation { 36 // FIXME: document exposed API methods and arguments 37 private static final String TAG = "WifiUtil"; 38 39 private static final String DEFAULT_URL_TO_CHECK = "http://www.google.com"; 40 41 private Bundle mArguments; 42 43 static class MissingArgException extends Exception { 44 public MissingArgException(String msg) { 45 super(msg); 46 } 47 48 public static MissingArgException fromArg(String arg) { 49 return new MissingArgException( 50 String.format("Error: missing mandatory argument '%s'", arg)); 51 } 52 } 53 54 @Override 55 public void onCreate(Bundle arguments) { 56 super.onCreate(arguments); 57 mArguments = arguments; 58 start(); 59 } 60 61 /** 62 * Fails an instrumentation request. 63 * 64 * @param errMsg an error message 65 */ 66 private void fail(String errMsg) { 67 Log.e(TAG, errMsg); 68 Bundle result = new Bundle(); 69 result.putString("error", errMsg); 70 finish(Activity.RESULT_CANCELED, result); 71 } 72 73 /** 74 * Returns the string value of an argument for the specified name, or throws 75 * {@link MissingArgException} if the argument is not found or empty. 76 * 77 * @param arg the name of an argument 78 * @return the value of an argument 79 * @throws MissingArgException if the argument is not found 80 */ 81 private String expectString(String arg) throws MissingArgException { 82 String val = mArguments.getString(arg); 83 if (TextUtils.isEmpty(val)) { 84 throw MissingArgException.fromArg(arg); 85 } 86 87 return val; 88 } 89 90 /** 91 * Returns the value of a string argument for the specified name, or defaultValue if the 92 * argument is not found or empty. 93 * 94 * @param arg the name of an argument 95 * @param defaultValue a value to return if the argument is not found 96 * @return the value of an argument 97 */ 98 private String getString(String arg, String defaultValue) { 99 String val = mArguments.getString(arg); 100 if (TextUtils.isEmpty(val)) { 101 return defaultValue; 102 } 103 104 return val; 105 } 106 107 /** 108 * Returns the integer value of an argument for the specified name, or throws 109 * {@link MissingArgException} if the argument is not found or cannot be parsed to an integer. 110 * 111 * @param arg the name of an argument 112 * @return the value of an argument 113 * @throws MissingArgException if the argument is not found 114 */ 115 private int expectInteger(String arg) throws MissingArgException { 116 String val = expectString(arg); 117 int intVal; 118 try { 119 intVal = Integer.parseInt(val); 120 } catch (NumberFormatException e) { 121 final String msg = String.format("Couldn't parse arg '%s': %s", arg, 122 e.getMessage()); 123 throw new MissingArgException(msg); 124 } 125 126 return intVal; 127 } 128 129 /** 130 * Returns the integer value of an argument for the specified name, or defaultValue if the 131 * argument is not found, empty, or cannot be parsed. 132 * 133 * @param arg the name of an argument 134 * @param defaultValue a value to return if the argument is not found 135 * @return the value of an argument 136 */ 137 private int getInteger(String arg, int defaultValue) { 138 try { 139 return expectInteger(arg); 140 } catch (MissingArgException e) { 141 return defaultValue; 142 } 143 } 144 145 private boolean getBoolean(String arg, boolean defaultValue) { 146 try { 147 return Boolean.parseBoolean(expectString(arg)); 148 } catch (MissingArgException e) { 149 return defaultValue; 150 } 151 } 152 153 @Override 154 public void onStart() { 155 super.onStart(); 156 final Bundle result = new Bundle(); 157 158 try { 159 final String method = expectString("method"); 160 161 WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); 162 if (wifiManager == null) { 163 fail("Couldn't get WifiManager reference; goodbye!"); 164 return; 165 } 166 WifiConnector connector = new WifiConnector(getContext()); 167 168 // As a pattern, method implementations below should gather arguments _first_, and then 169 // use those arguments so that the system is not left in an inconsistent state if an 170 // argument is missing in the middle of an implementation. 171 if ("enableWifi".equals(method)) { 172 result.putBoolean("result", wifiManager.setWifiEnabled(true)); 173 } else if ("disableWifi".equals(method)) { 174 result.putBoolean("result", wifiManager.setWifiEnabled(false)); 175 } else if ("addOpenNetwork".equals(method)) { 176 final String ssid = expectString("ssid"); 177 final boolean scanSsid = getBoolean("scan_ssid", false); 178 179 result.putInt("result", connector.addNetwork(ssid, null, scanSsid)); 180 181 } else if ("addWpaPskNetwork".equals(method)) { 182 final String ssid = expectString("ssid"); 183 final boolean scanSsid = getBoolean("scan_ssid", false); 184 final String psk = expectString("psk"); 185 186 result.putInt("result", connector.addNetwork(ssid, psk, scanSsid)); 187 188 } else if ("associateNetwork".equals(method)) { 189 final int id = expectInteger("id"); 190 191 result.putBoolean("result", 192 wifiManager.enableNetwork(id, true /* disable other networks */)); 193 194 } else if ("disconnect".equals(method)) { 195 result.putBoolean("result", wifiManager.disconnect()); 196 197 } else if ("disableNetwork".equals(method)) { 198 final int id = expectInteger("id"); 199 200 result.putBoolean("result", wifiManager.disableNetwork(id)); 201 202 } else if ("isWifiEnabled".equals(method)) { 203 result.putBoolean("result", wifiManager.isWifiEnabled()); 204 205 } else if ("getIpAddress".equals(method)) { 206 final WifiInfo info = wifiManager.getConnectionInfo(); 207 final int addr = info.getIpAddress(); 208 209 // IP address is stored with the first octet in the lowest byte 210 final int a = (addr >> 0) & 0xff; 211 final int b = (addr >> 8) & 0xff; 212 final int c = (addr >> 16) & 0xff; 213 final int d = (addr >> 24) & 0xff; 214 215 result.putString("result", String.format("%s.%s.%s.%s", a, b, c, d)); 216 217 } else if ("getSSID".equals(method)) { 218 final WifiInfo info = wifiManager.getConnectionInfo(); 219 220 result.putString("result", info.getSSID()); 221 222 } else if ("getBSSID".equals(method)) { 223 final WifiInfo info = wifiManager.getConnectionInfo(); 224 225 result.putString("result", info.getBSSID()); 226 227 } else if ("removeAllNetworks".equals(method)) { 228 connector.removeAllNetworks(true); 229 230 result.putBoolean("result", true); 231 232 } else if ("removeNetwork".equals(method)) { 233 final int id = expectInteger("id"); 234 235 result.putBoolean("result", wifiManager.removeNetwork(id)); 236 237 } else if ("saveConfiguration".equals(method)) { 238 result.putBoolean("result", wifiManager.saveConfiguration()); 239 240 } else if ("getSupplicantState".equals(method)) { 241 String state = wifiManager.getConnectionInfo().getSupplicantState().name(); 242 result.putString("result", state); 243 244 } else if ("checkConnectivity".equals(method)) { 245 final String url = getString("urlToCheck", DEFAULT_URL_TO_CHECK); 246 247 result.putBoolean("result", connector.checkConnectivity(url)); 248 249 } else if ("connectToNetwork".equals(method)) { 250 final String ssid = expectString("ssid"); 251 final boolean scanSsid = getBoolean("scan_ssid", false); 252 final String psk = getString("psk", null); 253 final String pingUrl = getString("urlToCheck", DEFAULT_URL_TO_CHECK); 254 final long connectTimeout = getInteger("connectTimeout", -1); 255 connector.connectToNetwork(ssid, psk, pingUrl, connectTimeout, scanSsid); 256 257 result.putBoolean("result", true); 258 259 } else if ("disconnectFromNetwork".equals(method)) { 260 connector.disconnectFromNetwork(); 261 262 result.putBoolean("result", true); 263 264 } else if ("getWifiInfo".equals(method)) { 265 result.putString("result", connector.getWifiInfo().toString()); 266 267 } else if ("startMonitor".equals(method)) { 268 final int interval = expectInteger("interval"); 269 final String urlToCheck = getString("urlToCheck", DEFAULT_URL_TO_CHECK); 270 271 WifiMonitorService.enable(getContext(), interval, urlToCheck); 272 273 result.putBoolean("result", true); 274 275 } else if ("stopMonitor".equals(method)) { 276 final Context context = getContext(); 277 WifiMonitorService.disable(context); 278 279 result.putString("result", WifiMonitorService.getData(context)); 280 281 } else { 282 fail(String.format("Didn't recognize method '%s'", method)); 283 return; 284 } 285 } catch (WifiException | MissingArgException e) { 286 fail(e.getMessage()); 287 return; 288 } 289 290 finish(Activity.RESULT_OK, result); 291 } 292 } 293