WifiNative.java revision 651cdfcbac6245f570475991588ddc2d30265e8d
1/* 2 * Copyright (C) 2008 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 android.net.wifi; 18 19import android.net.wifi.p2p.WifiP2pConfig; 20import android.net.wifi.p2p.WifiP2pGroup; 21import android.net.wifi.p2p.WifiP2pDevice; 22import android.util.Log; 23 24import java.io.InputStream; 25import java.lang.Process; 26import java.util.ArrayList; 27import java.util.List; 28 29/** 30 * Native calls for sending requests to the supplicant daemon, and for 31 * receiving asynchronous events. All methods of the form "xxxxCommand()" 32 * must be single-threaded, to avoid requests and responses initiated 33 * from multiple threads from being intermingled. 34 * <p/> 35 * Note that methods whose names are not of the form "xxxCommand()" do 36 * not talk to the supplicant daemon. 37 * Also, note that all WifiNative calls should happen in the 38 * WifiStateTracker class except for waitForEvent() call which is 39 * on a separate monitor channel for WifiMonitor 40 * 41 * TODO: clean up the API and move the functionality from JNI to here. We should 42 * be able to get everything done with doBooleanCommand, doIntCommand and 43 * doStringCommand native commands 44 * 45 * {@hide} 46 */ 47public class WifiNative { 48 49 static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0; 50 static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1; 51 static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2; 52 53 public native static String getErrorString(int errorCode); 54 55 public native static boolean loadDriver(); 56 57 public native static boolean isDriverLoaded(); 58 59 public native static boolean unloadDriver(); 60 61 public native static boolean startSupplicant(); 62 63 public native static boolean startP2pSupplicant(); 64 65 /* Does a graceful shutdown of supplicant. Is a common stop function for both p2p and sta. 66 * 67 * Note that underneath we use a harsh-sounding "terminate" supplicant command 68 * for a graceful stop and a mild-sounding "stop" interface 69 * to kill the process 70 */ 71 public native static boolean stopSupplicant(); 72 73 /* Sends a kill signal to supplicant. To be used when we have lost connection 74 or when the supplicant is hung */ 75 public native static boolean killSupplicant(); 76 77 public native static boolean connectToSupplicant(); 78 79 public native static void closeSupplicantConnection(); 80 81 public native static boolean pingCommand(); 82 83 public native static boolean scanCommand(boolean forceActive); 84 85 public native static boolean setScanModeCommand(boolean setActive); 86 87 public native static String listNetworksCommand(); 88 89 public native static int addNetworkCommand(); 90 91 public native static boolean setNetworkVariableCommand(int netId, String name, String value); 92 93 public native static String getNetworkVariableCommand(int netId, String name); 94 95 public native static boolean removeNetworkCommand(int netId); 96 97 public native static boolean enableNetworkCommand(int netId, boolean disableOthers); 98 99 public native static boolean disableNetworkCommand(int netId); 100 101 public native static boolean reconnectCommand(); 102 103 public native static boolean reassociateCommand(); 104 105 public native static boolean disconnectCommand(); 106 107 public native static String statusCommand(); 108 109 public native static int getRssiCommand(); 110 111 public native static int getRssiApproxCommand(); 112 113 public native static int getLinkSpeedCommand(); 114 115 public native static String getMacAddressCommand(); 116 117 public native static String scanResultsCommand(); 118 119 public native static boolean startDriverCommand(); 120 121 public native static boolean stopDriverCommand(); 122 123 124 /** 125 * Start filtering out Multicast V4 packets 126 * @return {@code true} if the operation succeeded, {@code false} otherwise 127 */ 128 public native static boolean startFilteringMulticastV4Packets(); 129 130 /** 131 * Stop filtering out Multicast V4 packets. 132 * @return {@code true} if the operation succeeded, {@code false} otherwise 133 */ 134 public native static boolean stopFilteringMulticastV4Packets(); 135 136 /** 137 * Start filtering out Multicast V6 packets 138 * @return {@code true} if the operation succeeded, {@code false} otherwise 139 */ 140 public native static boolean startFilteringMulticastV6Packets(); 141 142 /** 143 * Stop filtering out Multicast V6 packets. 144 * @return {@code true} if the operation succeeded, {@code false} otherwise 145 */ 146 public native static boolean stopFilteringMulticastV6Packets(); 147 148 public native static boolean setPowerModeCommand(int mode); 149 150 public native static int getBandCommand(); 151 152 public native static boolean setBandCommand(int band); 153 154 public native static int getPowerModeCommand(); 155 156 /** 157 * Sets the bluetooth coexistence mode. 158 * 159 * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED}, 160 * {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or 161 * {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}. 162 * @return Whether the mode was successfully set. 163 */ 164 public native static boolean setBluetoothCoexistenceModeCommand(int mode); 165 166 /** 167 * Enable or disable Bluetooth coexistence scan mode. When this mode is on, 168 * some of the low-level scan parameters used by the driver are changed to 169 * reduce interference with A2DP streaming. 170 * 171 * @param isSet whether to enable or disable this mode 172 * @return {@code true} if the command succeeded, {@code false} otherwise. 173 */ 174 public native static boolean setBluetoothCoexistenceScanModeCommand(boolean setCoexScanMode); 175 176 public native static boolean saveConfigCommand(); 177 178 public native static boolean reloadConfigCommand(); 179 180 public native static boolean setScanResultHandlingCommand(int mode); 181 182 public native static boolean addToBlacklistCommand(String bssid); 183 184 public native static boolean clearBlacklistCommand(); 185 186 public native static boolean startWpsPbcCommand(String bssid); 187 188 public native static boolean startWpsWithPinFromAccessPointCommand(String bssid, String apPin); 189 190 public native static String startWpsWithPinFromDeviceCommand(String bssid); 191 192 public native static boolean setSuspendOptimizationsCommand(boolean enabled); 193 194 public native static boolean setCountryCodeCommand(String countryCode); 195 196 /** 197 * Wait for the supplicant to send an event, returning the event string. 198 * @return the event string sent by the supplicant. 199 */ 200 public native static String waitForEvent(); 201 202 public native static void enableBackgroundScanCommand(boolean enable); 203 204 public native static void setScanIntervalCommand(int scanInterval); 205 206 private native static boolean doBooleanCommand(String command); 207 208 private native static int doIntCommand(String command); 209 210 private native static String doStringCommand(String command); 211 212 public static boolean wpsPbc() { 213 return doBooleanCommand("WPS_PBC"); 214 } 215 216 public static boolean wpsPin(String pin) { 217 return doBooleanCommand("WPS_PIN any " + pin); 218 } 219 220 public static boolean setPersistentReconnect(boolean enabled) { 221 int value = (enabled == true) ? 1 : 0; 222 return WifiNative.doBooleanCommand("SET persistent_reconnect " + value); 223 } 224 225 public static boolean setDeviceName(String name) { 226 return WifiNative.doBooleanCommand("SET device_name " + name); 227 } 228 229 public static boolean setDeviceType(String type) { 230 return WifiNative.doBooleanCommand("SET device_type " + type); 231 } 232 233 public static boolean p2pFind() { 234 return doBooleanCommand("P2P_FIND"); 235 } 236 237 public static boolean p2pFind(int timeout) { 238 if (timeout <= 0) { 239 return p2pFind(); 240 } 241 return doBooleanCommand("P2P_FIND " + timeout); 242 } 243 244 public static boolean p2pListen() { 245 return doBooleanCommand("P2P_LISTEN"); 246 } 247 248 public static boolean p2pListen(int timeout) { 249 if (timeout <= 0) { 250 return p2pListen(); 251 } 252 return doBooleanCommand("P2P_LISTEN " + timeout); 253 } 254 255 public static boolean p2pFlush() { 256 return doBooleanCommand("P2P_FLUSH"); 257 } 258 259 /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad] 260 [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */ 261 public static String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) { 262 if (config == null) return null; 263 List<String> args = new ArrayList<String>(); 264 WpsInfo wps = config.wps; 265 args.add(config.deviceAddress); 266 267 switch (wps.setup) { 268 case WpsInfo.PBC: 269 args.add("pbc"); 270 break; 271 case WpsInfo.DISPLAY: 272 //TODO: pass the pin back for display 273 args.add("pin"); 274 args.add("display"); 275 break; 276 case WpsInfo.KEYPAD: 277 args.add(wps.pin); 278 args.add("keypad"); 279 break; 280 case WpsInfo.LABEL: 281 args.add(wps.pin); 282 args.add("label"); 283 default: 284 break; 285 } 286 287 //TODO: Add persist behavior once the supplicant interaction is fixed for both 288 // group and client scenarios 289 /* Persist unless there is an explicit request to not do so*/ 290 //if (config.persist != WifiP2pConfig.Persist.NO) args.add("persistent"); 291 292 if (joinExistingGroup) args.add("join"); 293 294 int groupOwnerIntent = config.groupOwnerIntent; 295 if (groupOwnerIntent < 0 || groupOwnerIntent > 15) { 296 groupOwnerIntent = 3; //default value 297 } 298 args.add("go_intent=" + groupOwnerIntent); 299 300 String command = "P2P_CONNECT "; 301 for (String s : args) command += s + " "; 302 303 return doStringCommand(command); 304 } 305 306 public static boolean p2pCancelConnect() { 307 return doBooleanCommand("P2P_CANCEL"); 308 } 309 310 public static boolean p2pGroupAdd() { 311 return doBooleanCommand("P2P_GROUP_ADD"); 312 } 313 314 public static boolean p2pGroupRemove(String iface) { 315 if (iface == null) return false; 316 return doBooleanCommand("P2P_GROUP_REMOVE " + iface); 317 } 318 319 public static boolean p2pReject(String deviceAddress) { 320 return doBooleanCommand("P2P_REJECT " + deviceAddress); 321 } 322 323 /* Invite a peer to a group */ 324 public static boolean p2pInvite(WifiP2pGroup group, String deviceAddress) { 325 if (deviceAddress == null) return false; 326 327 if (group == null) { 328 return doBooleanCommand("P2P_INVITE peer=" + deviceAddress); 329 } else { 330 return doBooleanCommand("P2P_INVITE group=" + group.getInterface() 331 + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress); 332 } 333 } 334 335 /* Reinvoke a persistent connection */ 336 public static boolean p2pReinvoke(int netId, String deviceAddress) { 337 if (deviceAddress == null || netId < 0) return false; 338 339 return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress); 340 } 341 342 343 public static String p2pGetInterfaceAddress(String deviceAddress) { 344 if (deviceAddress == null) return null; 345 346 // "p2p_peer deviceAddress" returns a multi-line result containing 347 // intended_addr=fa:7b:7a:42:82:13 348 String peerInfo = p2pPeer(deviceAddress); 349 if (peerInfo == null) return null; 350 String[] tokens= peerInfo.split("\n"); 351 352 for (String token : tokens) { 353 //TODO: update from interface_addr when wpa_supplicant implementation is fixed 354 if (token.startsWith("intended_addr=")) { 355 String[] nameValue = token.split("="); 356 if (nameValue.length != 2) break; 357 return nameValue[1]; 358 } 359 } 360 return null; 361 } 362 363 public static String p2pGetDeviceAddress() { 364 String status = statusCommand(); 365 if (status == null) return ""; 366 367 String[] tokens = status.split("\n"); 368 for (String token : tokens) { 369 if (token.startsWith("p2p_device_address=")) { 370 String[] nameValue = token.split("="); 371 if (nameValue.length != 2) break; 372 return nameValue[1]; 373 } 374 } 375 return ""; 376 } 377 378 public static String p2pPeer(String deviceAddress) { 379 return doStringCommand("P2P_PEER " + deviceAddress); 380 } 381} 382