WifiNative.java revision c97b98d6877f6603a6a0eee820576f59e7da5e52
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 com.android.server.wifi; 18 19import android.net.wifi.BatchedScanSettings; 20import android.net.wifi.RttManager; 21import android.net.wifi.ScanResult; 22import android.net.wifi.WifiConfiguration; 23import android.net.wifi.WifiLinkLayerStats; 24import android.net.wifi.WifiManager; 25import android.net.wifi.WifiScanner; 26import android.net.wifi.RttManager; 27import android.net.wifi.WifiSsid; 28import android.net.wifi.WpsInfo; 29import android.net.wifi.p2p.WifiP2pConfig; 30import android.net.wifi.p2p.WifiP2pGroup; 31import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; 32import android.net.wifi.WifiEnterpriseConfig; 33import android.os.SystemClock; 34import android.text.TextUtils; 35import android.util.Base64; 36import android.util.LocalLog; 37import android.util.Log; 38 39import java.io.ByteArrayOutputStream; 40import java.io.IOException; 41import java.util.ArrayList; 42import java.util.List; 43import java.util.Locale; 44import java.util.zip.Deflater; 45 46/** 47 * Native calls for bring up/shut down of the supplicant daemon and for 48 * sending requests to the supplicant daemon 49 * 50 * waitForEvent() is called on the monitor thread for events. All other methods 51 * must be serialized from the framework. 52 * 53 * {@hide} 54 */ 55public class WifiNative { 56 57 private static boolean DBG = false; 58 private final String mTAG; 59 private static final int DEFAULT_GROUP_OWNER_INTENT = 6; 60 61 static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0; 62 static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1; 63 static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2; 64 65 static final int SCAN_WITHOUT_CONNECTION_SETUP = 1; 66 static final int SCAN_WITH_CONNECTION_SETUP = 2; 67 68 // Hold this lock before calling supplicant - it is required to 69 // mutually exclude access from Wifi and P2p state machines 70 static final Object mLock = new Object(); 71 72 public final String mInterfaceName; 73 public final String mInterfacePrefix; 74 75 private boolean mSuspendOptEnabled = false; 76 77 private static final int EID_HT_OPERATION = 61; 78 private static final int EID_VHT_OPERATION = 192; 79 private static final int EID_EXTENDED_CAPS = 127; 80 private static final int RTT_RESP_ENABLE_BIT = 70; 81 /* Register native functions */ 82 83 static { 84 /* Native functions are defined in libwifi-service.so */ 85 System.loadLibrary("wifi-service"); 86 registerNatives(); 87 } 88 89 private static native int registerNatives(); 90 91 public native static boolean loadDriver(); 92 93 public native static boolean isDriverLoaded(); 94 95 public native static boolean unloadDriver(); 96 97 public native static boolean startSupplicant(boolean p2pSupported); 98 99 /* Sends a kill signal to supplicant. To be used when we have lost connection 100 or when the supplicant is hung */ 101 public native static boolean killSupplicant(boolean p2pSupported); 102 103 private native boolean connectToSupplicantNative(); 104 105 private native void closeSupplicantConnectionNative(); 106 107 /** 108 * Wait for the supplicant to send an event, returning the event string. 109 * @return the event string sent by the supplicant. 110 */ 111 private native String waitForEventNative(); 112 113 private native boolean doBooleanCommandNative(String command); 114 115 private native int doIntCommandNative(String command); 116 117 private native String doStringCommandNative(String command); 118 119 public WifiNative(String interfaceName) { 120 mInterfaceName = interfaceName; 121 mTAG = "WifiNative-" + interfaceName; 122 if (!interfaceName.equals("p2p0")) { 123 mInterfacePrefix = "IFNAME=" + interfaceName + " "; 124 } else { 125 // commands for p2p0 interface don't need prefix 126 mInterfacePrefix = ""; 127 } 128 } 129 130 void enableVerboseLogging(int verbose) { 131 if (verbose > 0) { 132 DBG = true; 133 } else { 134 DBG = false; 135 } 136 } 137 138 private static final LocalLog mLocalLog = new LocalLog(65536); 139 140 // hold mLock before accessing mCmdIdLock 141 private static int sCmdId; 142 143 public static LocalLog getLocalLog() { 144 return mLocalLog; 145 } 146 147 private static int getNewCmdIdLocked() { 148 return sCmdId++; 149 } 150 151 private void localLog(String s) { 152 if (mLocalLog != null) 153 mLocalLog.log(mInterfaceName + ": " + s); 154 } 155 156 public boolean connectToSupplicant() { 157 // No synchronization necessary .. it is implemented in WifiMonitor 158 localLog(mInterfacePrefix + "connectToSupplicant"); 159 return connectToSupplicantNative(); 160 } 161 162 public void closeSupplicantConnection() { 163 localLog(mInterfacePrefix + "closeSupplicantConnection"); 164 closeSupplicantConnectionNative(); 165 } 166 167 public String waitForEvent() { 168 // No synchronization necessary .. it is implemented in WifiMonitor 169 return waitForEventNative(); 170 } 171 172 private boolean doBooleanCommand(String command) { 173 if (DBG) Log.d(mTAG, "doBoolean: " + command); 174 synchronized (mLock) { 175 int cmdId = getNewCmdIdLocked(); 176 String toLog = Integer.toString(cmdId) + ":" + mInterfacePrefix + command; 177 boolean result = doBooleanCommandNative(mInterfacePrefix + command); 178 localLog(toLog + " -> " + result); 179 if (DBG) Log.d(mTAG, command + ": returned " + result); 180 return result; 181 } 182 } 183 184 private boolean doBooleanCommandWithoutLogging(String command) { 185 if (DBG) Log.d(mTAG, "doBooleanCommandWithoutLogging: " + command); 186 synchronized (mLock) { 187 int cmdId = getNewCmdIdLocked(); 188 boolean result = doBooleanCommandNative(mInterfacePrefix + command); 189 if (DBG) Log.d(mTAG, command + ": returned " + result); 190 return result; 191 } 192 } 193 194 private int doIntCommand(String command) { 195 if (DBG) Log.d(mTAG, "doInt: " + command); 196 synchronized (mLock) { 197 int cmdId = getNewCmdIdLocked(); 198 String toLog = Integer.toString(cmdId) + ":" + mInterfacePrefix + command; 199 int result = doIntCommandNative(mInterfacePrefix + command); 200 localLog(toLog + " -> " + result); 201 if (DBG) Log.d(mTAG, " returned " + result); 202 return result; 203 } 204 } 205 206 private String doStringCommand(String command) { 207 if (DBG) { 208 //GET_NETWORK commands flood the logs 209 if (!command.startsWith("GET_NETWORK")) { 210 Log.d(mTAG, "doString: [" + command + "]"); 211 } 212 } 213 synchronized (mLock) { 214 int cmdId = getNewCmdIdLocked(); 215 String toLog = Integer.toString(cmdId) + ":" + mInterfacePrefix + command; 216 String result = doStringCommandNative(mInterfacePrefix + command); 217 if (result == null) { 218 if (DBG) Log.d(mTAG, "doStringCommandNative no result"); 219 } else { 220 if (!command.startsWith("STATUS-")) { 221 localLog(toLog + " -> " + result); 222 } 223 if (DBG) Log.d(mTAG, " returned " + result.replace("\n", " ")); 224 } 225 return result; 226 } 227 } 228 229 private String doStringCommandWithoutLogging(String command) { 230 if (DBG) { 231 //GET_NETWORK commands flood the logs 232 if (!command.startsWith("GET_NETWORK")) { 233 Log.d(mTAG, "doString: [" + command + "]"); 234 } 235 } 236 synchronized (mLock) { 237 return doStringCommandNative(mInterfacePrefix + command); 238 } 239 } 240 241 public boolean ping() { 242 String pong = doStringCommand("PING"); 243 return (pong != null && pong.equals("PONG")); 244 } 245 246 public void setSupplicantLogLevel(String level) { 247 doStringCommand("LOG_LEVEL " + level); 248 } 249 250 public String getFreqCapability() { 251 return doStringCommand("GET_CAPABILITY freq"); 252 } 253 254 public boolean scan(int type, String freqList) { 255 if (type == SCAN_WITHOUT_CONNECTION_SETUP) { 256 if (freqList == null) return doBooleanCommand("SCAN TYPE=ONLY"); 257 else return doBooleanCommand("SCAN TYPE=ONLY freq=" + freqList); 258 } else if (type == SCAN_WITH_CONNECTION_SETUP) { 259 if (freqList == null) return doBooleanCommand("SCAN"); 260 else return doBooleanCommand("SCAN freq=" + freqList); 261 } else { 262 throw new IllegalArgumentException("Invalid scan type"); 263 } 264 } 265 266 /* Does a graceful shutdown of supplicant. Is a common stop function for both p2p and sta. 267 * 268 * Note that underneath we use a harsh-sounding "terminate" supplicant command 269 * for a graceful stop and a mild-sounding "stop" interface 270 * to kill the process 271 */ 272 public boolean stopSupplicant() { 273 return doBooleanCommand("TERMINATE"); 274 } 275 276 public String listNetworks() { 277 return doStringCommand("LIST_NETWORKS"); 278 } 279 280 public String listNetworks(int last_id) { 281 return doStringCommand("LIST_NETWORKS LAST_ID=" + last_id); 282 } 283 284 public int addNetwork() { 285 return doIntCommand("ADD_NETWORK"); 286 } 287 288 public boolean setNetworkVariable(int netId, String name, String value) { 289 if (TextUtils.isEmpty(name) || TextUtils.isEmpty(value)) return false; 290 if (name.equals(WifiConfiguration.pskVarName) 291 || name.equals(WifiEnterpriseConfig.PASSWORD_KEY)) { 292 return doBooleanCommandWithoutLogging("SET_NETWORK " + netId + " " + name + " " + value); 293 } else { 294 return doBooleanCommand("SET_NETWORK " + netId + " " + name + " " + value); 295 } 296 } 297 298 public String getNetworkVariable(int netId, String name) { 299 if (TextUtils.isEmpty(name)) return null; 300 301 // GET_NETWORK will likely flood the logs ... 302 return doStringCommandWithoutLogging("GET_NETWORK " + netId + " " + name); 303 } 304 305 public boolean removeNetwork(int netId) { 306 return doBooleanCommand("REMOVE_NETWORK " + netId); 307 } 308 309 310 private void logDbg(String debug) { 311 long now = SystemClock.elapsedRealtimeNanos(); 312 String ts = String.format("[%,d us] ", now/1000); 313 Log.e("WifiNative: ", ts+debug+ " stack:" 314 + Thread.currentThread().getStackTrace()[2].getMethodName() +" - " 315 + Thread.currentThread().getStackTrace()[3].getMethodName() +" - " 316 + Thread.currentThread().getStackTrace()[4].getMethodName() +" - " 317 + Thread.currentThread().getStackTrace()[5].getMethodName()+" - " 318 + Thread.currentThread().getStackTrace()[6].getMethodName()); 319 320 } 321 public boolean enableNetwork(int netId, boolean disableOthers) { 322 if (DBG) logDbg("enableNetwork nid=" + Integer.toString(netId) 323 + " disableOthers=" + disableOthers); 324 if (disableOthers) { 325 return doBooleanCommand("SELECT_NETWORK " + netId); 326 } else { 327 return doBooleanCommand("ENABLE_NETWORK " + netId); 328 } 329 } 330 331 public boolean disableNetwork(int netId) { 332 if (DBG) logDbg("disableNetwork nid=" + Integer.toString(netId)); 333 return doBooleanCommand("DISABLE_NETWORK " + netId); 334 } 335 336 public boolean selectNetwork(int netId) { 337 if (DBG) logDbg("selectNetwork nid=" + Integer.toString(netId)); 338 return doBooleanCommand("SELECT_NETWORK " + netId); 339 } 340 341 public boolean reconnect() { 342 if (DBG) logDbg("RECONNECT "); 343 return doBooleanCommand("RECONNECT"); 344 } 345 346 public boolean reassociate() { 347 if (DBG) logDbg("REASSOCIATE "); 348 return doBooleanCommand("REASSOCIATE"); 349 } 350 351 public boolean disconnect() { 352 if (DBG) logDbg("DISCONNECT "); 353 return doBooleanCommand("DISCONNECT"); 354 } 355 356 public String status() { 357 return status(false); 358 } 359 360 public String status(boolean noEvents) { 361 if (noEvents) { 362 return doStringCommand("STATUS-NO_EVENTS"); 363 } else { 364 return doStringCommand("STATUS"); 365 } 366 } 367 368 public String getMacAddress() { 369 //Macaddr = XX.XX.XX.XX.XX.XX 370 String ret = doStringCommand("DRIVER MACADDR"); 371 if (!TextUtils.isEmpty(ret)) { 372 String[] tokens = ret.split(" = "); 373 if (tokens.length == 2) return tokens[1]; 374 } 375 return null; 376 } 377 378 379 380 /** 381 * Format of results: 382 * ================= 383 * id=1 384 * bssid=68:7f:74:d7:1b:6e 385 * freq=2412 386 * level=-43 387 * tsf=1344621975160944 388 * age=2623 389 * flags=[WPA2-PSK-CCMP][WPS][ESS] 390 * ssid=zubyb 391 * ==== 392 * 393 * RANGE=ALL gets all scan results 394 * RANGE=ID- gets results from ID 395 * MASK=<N> see wpa_supplicant/src/common/wpa_ctrl.h for details 396 * 0 0 1 0 2 397 * WPA_BSS_MASK_MESH_SCAN | WPA_BSS_MASK_DELIM | WPA_BSS_MASK_WIFI_DISPLAY 398 * 0 0 0 1 1 -> 9 399 * WPA_BSS_MASK_INTERNETW | WPA_BSS_MASK_P2P_SCAN | WPA_BSS_MASK_WPS_SCAN | WPA_BSS_MASK_SSID 400 * 1 0 0 1 9 -> d 401 * WPA_BSS_MASK_FLAGS | WPA_BSS_MASK_IE | WPA_BSS_MASK_AGE | WPA_BSS_MASK_TSF 402 * 1 0 0 0 8 403 * WPA_BSS_MASK_LEVEL | WPA_BSS_MASK_NOISE | WPA_BSS_MASK_QUAL | WPA_BSS_MASK_CAPABILITIES 404 * 0 1 1 1 7 405 * WPA_BSS_MASK_BEACON_INT | WPA_BSS_MASK_FREQ | WPA_BSS_MASK_BSSID | WPA_BSS_MASK_ID 406 * 407 * WPA_BSS_MASK_INTERNETW adds ANQP info (ctrl_iface:4151-4176) 408 * 409 * ctrl_iface.c:wpa_supplicant_ctrl_iface_process:7884 410 * wpa_supplicant_ctrl_iface_bss:4315 411 * print_bss_info 412 */ 413 public String scanResults(int sid) { 414 return doStringCommandWithoutLogging("BSS RANGE=" + sid + "- MASK=0x29d87"); 415 } 416 417 public String doCustomCommand(String command) { 418 return doStringCommand(command); 419 } 420 421 /** 422 * Format of result: 423 * id=1016 424 * bssid=00:03:7f:40:84:10 425 * freq=2462 426 * beacon_int=200 427 * capabilities=0x0431 428 * qual=0 429 * noise=0 430 * level=-46 431 * tsf=0000002669008476 432 * age=5 433 * ie=00105143412d485332302d52322d54455354010882848b960c12182403010b0706555... 434 * flags=[WPA2-EAP-CCMP][ESS][P2P][HS20] 435 * ssid=QCA-HS20-R2-TEST 436 * p2p_device_name= 437 * p2p_config_methods=0x0SET_NE 438 * anqp_venue_name=02083d656e6757692d466920416c6c69616e63650a3239383920436f... 439 * anqp_network_auth_type=010000 440 * anqp_roaming_consortium=03506f9a05001bc504bd 441 * anqp_ip_addr_type_availability=0c 442 * anqp_nai_realm=0200300000246d61696c2e6578616d706c652e636f6d3b636973636f2... 443 * anqp_3gpp=000600040132f465 444 * anqp_domain_name=0b65786d61706c652e636f6d 445 * hs20_operator_friendly_name=11656e6757692d466920416c6c69616e63650e636869... 446 * hs20_wan_metrics=01c40900008001000000000a00 447 * hs20_connection_capability=0100000006140001061600000650000106bb010106bb0... 448 * hs20_osu_providers_list=0b5143412d4f53552d425353010901310015656e6757692d... 449 */ 450 public String scanResult(String bssid) { 451 return doStringCommand("BSS " + bssid); 452 } 453 454 /** 455 * Format of command 456 * DRIVER WLS_BATCHING SET SCANFREQ=x MSCAN=r BESTN=y CHANNEL=<z, w, t> RTT=s 457 * where x is an ascii representation of an integer number of seconds between scans 458 * r is an ascii representation of an integer number of scans per batch 459 * y is an ascii representation of an integer number of the max AP to remember per scan 460 * z, w, t represent a 1..n size list of channel numbers and/or 'A', 'B' values 461 * indicating entire ranges of channels 462 * s is an ascii representation of an integer number of highest-strength AP 463 * for which we'd like approximate distance reported 464 * 465 * The return value is an ascii integer representing a guess of the number of scans 466 * the firmware can remember before it runs out of buffer space or -1 on error 467 */ 468 public String setBatchedScanSettings(BatchedScanSettings settings) { 469 if (settings == null) { 470 return doStringCommand("DRIVER WLS_BATCHING STOP"); 471 } 472 String cmd = "DRIVER WLS_BATCHING SET SCANFREQ=" + settings.scanIntervalSec; 473 cmd += " MSCAN=" + settings.maxScansPerBatch; 474 if (settings.maxApPerScan != BatchedScanSettings.UNSPECIFIED) { 475 cmd += " BESTN=" + settings.maxApPerScan; 476 } 477 if (settings.channelSet != null && !settings.channelSet.isEmpty()) { 478 cmd += " CHANNEL=<"; 479 int i = 0; 480 for (String channel : settings.channelSet) { 481 cmd += (i > 0 ? "," : "") + channel; 482 ++i; 483 } 484 cmd += ">"; 485 } 486 if (settings.maxApForDistance != BatchedScanSettings.UNSPECIFIED) { 487 cmd += " RTT=" + settings.maxApForDistance; 488 } 489 return doStringCommand(cmd); 490 } 491 492 public String getBatchedScanResults() { 493 return doStringCommand("DRIVER WLS_BATCHING GET"); 494 } 495 496 public boolean startDriver() { 497 return doBooleanCommand("DRIVER START"); 498 } 499 500 public boolean stopDriver() { 501 return doBooleanCommand("DRIVER STOP"); 502 } 503 504 505 /** 506 * Start filtering out Multicast V4 packets 507 * @return {@code true} if the operation succeeded, {@code false} otherwise 508 * 509 * Multicast filtering rules work as follows: 510 * 511 * The driver can filter multicast (v4 and/or v6) and broadcast packets when in 512 * a power optimized mode (typically when screen goes off). 513 * 514 * In order to prevent the driver from filtering the multicast/broadcast packets, we have to 515 * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective 516 * 517 * DRIVER RXFILTER-ADD Num 518 * where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6 519 * 520 * and DRIVER RXFILTER-START 521 * In order to stop the usage of these rules, we do 522 * 523 * DRIVER RXFILTER-STOP 524 * DRIVER RXFILTER-REMOVE Num 525 * where Num is as described for RXFILTER-ADD 526 * 527 * The SETSUSPENDOPT driver command overrides the filtering rules 528 */ 529 public boolean startFilteringMulticastV4Packets() { 530 return doBooleanCommand("DRIVER RXFILTER-STOP") 531 && doBooleanCommand("DRIVER RXFILTER-REMOVE 2") 532 && doBooleanCommand("DRIVER RXFILTER-START"); 533 } 534 535 /** 536 * Stop filtering out Multicast V4 packets. 537 * @return {@code true} if the operation succeeded, {@code false} otherwise 538 */ 539 public boolean stopFilteringMulticastV4Packets() { 540 return doBooleanCommand("DRIVER RXFILTER-STOP") 541 && doBooleanCommand("DRIVER RXFILTER-ADD 2") 542 && doBooleanCommand("DRIVER RXFILTER-START"); 543 } 544 545 /** 546 * Start filtering out Multicast V6 packets 547 * @return {@code true} if the operation succeeded, {@code false} otherwise 548 */ 549 public boolean startFilteringMulticastV6Packets() { 550 return doBooleanCommand("DRIVER RXFILTER-STOP") 551 && doBooleanCommand("DRIVER RXFILTER-REMOVE 3") 552 && doBooleanCommand("DRIVER RXFILTER-START"); 553 } 554 555 /** 556 * Stop filtering out Multicast V6 packets. 557 * @return {@code true} if the operation succeeded, {@code false} otherwise 558 */ 559 public boolean stopFilteringMulticastV6Packets() { 560 return doBooleanCommand("DRIVER RXFILTER-STOP") 561 && doBooleanCommand("DRIVER RXFILTER-ADD 3") 562 && doBooleanCommand("DRIVER RXFILTER-START"); 563 } 564 565 /** 566 * Set the operational frequency band 567 * @param band One of 568 * {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO}, 569 * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ}, 570 * {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ}, 571 * @return {@code true} if the operation succeeded, {@code false} otherwise 572 */ 573 public boolean setBand(int band) { 574 String bandstr; 575 576 if (band == WifiManager.WIFI_FREQUENCY_BAND_5GHZ) 577 bandstr = "5G"; 578 else if (band == WifiManager.WIFI_FREQUENCY_BAND_2GHZ) 579 bandstr = "2G"; 580 else 581 bandstr = "AUTO"; 582 return doBooleanCommand("SET SETBAND " + bandstr); 583 } 584 585 /** 586 * Sets the bluetooth coexistence mode. 587 * 588 * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED}, 589 * {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or 590 * {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}. 591 * @return Whether the mode was successfully set. 592 */ 593 public boolean setBluetoothCoexistenceMode(int mode) { 594 return doBooleanCommand("DRIVER BTCOEXMODE " + mode); 595 } 596 597 /** 598 * Enable or disable Bluetooth coexistence scan mode. When this mode is on, 599 * some of the low-level scan parameters used by the driver are changed to 600 * reduce interference with A2DP streaming. 601 * 602 * @param isSet whether to enable or disable this mode 603 * @return {@code true} if the command succeeded, {@code false} otherwise. 604 */ 605 public boolean setBluetoothCoexistenceScanMode(boolean setCoexScanMode) { 606 if (setCoexScanMode) { 607 return doBooleanCommand("DRIVER BTCOEXSCAN-START"); 608 } else { 609 return doBooleanCommand("DRIVER BTCOEXSCAN-STOP"); 610 } 611 } 612 613 public void enableSaveConfig() { 614 doBooleanCommand("SET update_config 1"); 615 } 616 617 public boolean saveConfig() { 618 return doBooleanCommand("SAVE_CONFIG"); 619 } 620 621 public boolean addToBlacklist(String bssid) { 622 if (TextUtils.isEmpty(bssid)) return false; 623 return doBooleanCommand("BLACKLIST " + bssid); 624 } 625 626 public boolean clearBlacklist() { 627 return doBooleanCommand("BLACKLIST clear"); 628 } 629 630 public boolean setSuspendOptimizations(boolean enabled) { 631 // if (mSuspendOptEnabled == enabled) return true; 632 mSuspendOptEnabled = enabled; 633 634 Log.e("native", "do suspend " + enabled); 635 if (enabled) { 636 return doBooleanCommand("DRIVER SETSUSPENDMODE 1"); 637 } else { 638 return doBooleanCommand("DRIVER SETSUSPENDMODE 0"); 639 } 640 } 641 642 public boolean setCountryCode(String countryCode) { 643 if (countryCode != null) 644 return doBooleanCommand("DRIVER COUNTRY " + countryCode.toUpperCase(Locale.ROOT)); 645 else 646 return doBooleanCommand("DRIVER COUNTRY"); 647 } 648 649 public boolean enableBackgroundScan(boolean enable) { 650 boolean ret; 651 if (enable) { 652 ret = doBooleanCommand("SET pno 1"); 653 } else { 654 ret = doBooleanCommand("SET pno 0"); 655 } 656 return ret; 657 } 658 659 public void enableAutoConnect(boolean enable) { 660 if (enable) { 661 doBooleanCommand("STA_AUTOCONNECT 1"); 662 } else { 663 doBooleanCommand("STA_AUTOCONNECT 0"); 664 } 665 } 666 667 public void setScanInterval(int scanInterval) { 668 doBooleanCommand("SCAN_INTERVAL " + scanInterval); 669 } 670 671 public void startTdls(String macAddr, boolean enable) { 672 if (enable) { 673 doBooleanCommand("TDLS_DISCOVER " + macAddr); 674 doBooleanCommand("TDLS_SETUP " + macAddr); 675 } else { 676 doBooleanCommand("TDLS_TEARDOWN " + macAddr); 677 } 678 } 679 680 /** Example output: 681 * RSSI=-65 682 * LINKSPEED=48 683 * NOISE=9999 684 * FREQUENCY=0 685 */ 686 public String signalPoll() { 687 return doStringCommandWithoutLogging("SIGNAL_POLL"); 688 } 689 690 /** Example outout: 691 * TXGOOD=396 692 * TXBAD=1 693 */ 694 public String pktcntPoll() { 695 return doStringCommand("PKTCNT_POLL"); 696 } 697 698 public void bssFlush() { 699 doBooleanCommand("BSS_FLUSH 0"); 700 } 701 702 public boolean startWpsPbc(String bssid) { 703 if (TextUtils.isEmpty(bssid)) { 704 return doBooleanCommand("WPS_PBC"); 705 } else { 706 return doBooleanCommand("WPS_PBC " + bssid); 707 } 708 } 709 710 public boolean startWpsPbc(String iface, String bssid) { 711 synchronized (mLock) { 712 if (TextUtils.isEmpty(bssid)) { 713 return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC"); 714 } else { 715 return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC " + bssid); 716 } 717 } 718 } 719 720 public boolean startWpsPinKeypad(String pin) { 721 if (TextUtils.isEmpty(pin)) return false; 722 return doBooleanCommand("WPS_PIN any " + pin); 723 } 724 725 public boolean startWpsPinKeypad(String iface, String pin) { 726 if (TextUtils.isEmpty(pin)) return false; 727 synchronized (mLock) { 728 return doBooleanCommandNative("IFNAME=" + iface + " WPS_PIN any " + pin); 729 } 730 } 731 732 733 public String startWpsPinDisplay(String bssid) { 734 if (TextUtils.isEmpty(bssid)) { 735 return doStringCommand("WPS_PIN any"); 736 } else { 737 return doStringCommand("WPS_PIN " + bssid); 738 } 739 } 740 741 public String startWpsPinDisplay(String iface, String bssid) { 742 synchronized (mLock) { 743 if (TextUtils.isEmpty(bssid)) { 744 return doStringCommandNative("IFNAME=" + iface + " WPS_PIN any"); 745 } else { 746 return doStringCommandNative("IFNAME=" + iface + " WPS_PIN " + bssid); 747 } 748 } 749 } 750 751 public boolean setExternalSim(boolean external) { 752 synchronized (mLock) { 753 String value = external ? "1" : "0"; 754 Log.d(TAG, "Setting external_sim to " + value); 755 return doBooleanCommand("SET external_sim " + value); 756 } 757 } 758 759 public boolean simAuthResponse(int id, String type, String response) { 760 // with type = GSM-AUTH, UMTS-AUTH or UMTS-AUTS 761 synchronized (mLock) { 762 return doBooleanCommand("CTRL-RSP-SIM-" + id + ":" + type + response); 763 } 764 } 765 766 public boolean simIdentityResponse(int id, String response) { 767 synchronized (mLock) { 768 return doBooleanCommand("CTRL-RSP-IDENTITY-" + id + ":" + response); 769 } 770 } 771 772 /* Configures an access point connection */ 773 public boolean startWpsRegistrar(String bssid, String pin) { 774 if (TextUtils.isEmpty(bssid) || TextUtils.isEmpty(pin)) return false; 775 return doBooleanCommand("WPS_REG " + bssid + " " + pin); 776 } 777 778 public boolean cancelWps() { 779 return doBooleanCommand("WPS_CANCEL"); 780 } 781 782 public boolean setPersistentReconnect(boolean enabled) { 783 int value = (enabled == true) ? 1 : 0; 784 return doBooleanCommand("SET persistent_reconnect " + value); 785 } 786 787 public boolean setDeviceName(String name) { 788 return doBooleanCommand("SET device_name " + name); 789 } 790 791 public boolean setDeviceType(String type) { 792 return doBooleanCommand("SET device_type " + type); 793 } 794 795 public boolean setConfigMethods(String cfg) { 796 return doBooleanCommand("SET config_methods " + cfg); 797 } 798 799 public boolean setManufacturer(String value) { 800 return doBooleanCommand("SET manufacturer " + value); 801 } 802 803 public boolean setModelName(String value) { 804 return doBooleanCommand("SET model_name " + value); 805 } 806 807 public boolean setModelNumber(String value) { 808 return doBooleanCommand("SET model_number " + value); 809 } 810 811 public boolean setSerialNumber(String value) { 812 return doBooleanCommand("SET serial_number " + value); 813 } 814 815 public boolean setP2pSsidPostfix(String postfix) { 816 return doBooleanCommand("SET p2p_ssid_postfix " + postfix); 817 } 818 819 public boolean setP2pGroupIdle(String iface, int time) { 820 synchronized (mLock) { 821 return doBooleanCommandNative("IFNAME=" + iface + " SET p2p_group_idle " + time); 822 } 823 } 824 825 public void setPowerSave(boolean enabled) { 826 if (enabled) { 827 doBooleanCommand("SET ps 1"); 828 } else { 829 doBooleanCommand("SET ps 0"); 830 } 831 } 832 833 public boolean setP2pPowerSave(String iface, boolean enabled) { 834 synchronized (mLock) { 835 if (enabled) { 836 return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 1"); 837 } else { 838 return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 0"); 839 } 840 } 841 } 842 843 public boolean setWfdEnable(boolean enable) { 844 return doBooleanCommand("SET wifi_display " + (enable ? "1" : "0")); 845 } 846 847 public boolean setWfdDeviceInfo(String hex) { 848 return doBooleanCommand("WFD_SUBELEM_SET 0 " + hex); 849 } 850 851 /** 852 * "sta" prioritizes STA connection over P2P and "p2p" prioritizes 853 * P2P connection over STA 854 */ 855 public boolean setConcurrencyPriority(String s) { 856 return doBooleanCommand("P2P_SET conc_pref " + s); 857 } 858 859 public boolean p2pFind() { 860 return doBooleanCommand("P2P_FIND"); 861 } 862 863 public boolean p2pFind(int timeout) { 864 if (timeout <= 0) { 865 return p2pFind(); 866 } 867 return doBooleanCommand("P2P_FIND " + timeout); 868 } 869 870 public boolean p2pStopFind() { 871 return doBooleanCommand("P2P_STOP_FIND"); 872 } 873 874 public boolean p2pListen() { 875 return doBooleanCommand("P2P_LISTEN"); 876 } 877 878 public boolean p2pListen(int timeout) { 879 if (timeout <= 0) { 880 return p2pListen(); 881 } 882 return doBooleanCommand("P2P_LISTEN " + timeout); 883 } 884 885 public boolean p2pExtListen(boolean enable, int period, int interval) { 886 if (enable && interval < period) { 887 return false; 888 } 889 return doBooleanCommand("P2P_EXT_LISTEN" 890 + (enable ? (" " + period + " " + interval) : "")); 891 } 892 893 public boolean p2pSetChannel(int lc, int oc) { 894 if (DBG) Log.d(mTAG, "p2pSetChannel: lc="+lc+", oc="+oc); 895 896 if (lc >=1 && lc <= 11) { 897 if (!doBooleanCommand("P2P_SET listen_channel " + lc)) { 898 return false; 899 } 900 } else if (lc != 0) { 901 return false; 902 } 903 904 if (oc >= 1 && oc <= 165 ) { 905 int freq = (oc <= 14 ? 2407 : 5000) + oc * 5; 906 return doBooleanCommand("P2P_SET disallow_freq 1000-" 907 + (freq - 5) + "," + (freq + 5) + "-6000"); 908 } else if (oc == 0) { 909 /* oc==0 disables "P2P_SET disallow_freq" (enables all freqs) */ 910 return doBooleanCommand("P2P_SET disallow_freq \"\""); 911 } 912 913 return false; 914 } 915 916 public boolean p2pFlush() { 917 return doBooleanCommand("P2P_FLUSH"); 918 } 919 920 /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad] 921 [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */ 922 public String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) { 923 if (config == null) return null; 924 List<String> args = new ArrayList<String>(); 925 WpsInfo wps = config.wps; 926 args.add(config.deviceAddress); 927 928 switch (wps.setup) { 929 case WpsInfo.PBC: 930 args.add("pbc"); 931 break; 932 case WpsInfo.DISPLAY: 933 if (TextUtils.isEmpty(wps.pin)) { 934 args.add("pin"); 935 } else { 936 args.add(wps.pin); 937 } 938 args.add("display"); 939 break; 940 case WpsInfo.KEYPAD: 941 args.add(wps.pin); 942 args.add("keypad"); 943 break; 944 case WpsInfo.LABEL: 945 args.add(wps.pin); 946 args.add("label"); 947 default: 948 break; 949 } 950 951 if (config.netId == WifiP2pGroup.PERSISTENT_NET_ID) { 952 args.add("persistent"); 953 } 954 955 if (joinExistingGroup) { 956 args.add("join"); 957 } else { 958 //TODO: This can be adapted based on device plugged in state and 959 //device battery state 960 int groupOwnerIntent = config.groupOwnerIntent; 961 if (groupOwnerIntent < 0 || groupOwnerIntent > 15) { 962 groupOwnerIntent = DEFAULT_GROUP_OWNER_INTENT; 963 } 964 args.add("go_intent=" + groupOwnerIntent); 965 } 966 967 String command = "P2P_CONNECT "; 968 for (String s : args) command += s + " "; 969 970 return doStringCommand(command); 971 } 972 973 public boolean p2pCancelConnect() { 974 return doBooleanCommand("P2P_CANCEL"); 975 } 976 977 public boolean p2pProvisionDiscovery(WifiP2pConfig config) { 978 if (config == null) return false; 979 980 switch (config.wps.setup) { 981 case WpsInfo.PBC: 982 return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " pbc"); 983 case WpsInfo.DISPLAY: 984 //We are doing display, so provision discovery is keypad 985 return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " keypad"); 986 case WpsInfo.KEYPAD: 987 //We are doing keypad, so provision discovery is display 988 return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " display"); 989 default: 990 break; 991 } 992 return false; 993 } 994 995 public boolean p2pGroupAdd(boolean persistent) { 996 if (persistent) { 997 return doBooleanCommand("P2P_GROUP_ADD persistent"); 998 } 999 return doBooleanCommand("P2P_GROUP_ADD"); 1000 } 1001 1002 public boolean p2pGroupAdd(int netId) { 1003 return doBooleanCommand("P2P_GROUP_ADD persistent=" + netId); 1004 } 1005 1006 public boolean p2pGroupRemove(String iface) { 1007 if (TextUtils.isEmpty(iface)) return false; 1008 synchronized (mLock) { 1009 return doBooleanCommandNative("IFNAME=" + iface + " P2P_GROUP_REMOVE " + iface); 1010 } 1011 } 1012 1013 public boolean p2pReject(String deviceAddress) { 1014 return doBooleanCommand("P2P_REJECT " + deviceAddress); 1015 } 1016 1017 /* Invite a peer to a group */ 1018 public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) { 1019 if (TextUtils.isEmpty(deviceAddress)) return false; 1020 1021 if (group == null) { 1022 return doBooleanCommand("P2P_INVITE peer=" + deviceAddress); 1023 } else { 1024 return doBooleanCommand("P2P_INVITE group=" + group.getInterface() 1025 + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress); 1026 } 1027 } 1028 1029 /* Reinvoke a persistent connection */ 1030 public boolean p2pReinvoke(int netId, String deviceAddress) { 1031 if (TextUtils.isEmpty(deviceAddress) || netId < 0) return false; 1032 1033 return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress); 1034 } 1035 1036 public String p2pGetSsid(String deviceAddress) { 1037 return p2pGetParam(deviceAddress, "oper_ssid"); 1038 } 1039 1040 public String p2pGetDeviceAddress() { 1041 1042 Log.d(TAG, "p2pGetDeviceAddress"); 1043 1044 String status = null; 1045 1046 /* Explicitly calling the API without IFNAME= prefix to take care of the devices that 1047 don't have p2p0 interface. Supplicant seems to be returning the correct address anyway. */ 1048 1049 synchronized (mLock) { 1050 status = doStringCommandNative("STATUS"); 1051 } 1052 1053 String result = ""; 1054 if (status != null) { 1055 String[] tokens = status.split("\n"); 1056 for (String token : tokens) { 1057 if (token.startsWith("p2p_device_address=")) { 1058 String[] nameValue = token.split("="); 1059 if (nameValue.length != 2) 1060 break; 1061 result = nameValue[1]; 1062 } 1063 } 1064 } 1065 1066 Log.d(TAG, "p2pGetDeviceAddress returning " + result); 1067 return result; 1068 } 1069 1070 public int getGroupCapability(String deviceAddress) { 1071 int gc = 0; 1072 if (TextUtils.isEmpty(deviceAddress)) return gc; 1073 String peerInfo = p2pPeer(deviceAddress); 1074 if (TextUtils.isEmpty(peerInfo)) return gc; 1075 1076 String[] tokens = peerInfo.split("\n"); 1077 for (String token : tokens) { 1078 if (token.startsWith("group_capab=")) { 1079 String[] nameValue = token.split("="); 1080 if (nameValue.length != 2) break; 1081 try { 1082 return Integer.decode(nameValue[1]); 1083 } catch(NumberFormatException e) { 1084 return gc; 1085 } 1086 } 1087 } 1088 return gc; 1089 } 1090 1091 public String p2pPeer(String deviceAddress) { 1092 return doStringCommand("P2P_PEER " + deviceAddress); 1093 } 1094 1095 private String p2pGetParam(String deviceAddress, String key) { 1096 if (deviceAddress == null) return null; 1097 1098 String peerInfo = p2pPeer(deviceAddress); 1099 if (peerInfo == null) return null; 1100 String[] tokens= peerInfo.split("\n"); 1101 1102 key += "="; 1103 for (String token : tokens) { 1104 if (token.startsWith(key)) { 1105 String[] nameValue = token.split("="); 1106 if (nameValue.length != 2) break; 1107 return nameValue[1]; 1108 } 1109 } 1110 return null; 1111 } 1112 1113 public boolean p2pServiceAdd(WifiP2pServiceInfo servInfo) { 1114 /* 1115 * P2P_SERVICE_ADD bonjour <query hexdump> <RDATA hexdump> 1116 * P2P_SERVICE_ADD upnp <version hex> <service> 1117 * 1118 * e.g) 1119 * [Bonjour] 1120 * # IP Printing over TCP (PTR) (RDATA=MyPrinter._ipp._tcp.local.) 1121 * P2P_SERVICE_ADD bonjour 045f697070c00c000c01 094d795072696e746572c027 1122 * # IP Printing over TCP (TXT) (RDATA=txtvers=1,pdl=application/postscript) 1123 * P2P_SERVICE_ADD bonjour 096d797072696e746572045f697070c00c001001 1124 * 09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074 1125 * 1126 * [UPnP] 1127 * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012 1128 * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice 1129 * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp 1130 * -org:device:InternetGatewayDevice:1 1131 * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9322-123456789012::urn:schemas-upnp 1132 * -org:service:ContentDirectory:2 1133 */ 1134 for (String s : servInfo.getSupplicantQueryList()) { 1135 String command = "P2P_SERVICE_ADD"; 1136 command += (" " + s); 1137 if (!doBooleanCommand(command)) { 1138 return false; 1139 } 1140 } 1141 return true; 1142 } 1143 1144 public boolean p2pServiceDel(WifiP2pServiceInfo servInfo) { 1145 /* 1146 * P2P_SERVICE_DEL bonjour <query hexdump> 1147 * P2P_SERVICE_DEL upnp <version hex> <service> 1148 */ 1149 for (String s : servInfo.getSupplicantQueryList()) { 1150 String command = "P2P_SERVICE_DEL "; 1151 1152 String[] data = s.split(" "); 1153 if (data.length < 2) { 1154 return false; 1155 } 1156 if ("upnp".equals(data[0])) { 1157 command += s; 1158 } else if ("bonjour".equals(data[0])) { 1159 command += data[0]; 1160 command += (" " + data[1]); 1161 } else { 1162 return false; 1163 } 1164 if (!doBooleanCommand(command)) { 1165 return false; 1166 } 1167 } 1168 return true; 1169 } 1170 1171 public boolean p2pServiceFlush() { 1172 return doBooleanCommand("P2P_SERVICE_FLUSH"); 1173 } 1174 1175 public String p2pServDiscReq(String addr, String query) { 1176 String command = "P2P_SERV_DISC_REQ"; 1177 command += (" " + addr); 1178 command += (" " + query); 1179 1180 return doStringCommand(command); 1181 } 1182 1183 public boolean p2pServDiscCancelReq(String id) { 1184 return doBooleanCommand("P2P_SERV_DISC_CANCEL_REQ " + id); 1185 } 1186 1187 /* Set the current mode of miracast operation. 1188 * 0 = disabled 1189 * 1 = operating as source 1190 * 2 = operating as sink 1191 */ 1192 public void setMiracastMode(int mode) { 1193 // Note: optional feature on the driver. It is ok for this to fail. 1194 doBooleanCommand("DRIVER MIRACAST " + mode); 1195 } 1196 1197 public boolean fetchAnqp(String bssid, String subtypes) { 1198 return doBooleanCommand("ANQP_GET " + bssid + " " + subtypes); 1199 } 1200 1201 /* 1202 * NFC-related calls 1203 */ 1204 public String getNfcWpsConfigurationToken(int netId) { 1205 return doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId); 1206 } 1207 1208 public String getNfcHandoverRequest() { 1209 return doStringCommand("NFC_GET_HANDOVER_REQ NDEF P2P-CR"); 1210 } 1211 1212 public String getNfcHandoverSelect() { 1213 return doStringCommand("NFC_GET_HANDOVER_SEL NDEF P2P-CR"); 1214 } 1215 1216 public boolean initiatorReportNfcHandover(String selectMessage) { 1217 return doBooleanCommand("NFC_REPORT_HANDOVER INIT P2P 00 " + selectMessage); 1218 } 1219 1220 public boolean responderReportNfcHandover(String requestMessage) { 1221 return doBooleanCommand("NFC_REPORT_HANDOVER RESP P2P " + requestMessage + " 00"); 1222 } 1223 1224 /* WIFI HAL support */ 1225 1226 private static final String TAG = "WifiNative-HAL"; 1227 private static long sWifiHalHandle = 0; /* used by JNI to save wifi_handle */ 1228 private static long[] sWifiIfaceHandles = null; /* used by JNI to save interface handles */ 1229 private static int sWlan0Index = -1; 1230 private static int sP2p0Index = -1; 1231 private static MonitorThread sThread; 1232 private static final int STOP_HAL_TIMEOUT_MS = 1000; 1233 1234 private static native boolean startHalNative(); 1235 private static native void stopHalNative(); 1236 private static native void waitForHalEventNative(); 1237 1238 private static class MonitorThread extends Thread { 1239 public void run() { 1240 Log.i(TAG, "Waiting for HAL events mWifiHalHandle=" + Long.toString(sWifiHalHandle)); 1241 waitForHalEventNative(); 1242 } 1243 } 1244 1245 synchronized public static boolean startHal() { 1246 1247 String debugLog = "startHal stack: "; 1248 java.lang.StackTraceElement[] elements = Thread.currentThread().getStackTrace(); 1249 for (int i = 2; i < elements.length && i <= 7; i++ ) { 1250 debugLog = debugLog + " - " + elements[i].getMethodName(); 1251 } 1252 1253 mLocalLog.log(debugLog); 1254 1255 synchronized (mLock) { 1256 if (startHalNative() && (getInterfaces() != 0) && (sWlan0Index != -1)) { 1257 sThread = new MonitorThread(); 1258 sThread.start(); 1259 return true; 1260 } else { 1261 if (DBG) mLocalLog.log("Could not start hal"); 1262 Log.e(TAG, "Could not start hal"); 1263 return false; 1264 } 1265 } 1266 } 1267 1268 synchronized public static void stopHal() { 1269 synchronized (mLock) { 1270 if (sWifiHalHandle != 0) { 1271 stopHalNative(); 1272 try { 1273 sThread.join(STOP_HAL_TIMEOUT_MS); 1274 Log.d(TAG, "HAL event thread stopped successfully"); 1275 } catch (InterruptedException e) { 1276 Log.e(TAG, "Could not stop HAL cleanly"); 1277 } 1278 sThread = null; 1279 sWifiHalHandle = 0; 1280 sWifiIfaceHandles = null; 1281 sWlan0Index = -1; 1282 sP2p0Index = -1; 1283 } 1284 } 1285 } 1286 1287 private static native int getInterfacesNative(); 1288 1289 synchronized public static int getInterfaces() { 1290 synchronized (mLock) { 1291 if (sWifiHalHandle != 0) { 1292 if (sWifiIfaceHandles == null) { 1293 int num = getInterfacesNative(); 1294 int wifi_num = 0; 1295 for (int i = 0; i < num; i++) { 1296 String name = getInterfaceNameNative(i); 1297 Log.i(TAG, "interface[" + i + "] = " + name); 1298 if (name.equals("wlan0")) { 1299 sWlan0Index = i; 1300 wifi_num++; 1301 } else if (name.equals("p2p0")) { 1302 sP2p0Index = i; 1303 wifi_num++; 1304 } 1305 } 1306 return wifi_num; 1307 } else { 1308 return sWifiIfaceHandles.length; 1309 } 1310 } else { 1311 return 0; 1312 } 1313 } 1314 } 1315 1316 private static native String getInterfaceNameNative(int index); 1317 synchronized public static String getInterfaceName(int index) { 1318 return getInterfaceNameNative(index); 1319 } 1320 1321 public static class ScanCapabilities { 1322 public int max_scan_cache_size; // in number of scan results?? 1323 public int max_scan_buckets; 1324 public int max_ap_cache_per_scan; 1325 public int max_rssi_sample_size; 1326 public int max_scan_reporting_threshold; // in number of scan results?? 1327 public int max_hotlist_bssids; 1328 public int max_significant_wifi_change_aps; 1329 } 1330 1331 public static boolean getScanCapabilities(ScanCapabilities capabilities) { 1332 return getScanCapabilitiesNative(sWlan0Index, capabilities); 1333 } 1334 1335 private static native boolean getScanCapabilitiesNative( 1336 int iface, ScanCapabilities capabilities); 1337 1338 private static native boolean startScanNative(int iface, int id, ScanSettings settings); 1339 private static native boolean stopScanNative(int iface, int id); 1340 private static native WifiScanner.ScanData[] getScanResultsNative(int iface, boolean flush); 1341 private static native WifiLinkLayerStats getWifiLinkLayerStatsNative(int iface); 1342 private static native void setWifiLinkLayerStatsNative(int iface, int enable); 1343 1344 public static class ChannelSettings { 1345 int frequency; 1346 int dwell_time_ms; 1347 boolean passive; 1348 } 1349 1350 public static class BucketSettings { 1351 int bucket; 1352 int band; 1353 int period_ms; 1354 int report_events; 1355 int num_channels; 1356 ChannelSettings channels[]; 1357 } 1358 1359 public static class ScanSettings { 1360 int base_period_ms; 1361 int max_ap_per_scan; 1362 int report_threshold_percent; 1363 int report_threshold_num_scans; 1364 int num_buckets; 1365 BucketSettings buckets[]; 1366 } 1367 1368 public static interface ScanEventHandler { 1369 void onScanResultsAvailable(); 1370 void onFullScanResult(ScanResult fullScanResult); 1371 void onScanStatus(); 1372 void onScanPaused(WifiScanner.ScanData[] data); 1373 void onScanRestarted(); 1374 } 1375 1376 synchronized static void onScanResultsAvailable(int id) { 1377 if (sScanEventHandler != null) { 1378 sScanEventHandler.onScanResultsAvailable(); 1379 } 1380 } 1381 1382 /* scan status, keep these values in sync with gscan.h */ 1383 private static int WIFI_SCAN_BUFFER_FULL = 0; 1384 private static int WIFI_SCAN_COMPLETE = 1; 1385 1386 synchronized static void onScanStatus(int status) { 1387 if (status == WIFI_SCAN_BUFFER_FULL) { 1388 /* we have a separate event to take care of this */ 1389 } else if (status == WIFI_SCAN_COMPLETE) { 1390 if (sScanEventHandler != null) { 1391 sScanEventHandler.onScanStatus(); 1392 } 1393 } 1394 } 1395 1396 static void populateScanResult(ScanResult result, byte bytes[], String dbg) { 1397 int num = 0; 1398 if (bytes == null) return; 1399 if (dbg == null) dbg = ""; 1400 for (int i = 0; i < bytes.length; ) { 1401 int type = bytes[i] & 0xFF; 1402 int len = bytes[i + 1] & 0xFF; 1403 1404 if (i + len + 2 > bytes.length) { 1405 Log.w(TAG, dbg + "bad length " + len + " of IE " + type + " from " + result.BSSID); 1406 Log.w(TAG, dbg + "ignoring the rest of the IEs"); 1407 break; 1408 } 1409 num++; 1410 i += len + 2; 1411 if (DBG) Log.i(TAG, dbg + "bytes[" + i + "] = [" + type + ", " + len + "]" + ", " + 1412 "next = " + i); 1413 } 1414 1415 int secondChanelOffset = 0; 1416 byte channelMode = 0; 1417 byte centerFreqIndex1 = 0; 1418 byte centerFreqIndex2 = 0; 1419 result.is80211McRTTResponder = false; 1420 1421 ScanResult.InformationElement elements[] = new ScanResult.InformationElement[num]; 1422 for (int i = 0, index = 0; i < num; i++) { 1423 int type = bytes[index] & 0xFF; 1424 int len = bytes[index + 1] & 0xFF; 1425 if (DBG) Log.i(TAG, dbg + "index = " + index + ", type = " + type + ", len = " + len); 1426 ScanResult.InformationElement elem = new ScanResult.InformationElement(); 1427 elem.id = type; 1428 elem.bytes = new byte[len]; 1429 for (int j = 0; j < len; j++) { 1430 elem.bytes[j] = bytes[index + j + 2]; 1431 } 1432 elements[i] = elem; 1433 int inforStart = index + 2; 1434 index += (len + 2); 1435 1436 if(type == EID_HT_OPERATION) { 1437 secondChanelOffset = bytes[inforStart + 1] & 0x3; 1438 } else if(type == EID_VHT_OPERATION) { 1439 channelMode = bytes[inforStart]; 1440 centerFreqIndex1 = bytes[inforStart + 1]; 1441 centerFreqIndex2 = bytes[inforStart + 2]; 1442 } else if (type == EID_EXTENDED_CAPS) { 1443 int tempIndex = RTT_RESP_ENABLE_BIT / 8; 1444 byte offset = RTT_RESP_ENABLE_BIT % 8; 1445 1446 if(len < tempIndex + 1) { 1447 result.is80211McRTTResponder = false; 1448 } else { 1449 if ((bytes[inforStart + tempIndex] & ((byte)0x1 << offset)) != 0) { 1450 result.is80211McRTTResponder = true; 1451 } else { 1452 result.is80211McRTTResponder = false; 1453 } 1454 } 1455 } 1456 } 1457 //handle RTT related information 1458 if (channelMode != 0) { 1459 // 80 or 160 MHz 1460 result.channelWidth = channelMode + 1; 1461 1462 //convert channel index to frequency in MHz, channel 36 is 5180MHz 1463 result.centerFreq0 = (centerFreqIndex1 - 36) * 5 + 5180; 1464 1465 if(channelMode > 1) { //160MHz 1466 result.centerFreq1 = (centerFreqIndex2 - 36) * 5 + 5180; 1467 } else { 1468 result.centerFreq1 = 0; 1469 } 1470 } else { 1471 //20 or 40 MHz 1472 if (secondChanelOffset != 0) {//40MHz 1473 result.channelWidth = 1; 1474 if (secondChanelOffset == 1) { 1475 result.centerFreq0 = result.frequency + 20; 1476 } else if (secondChanelOffset == 3) { 1477 result.centerFreq0 = result.frequency - 20; 1478 } else { 1479 result.centerFreq0 = 0; 1480 Log.e(TAG, dbg + ": Error on secondChanelOffset"); 1481 } 1482 } else { 1483 result.centerFreq0 = 0; 1484 result.centerFreq1 = 0; 1485 } 1486 result.centerFreq1 = 0; 1487 } 1488 if(DBG) { 1489 Log.d(TAG, dbg + "SSID: " + result.SSID + " ChannelWidth is: " + result.channelWidth + 1490 " PrimaryFreq: " + result.frequency +" mCenterfreq0: " + result.centerFreq0 + 1491 " mCenterfreq1: " + result.centerFreq1 + (result.is80211McRTTResponder ? 1492 "Support RTT reponder: " : "Do not support RTT responder")); 1493 } 1494 1495 result.informationElements = elements; 1496 } 1497 1498 synchronized static void onFullScanResult(int id, ScanResult result, byte bytes[]) { 1499 if (DBG) Log.i(TAG, "Got a full scan results event, ssid = " + result.SSID + ", " + 1500 "num = " + bytes.length); 1501 1502 if (sScanEventHandler == null) { 1503 return; 1504 } 1505 populateScanResult(result, bytes, " onFullScanResult "); 1506 1507 sScanEventHandler.onFullScanResult(result); 1508 } 1509 1510 private static int sScanCmdId = 0; 1511 private static ScanEventHandler sScanEventHandler; 1512 private static ScanSettings sScanSettings; 1513 1514 synchronized public static boolean startScan( 1515 ScanSettings settings, ScanEventHandler eventHandler) { 1516 synchronized (mLock) { 1517 if (sWifiHalHandle != 0) { 1518 1519 if (sScanCmdId != 0) { 1520 stopScan(); 1521 } else if (sScanSettings != null || sScanEventHandler != null) { 1522 /* current scan is paused; no need to stop it */ 1523 } 1524 1525 sScanCmdId = getNewCmdIdLocked(); 1526 1527 sScanSettings = settings; 1528 sScanEventHandler = eventHandler; 1529 1530 if (startScanNative(sWlan0Index, sScanCmdId, settings) == false) { 1531 sScanEventHandler = null; 1532 sScanSettings = null; 1533 sScanCmdId = 0; 1534 return false; 1535 } 1536 1537 return true; 1538 } else { 1539 return false; 1540 } 1541 } 1542 } 1543 1544 synchronized public static void stopScan() { 1545 synchronized (mLock) { 1546 if (sWifiHalHandle != 0) { 1547 stopScanNative(sWlan0Index, sScanCmdId); 1548 sScanSettings = null; 1549 sScanEventHandler = null; 1550 sScanCmdId = 0; 1551 } 1552 } 1553 } 1554 1555 synchronized public static void pauseScan() { 1556 synchronized (mLock) { 1557 if (sWifiHalHandle != 0) { 1558 if (sScanCmdId != 0 && sScanSettings != null && sScanEventHandler != null) { 1559 Log.d(TAG, "Pausing scan"); 1560 WifiScanner.ScanData scanData[] = getScanResultsNative(sWlan0Index, true); 1561 stopScanNative(sWlan0Index, sScanCmdId); 1562 sScanCmdId = 0; 1563 sScanEventHandler.onScanPaused(scanData); 1564 } 1565 } 1566 } 1567 } 1568 1569 synchronized public static void restartScan() { 1570 synchronized (mLock) { 1571 if (sWifiHalHandle != 0) { 1572 if (sScanCmdId == 0 && sScanSettings != null && sScanEventHandler != null) { 1573 Log.d(TAG, "Restarting scan"); 1574 ScanEventHandler handler = sScanEventHandler; 1575 ScanSettings settings = sScanSettings; 1576 if (startScan(sScanSettings, sScanEventHandler)) { 1577 sScanEventHandler.onScanRestarted(); 1578 } else { 1579 /* we are still paused; don't change state */ 1580 sScanEventHandler = handler; 1581 sScanSettings = settings; 1582 } 1583 } 1584 } 1585 } 1586 } 1587 1588 synchronized public static WifiScanner.ScanData[] getScanResults(boolean flush) { 1589 synchronized (mLock) { 1590 if (sWifiHalHandle != 0) { 1591 return getScanResultsNative(sWlan0Index, flush); 1592 } else { 1593 return null; 1594 } 1595 } 1596 } 1597 1598 public static interface HotlistEventHandler { 1599 void onHotlistApFound (ScanResult[] result); 1600 void onHotlistApLost (ScanResult[] result); 1601 } 1602 1603 private static int sHotlistCmdId = 0; 1604 private static HotlistEventHandler sHotlistEventHandler; 1605 1606 private native static boolean setHotlistNative(int iface, int id, 1607 WifiScanner.HotlistSettings settings); 1608 private native static boolean resetHotlistNative(int iface, int id); 1609 1610 synchronized public static boolean setHotlist(WifiScanner.HotlistSettings settings, 1611 HotlistEventHandler eventHandler) { 1612 synchronized (mLock) { 1613 if (sWifiHalHandle != 0) { 1614 if (sHotlistCmdId != 0) { 1615 return false; 1616 } else { 1617 sHotlistCmdId = getNewCmdIdLocked(); 1618 } 1619 1620 sHotlistEventHandler = eventHandler; 1621 if (setHotlistNative(sWlan0Index, sHotlistCmdId, settings) == false) { 1622 sHotlistEventHandler = null; 1623 return false; 1624 } 1625 1626 return true; 1627 } else { 1628 return false; 1629 } 1630 } 1631 } 1632 1633 synchronized public static void resetHotlist() { 1634 synchronized (mLock) { 1635 if (sWifiHalHandle != 0) { 1636 if (sHotlistCmdId != 0) { 1637 resetHotlistNative(sWlan0Index, sHotlistCmdId); 1638 sHotlistCmdId = 0; 1639 sHotlistEventHandler = null; 1640 } 1641 } 1642 } 1643 } 1644 1645 synchronized public static void onHotlistApFound(int id, ScanResult[] results) { 1646 synchronized (mLock) { 1647 if (sWifiHalHandle != 0) { 1648 if (sHotlistCmdId != 0) { 1649 sHotlistEventHandler.onHotlistApFound(results); 1650 } else { 1651 /* this can happen because of race conditions */ 1652 Log.d(TAG, "Ignoring hotlist AP found event"); 1653 } 1654 } 1655 } 1656 } 1657 1658 synchronized public static void onHotlistApLost(int id, ScanResult[] results) { 1659 synchronized (mLock) { 1660 if (sWifiHalHandle != 0) { 1661 if (sHotlistCmdId != 0) { 1662 sHotlistEventHandler.onHotlistApLost(results); 1663 } else { 1664 /* this can happen because of race conditions */ 1665 Log.d(TAG, "Ignoring hotlist AP lost event"); 1666 } 1667 } 1668 } 1669 } 1670 1671 public static interface SignificantWifiChangeEventHandler { 1672 void onChangesFound(ScanResult[] result); 1673 } 1674 1675 private static SignificantWifiChangeEventHandler sSignificantWifiChangeHandler; 1676 private static int sSignificantWifiChangeCmdId; 1677 1678 private static native boolean trackSignificantWifiChangeNative( 1679 int iface, int id, WifiScanner.WifiChangeSettings settings); 1680 private static native boolean untrackSignificantWifiChangeNative(int iface, int id); 1681 1682 synchronized public static boolean trackSignificantWifiChange( 1683 WifiScanner.WifiChangeSettings settings, SignificantWifiChangeEventHandler handler) { 1684 synchronized (mLock) { 1685 if (sWifiHalHandle != 0) { 1686 if (sSignificantWifiChangeCmdId != 0) { 1687 return false; 1688 } else { 1689 sSignificantWifiChangeCmdId = getNewCmdIdLocked(); 1690 } 1691 1692 sSignificantWifiChangeHandler = handler; 1693 if (trackSignificantWifiChangeNative(sWlan0Index, sScanCmdId, settings) == false) { 1694 sSignificantWifiChangeHandler = null; 1695 return false; 1696 } 1697 1698 return true; 1699 } else { 1700 return false; 1701 } 1702 1703 } 1704 } 1705 1706 synchronized static void untrackSignificantWifiChange() { 1707 synchronized (mLock) { 1708 if (sWifiHalHandle != 0) { 1709 if (sSignificantWifiChangeCmdId != 0) { 1710 untrackSignificantWifiChangeNative(sWlan0Index, sSignificantWifiChangeCmdId); 1711 sSignificantWifiChangeCmdId = 0; 1712 sSignificantWifiChangeHandler = null; 1713 } 1714 } 1715 } 1716 } 1717 1718 synchronized static void onSignificantWifiChange(int id, ScanResult[] results) { 1719 synchronized (mLock) { 1720 if (sSignificantWifiChangeCmdId != 0) { 1721 sSignificantWifiChangeHandler.onChangesFound(results); 1722 } else { 1723 /* this can happen because of race conditions */ 1724 Log.d(TAG, "Ignoring significant wifi change"); 1725 } 1726 } 1727 } 1728 1729 synchronized public static WifiLinkLayerStats getWifiLinkLayerStats(String iface) { 1730 // TODO: use correct iface name to Index translation 1731 if (iface == null) return null; 1732 synchronized (mLock) { 1733 if (sWifiHalHandle != 0) { 1734 return getWifiLinkLayerStatsNative(sWlan0Index); 1735 } else { 1736 return null; 1737 } 1738 } 1739 } 1740 1741 synchronized public static void setWifiLinkLayerStats(String iface, int enable) { 1742 if (iface == null) return; 1743 synchronized (mLock) { 1744 if (sWifiHalHandle != 0) { 1745 setWifiLinkLayerStatsNative(sWlan0Index, enable); 1746 } 1747 } 1748 } 1749 1750 public static native int getSupportedFeatureSetNative(int iface); 1751 synchronized public static int getSupportedFeatureSet() { 1752 synchronized (mLock) { 1753 if (sWifiHalHandle != 0) { 1754 return getSupportedFeatureSetNative(sWlan0Index); 1755 } else { 1756 Log.d(TAG, "Failing getSupportedFeatureset because HAL isn't started"); 1757 return 0; 1758 } 1759 } 1760 } 1761 1762 /* Rtt related commands/events */ 1763 public static interface RttEventHandler { 1764 void onRttResults(RttManager.RttResult[] result); 1765 } 1766 1767 private static RttEventHandler sRttEventHandler; 1768 private static int sRttCmdId; 1769 1770 synchronized private static void onRttResults(int id, RttManager.RttResult[] results) { 1771 if (id == sRttCmdId) { 1772 Log.d(TAG, "Received " + results.length + " rtt results"); 1773 sRttEventHandler.onRttResults(results); 1774 sRttCmdId = 0; 1775 } else { 1776 Log.d(TAG, "RTT Received event for unknown cmd = " + id + ", current id = " + sRttCmdId); 1777 } 1778 } 1779 1780 private static native boolean requestRangeNative( 1781 int iface, int id, RttManager.RttParams[] params); 1782 private static native boolean cancelRangeRequestNative( 1783 int iface, int id, RttManager.RttParams[] params); 1784 1785 synchronized public static boolean requestRtt( 1786 RttManager.RttParams[] params, RttEventHandler handler) { 1787 synchronized (mLock) { 1788 if (sWifiHalHandle != 0) { 1789 if (sRttCmdId != 0) { 1790 Log.v("TAG", "Last one is still under measurement!"); 1791 return false; 1792 } else { 1793 sRttCmdId = getNewCmdIdLocked(); 1794 } 1795 sRttEventHandler = handler; 1796 Log.v(TAG, "native issue RTT request"); 1797 return requestRangeNative(sWlan0Index, sRttCmdId, params); 1798 } else { 1799 return false; 1800 } 1801 } 1802 } 1803 1804 synchronized public static boolean cancelRtt(RttManager.RttParams[] params) { 1805 synchronized(mLock) { 1806 if (sWifiHalHandle != 0) { 1807 if (sRttCmdId == 0) { 1808 return false; 1809 } 1810 1811 sRttCmdId = 0; 1812 1813 if (cancelRangeRequestNative(sWlan0Index, sRttCmdId, params)) { 1814 sRttEventHandler = null; 1815 Log.v(TAG, "Xin: RTT cancel Request Successfully"); 1816 return true; 1817 } else { 1818 Log.e(TAG, "Xin:RTT cancel Request failed"); 1819 return false; 1820 } 1821 } else { 1822 return false; 1823 } 1824 } 1825 } 1826 1827 private static native boolean setScanningMacOuiNative(int iface, byte[] oui); 1828 1829 synchronized public static boolean setScanningMacOui(byte[] oui) { 1830 synchronized (mLock) { 1831 if (sWifiHalHandle != 0) { 1832 return setScanningMacOuiNative(sWlan0Index, oui); 1833 } else { 1834 return false; 1835 } 1836 } 1837 } 1838 1839 private static native int[] getChannelsForBandNative( 1840 int iface, int band); 1841 1842 synchronized public static int [] getChannelsForBand(int band) { 1843 synchronized (mLock) { 1844 return getChannelsForBandNative(sWlan0Index, band); 1845 } 1846 } 1847 1848 1849 private static native boolean setDfsFlagNative(int iface, boolean dfsOn); 1850 synchronized public static boolean setDfsFlag(boolean dfsOn) { 1851 synchronized (mLock) { 1852 if (sWifiHalHandle != 0) { 1853 return setDfsFlagNative(sWlan0Index, dfsOn); 1854 } else { 1855 return false; 1856 } 1857 } 1858 } 1859 1860 private static native boolean toggleInterfaceNative(int on); 1861 synchronized public static boolean toggleInterface(int on) { 1862 synchronized (mLock) { 1863 if (sWifiHalHandle != 0) { 1864 return toggleInterfaceNative(0); 1865 } else { 1866 return false; 1867 } 1868 } 1869 } 1870 1871 private static native RttManager.RttCapabilities getRttCapabilitiesNative(int iface); 1872 synchronized public static RttManager.RttCapabilities getRttCapabilities() { 1873 synchronized (mLock) { 1874 if (sWifiHalHandle != 0) { 1875 return getRttCapabilitiesNative(sWlan0Index); 1876 }else { 1877 return null; 1878 } 1879 } 1880 } 1881 1882 private static native boolean setCountryCodeHalNative(int iface, String CountryCode); 1883 synchronized public static boolean setCountryCodeHal( String CountryCode) { 1884 synchronized (mLock) { 1885 if (sWifiHalHandle != 0) { 1886 return setCountryCodeHalNative(sWlan0Index, CountryCode); 1887 } else { 1888 return false; 1889 } 1890 } 1891 } 1892 1893 /* Rtt related commands/events */ 1894 public abstract class TdlsEventHandler { 1895 abstract public void onTdlsStatus(String macAddr, int status, int reason); 1896 } 1897 1898 private static TdlsEventHandler sTdlsEventHandler; 1899 1900 private static native boolean enableDisableTdlsNative(int iface, boolean enable, 1901 String macAddr); 1902 synchronized public static boolean enableDisableTdls(boolean enable, String macAdd, 1903 TdlsEventHandler tdlsCallBack) { 1904 synchronized (mLock) { 1905 sTdlsEventHandler = tdlsCallBack; 1906 return enableDisableTdlsNative(sWlan0Index, enable, macAdd); 1907 } 1908 } 1909 1910 // Once TDLS per mac and event feature is implemented, this class definition should be 1911 // moved to the right place, like WifiManager etc 1912 public static class TdlsStatus { 1913 int channel; 1914 int global_operating_class; 1915 int state; 1916 int reason; 1917 } 1918 private static native TdlsStatus getTdlsStatusNative(int iface, String macAddr); 1919 synchronized public static TdlsStatus getTdlsStatus (String macAdd) { 1920 synchronized (mLock) { 1921 if (sWifiHalHandle != 0) { 1922 return getTdlsStatusNative(sWlan0Index, macAdd); 1923 } else { 1924 return null; 1925 } 1926 } 1927 } 1928 1929 //ToFix: Once TDLS per mac and event feature is implemented, this class definition should be 1930 // moved to the right place, like WifiStateMachine etc 1931 public static class TdlsCapabilities { 1932 /* Maximum TDLS session number can be supported by the Firmware and hardware */ 1933 int maxConcurrentTdlsSessionNumber; 1934 boolean isGlobalTdlsSupported; 1935 boolean isPerMacTdlsSupported; 1936 boolean isOffChannelTdlsSupported; 1937 } 1938 1939 1940 1941 private static native TdlsCapabilities getTdlsCapabilitiesNative(int iface); 1942 synchronized public static TdlsCapabilities getTdlsCapabilities () { 1943 synchronized (mLock) { 1944 if (sWifiHalHandle != 0) { 1945 return getTdlsCapabilitiesNative(sWlan0Index); 1946 } else { 1947 return null; 1948 } 1949 } 1950 } 1951 1952 synchronized private static boolean onTdlsStatus(String macAddr, int status, int reason) { 1953 if (sTdlsEventHandler == null) { 1954 return false; 1955 } else { 1956 sTdlsEventHandler.onTdlsStatus(macAddr, status, reason); 1957 return true; 1958 } 1959 } 1960 1961 //--------------------------------------------------------------------------------- 1962 1963 /* Wifi Logger commands/events */ 1964 1965 public static native boolean startLogging(int iface); 1966 1967 public static interface WifiLoggerEventHandler { 1968 void onRingBufferData(RingBufferStatus status, byte[] buffer); 1969 void onWifiAlert(int errorCode, byte[] buffer); 1970 } 1971 1972 private static WifiLoggerEventHandler sWifiLoggerEventHandler = null; 1973 1974 private static void onRingBufferData(RingBufferStatus status, byte[] buffer) { 1975 if (sWifiLoggerEventHandler != null) 1976 sWifiLoggerEventHandler.onRingBufferData(status, buffer); 1977 } 1978 1979 private static void onWifiAlert(byte[] buffer, int errorCode) { 1980 if (sWifiLoggerEventHandler != null) 1981 sWifiLoggerEventHandler.onWifiAlert(errorCode, buffer); 1982 } 1983 1984 synchronized public static void setLoggingEventHandler(WifiLoggerEventHandler handler) { 1985 synchronized (mLock) { 1986 sWifiLoggerEventHandler = handler; 1987 } 1988 } 1989 1990 private static native boolean startLoggingRingBufferNative(int iface, int verboseLevel, 1991 int flags, int minIntervalSec ,int minDataSize, String ringName); 1992 synchronized public static boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, 1993 int minDataSize, String ringName){ 1994 synchronized (mLock) { 1995 if (sWifiHalHandle != 0) { 1996 return startLoggingRingBufferNative(sWlan0Index, verboseLevel, flags, maxInterval, 1997 minDataSize, ringName); 1998 } else { 1999 return false; 2000 } 2001 } 2002 } 2003 2004 private static native int getSupportedLoggerFeatureSetNative(int iface); 2005 synchronized public static int getSupportedLoggerFeatureSet() { 2006 synchronized (mLock) { 2007 if (sWifiHalHandle != 0) { 2008 return getSupportedLoggerFeatureSetNative(sWlan0Index); 2009 } else { 2010 return 0; 2011 } 2012 } 2013 } 2014 2015 private static native String getDriverVersionNative(int iface); 2016 synchronized public static String getDriverVersion() { 2017 synchronized (mLock) { 2018 if (sWifiHalHandle != 0) { 2019 return getDriverVersionNative(sWlan0Index); 2020 } else { 2021 return ""; 2022 } 2023 } 2024 } 2025 2026 2027 private static native String getFirmwareVersionNative(int iface); 2028 synchronized public static String getFirmwareVersion() { 2029 synchronized (mLock) { 2030 if (sWifiHalHandle != 0) { 2031 return getFirmwareVersionNative(sWlan0Index); 2032 } else { 2033 return ""; 2034 } 2035 } 2036 } 2037 2038 public static class RingBufferStatus{ 2039 String name; 2040 int flag; 2041 int ringBufferId; 2042 int ringBufferByteSize; 2043 int verboseLevel; 2044 int writtenBytes; 2045 int readBytes; 2046 int writtenRecords; 2047 2048 @Override 2049 public String toString() { 2050 return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId + 2051 " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel + 2052 " writtenBytes: " + writtenBytes + " readBytes: " + readBytes + 2053 " writtenRecords: " + writtenRecords; 2054 } 2055 } 2056 2057 private static native RingBufferStatus[] getRingBufferStatusNative(int iface); 2058 synchronized public static RingBufferStatus[] getRingBufferStatus() { 2059 synchronized (mLock) { 2060 if (sWifiHalHandle != 0) { 2061 return getRingBufferStatusNative(sWlan0Index); 2062 } else { 2063 return null; 2064 } 2065 } 2066 } 2067 2068 private static native boolean getRingBufferDataNative(int iface, String ringName); 2069 synchronized public static boolean getRingBufferData(String ringName) { 2070 synchronized (mLock) { 2071 if (sWifiHalHandle != 0) { 2072 return getRingBufferDataNative(sWlan0Index, ringName); 2073 } else { 2074 return false; 2075 } 2076 } 2077 } 2078 2079 static private byte[] mFwMemoryDump; 2080 private static void onWifiFwMemoryAvailable(byte[] buffer) { 2081 mFwMemoryDump = buffer; 2082 if (DBG) { 2083 Log.d(TAG, "onWifiFwMemoryAvailable is called and buffer length is: " + 2084 (buffer == null ? 0 : buffer.length)); 2085 } 2086 } 2087 private static native boolean getFwMemoryDumpNative(int iface); 2088 synchronized public static byte[] getFwMemoryDump() { 2089 synchronized (mLock) { 2090 if (sWifiHalHandle != 0) { 2091 if(getFwMemoryDumpNative(sWlan0Index)) { 2092 byte[] fwMemoryDump = mFwMemoryDump; 2093 mFwMemoryDump = null; 2094 return fwMemoryDump; 2095 } else { 2096 return null; 2097 } 2098 } 2099 2100 return null; 2101 } 2102 } 2103 2104 //--------------------------------------------------------------------------------- 2105 /* Configure ePNO */ 2106 2107 public class WifiPnoNetwork { 2108 String SSID; 2109 int rssi_threshold; 2110 int flags; 2111 int auth; 2112 String configKey; // kept for reference 2113 2114 WifiPnoNetwork(WifiConfiguration config, int threshold) { 2115 if (config.SSID == null) { 2116 this.SSID = ""; 2117 this.flags = 1; 2118 } else { 2119 this.SSID = config.SSID; 2120 } 2121 this.rssi_threshold = threshold; 2122 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { 2123 auth |= 2; 2124 } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) || 2125 config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) { 2126 auth |= 4; 2127 } else if (config.wepKeys[0] != null) { 2128 auth |= 1; 2129 } else { 2130 auth |= 1; 2131 } 2132// auth = 0; 2133 flags |= 6; //A and G 2134 configKey = config.configKey(); 2135 } 2136 2137 @Override 2138 public String toString() { 2139 StringBuilder sbuf = new StringBuilder(); 2140 sbuf.append(this.SSID); 2141 sbuf.append(" flags=").append(this.flags); 2142 sbuf.append(" rssi=").append(this.rssi_threshold); 2143 sbuf.append(" auth=").append(this.auth); 2144 return sbuf.toString(); 2145 } 2146 } 2147 2148 public static interface WifiPnoEventHandler { 2149 void onPnoNetworkFound(ScanResult results[]); 2150 } 2151 2152 private static WifiPnoEventHandler sWifiPnoEventHandler; 2153 2154 private static int sPnoCmdId = 0; 2155 2156 private native static boolean setPnoListNative(int iface, int id, WifiPnoNetwork list[]); 2157 2158 synchronized public static boolean setPnoList(WifiPnoNetwork list[], 2159 WifiPnoEventHandler eventHandler) { 2160 Log.e(TAG, "setPnoList cmd " + sPnoCmdId); 2161 2162 synchronized (mLock) { 2163 if (sWifiHalHandle != 0) { 2164 2165 sPnoCmdId = getNewCmdIdLocked(); 2166 2167 sWifiPnoEventHandler = eventHandler; 2168 if (setPnoListNative(sWlan0Index, sPnoCmdId, list)) { 2169 return true; 2170 } 2171 } 2172 2173 sWifiPnoEventHandler = null; 2174 return false; 2175 } 2176 } 2177 2178 synchronized public static void onPnoNetworkFound(int id, ScanResult[] results) { 2179 2180 if (results == null) { 2181 Log.e(TAG, "onPnoNetworkFound null results"); 2182 return; 2183 2184 } 2185 Log.d(TAG, "WifiNative.onPnoNetworkFound result " + results.length); 2186 2187 //Log.e(TAG, "onPnoNetworkFound length " + results.length); 2188 //return; 2189 for (int i=0; i<results.length; i++) { 2190 Log.e(TAG, "onPnoNetworkFound SSID " + results[i].SSID 2191 + " " + results[i].level + " " + results[i].frequency); 2192 2193 populateScanResult(results[i], results[i].bytes, "onPnoNetworkFound "); 2194 results[i].wifiSsid = WifiSsid.createFromAsciiEncoded(results[i].SSID); 2195 } 2196 synchronized (mLock) { 2197 if (sPnoCmdId != 0 && sWifiPnoEventHandler != null) { 2198 sWifiPnoEventHandler.onPnoNetworkFound(results); 2199 } else { 2200 /* this can happen because of race conditions */ 2201 Log.d(TAG, "Ignoring Pno Network found event"); 2202 } 2203 } 2204 } 2205 2206 public class WifiLazyRoamParams { 2207 int A_band_boost_threshold; 2208 int A_band_penalty_threshold; 2209 int A_band_boost_factor; 2210 int A_band_penalty_factor; 2211 int A_band_max_boost; 2212 int lazy_roam_hysteresis; 2213 int alert_roam_rssi_trigger; 2214 2215 WifiLazyRoamParams() { 2216 } 2217 2218 @Override 2219 public String toString() { 2220 StringBuilder sbuf = new StringBuilder(); 2221 sbuf.append(" A_band_boost_threshold=").append(this.A_band_boost_threshold); 2222 sbuf.append(" A_band_penalty_threshold=").append(this.A_band_penalty_threshold); 2223 sbuf.append(" A_band_boost_factor=").append(this.A_band_boost_factor); 2224 sbuf.append(" A_band_penalty_factor=").append(this.A_band_penalty_factor); 2225 sbuf.append(" A_band_max_boost=").append(this.A_band_max_boost); 2226 sbuf.append(" lazy_roam_hysteresis=").append(this.lazy_roam_hysteresis); 2227 sbuf.append(" alert_roam_rssi_trigger=").append(this.alert_roam_rssi_trigger); 2228 return sbuf.toString(); 2229 } 2230 } 2231 2232 private native static boolean setLazyRoamNative(int iface, int id, 2233 boolean enabled, WifiLazyRoamParams param); 2234 2235 synchronized public static boolean setLazyRoam(boolean enabled, WifiLazyRoamParams params) { 2236 synchronized (mLock) { 2237 if (sWifiHalHandle != 0) { 2238 sPnoCmdId = getNewCmdIdLocked(); 2239 return setLazyRoamNative(sWlan0Index, sPnoCmdId, enabled, params); 2240 } else { 2241 return false; 2242 } 2243 } 2244 } 2245 2246 private native static boolean setBssidBlacklistNative(int iface, int id, 2247 String list[]); 2248 2249 synchronized public static boolean setBssidBlacklist(String list[]) { 2250 int size = 0; 2251 if (list != null) { 2252 size = list.length; 2253 } 2254 Log.e(TAG, "setBssidBlacklist cmd " + sPnoCmdId + " size " + size); 2255 2256 synchronized (mLock) { 2257 if (sWifiHalHandle != 0) { 2258 sPnoCmdId = getNewCmdIdLocked(); 2259 return setBssidBlacklistNative(sWlan0Index, sPnoCmdId, list); 2260 } else { 2261 return false; 2262 } 2263 } 2264 } 2265 2266 private native static boolean setSsidWhitelistNative(int iface, int id, String list[]); 2267 2268 synchronized public static boolean setSsidWhitelist(String list[]) { 2269 int size = 0; 2270 if (list != null) { 2271 size = list.length; 2272 } 2273 Log.e(TAG, "setSsidWhitelist cmd " + sPnoCmdId + " size " + size); 2274 2275 synchronized (mLock) { 2276 if (sWifiHalHandle != 0) { 2277 sPnoCmdId = getNewCmdIdLocked(); 2278 2279 return setSsidWhitelistNative(sWlan0Index, sPnoCmdId, list); 2280 } else { 2281 return false; 2282 } 2283 } 2284 } 2285} 2286