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 17 package com.android.server.wifi; 18 19 import android.annotation.Nullable; 20 import android.app.AlarmManager; 21 import android.app.PendingIntent; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.net.apf.ApfCapabilities; 27 import android.net.wifi.RttManager; 28 import android.net.wifi.RttManager.ResponderConfig; 29 import android.net.wifi.ScanResult; 30 import android.net.wifi.WifiConfiguration; 31 import android.net.wifi.WifiEnterpriseConfig; 32 import android.net.wifi.WifiLinkLayerStats; 33 import android.net.wifi.WifiManager; 34 import android.net.wifi.WifiScanner; 35 import android.net.wifi.WifiSsid; 36 import android.net.wifi.WifiWakeReasonAndCounts; 37 import android.net.wifi.WpsInfo; 38 import android.net.wifi.p2p.WifiP2pConfig; 39 import android.net.wifi.p2p.WifiP2pGroup; 40 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; 41 import android.os.SystemClock; 42 import android.os.SystemProperties; 43 import android.text.TextUtils; 44 import android.util.LocalLog; 45 import android.util.Log; 46 47 import com.android.internal.annotations.Immutable; 48 import com.android.internal.util.HexDump; 49 import com.android.server.connectivity.KeepalivePacketData; 50 import com.android.server.wifi.hotspot2.NetworkDetail; 51 import com.android.server.wifi.hotspot2.SupplicantBridge; 52 import com.android.server.wifi.hotspot2.Utils; 53 import com.android.server.wifi.util.FrameParser; 54 import com.android.server.wifi.util.InformationElementUtil; 55 56 import libcore.util.HexEncoding; 57 58 import org.json.JSONException; 59 import org.json.JSONObject; 60 61 import java.io.PrintWriter; 62 import java.io.StringWriter; 63 import java.io.UnsupportedEncodingException; 64 import java.net.URLDecoder; 65 import java.net.URLEncoder; 66 import java.nio.ByteBuffer; 67 import java.nio.CharBuffer; 68 import java.nio.charset.CharacterCodingException; 69 import java.nio.charset.CharsetDecoder; 70 import java.nio.charset.StandardCharsets; 71 import java.text.SimpleDateFormat; 72 import java.util.ArrayList; 73 import java.util.BitSet; 74 import java.util.Date; 75 import java.util.HashMap; 76 import java.util.Iterator; 77 import java.util.List; 78 import java.util.Locale; 79 import java.util.Map; 80 import java.util.Set; 81 import java.util.TimeZone; 82 83 84 /** 85 * Native calls for bring up/shut down of the supplicant daemon and for 86 * sending requests to the supplicant daemon 87 * 88 * waitForEvent() is called on the monitor thread for events. All other methods 89 * must be serialized from the framework. 90 * 91 * {@hide} 92 */ 93 public class WifiNative { 94 private static boolean DBG = false; 95 96 // Must match wifi_hal.h 97 public static final int WIFI_SUCCESS = 0; 98 99 /** 100 * Hold this lock before calling supplicant or HAL methods 101 * it is required to mutually exclude access to the driver 102 */ 103 public static final Object sLock = new Object(); 104 105 private static final LocalLog sLocalLog = new LocalLog(8192); 106 getLocalLog()107 public static LocalLog getLocalLog() { 108 return sLocalLog; 109 } 110 111 /* Register native functions */ 112 static { 113 /* Native functions are defined in libwifi-service.so */ 114 System.loadLibrary("wifi-service"); registerNatives()115 registerNatives(); 116 } 117 registerNatives()118 private static native int registerNatives(); 119 120 /* 121 * Singleton WifiNative instances 122 */ 123 private static WifiNative wlanNativeInterface = 124 new WifiNative(SystemProperties.get("wifi.interface", "wlan0"), true); getWlanNativeInterface()125 public static WifiNative getWlanNativeInterface() { 126 return wlanNativeInterface; 127 } 128 129 private static WifiNative p2pNativeInterface = 130 // commands for p2p0 interface don't need prefix 131 new WifiNative(SystemProperties.get("wifi.direct.interface", "p2p0"), false); getP2pNativeInterface()132 public static WifiNative getP2pNativeInterface() { 133 return p2pNativeInterface; 134 } 135 136 137 private final String mTAG; 138 private final String mInterfaceName; 139 private final String mInterfacePrefix; 140 141 private Context mContext = null; initContext(Context context)142 public void initContext(Context context) { 143 if (mContext == null && context != null) { 144 mContext = context; 145 } 146 } 147 WifiNative(String interfaceName, boolean requiresPrefix)148 private WifiNative(String interfaceName, 149 boolean requiresPrefix) { 150 mInterfaceName = interfaceName; 151 mTAG = "WifiNative-" + interfaceName; 152 153 if (requiresPrefix) { 154 mInterfacePrefix = "IFNAME=" + interfaceName + " "; 155 } else { 156 mInterfacePrefix = ""; 157 } 158 } 159 getInterfaceName()160 public String getInterfaceName() { 161 return mInterfaceName; 162 } 163 164 // Note this affects logging on for all interfaces enableVerboseLogging(int verbose)165 void enableVerboseLogging(int verbose) { 166 if (verbose > 0) { 167 DBG = true; 168 } else { 169 DBG = false; 170 } 171 } 172 localLog(String s)173 private void localLog(String s) { 174 if (sLocalLog != null) sLocalLog.log(mInterfaceName + ": " + s); 175 } 176 177 178 179 /* 180 * Driver and Supplicant management 181 */ loadDriverNative()182 private native static boolean loadDriverNative(); loadDriver()183 public boolean loadDriver() { 184 synchronized (sLock) { 185 return loadDriverNative(); 186 } 187 } 188 isDriverLoadedNative()189 private native static boolean isDriverLoadedNative(); isDriverLoaded()190 public boolean isDriverLoaded() { 191 synchronized (sLock) { 192 return isDriverLoadedNative(); 193 } 194 } 195 unloadDriverNative()196 private native static boolean unloadDriverNative(); unloadDriver()197 public boolean unloadDriver() { 198 synchronized (sLock) { 199 return unloadDriverNative(); 200 } 201 } 202 startSupplicantNative(boolean p2pSupported)203 private native static boolean startSupplicantNative(boolean p2pSupported); startSupplicant(boolean p2pSupported)204 public boolean startSupplicant(boolean p2pSupported) { 205 synchronized (sLock) { 206 return startSupplicantNative(p2pSupported); 207 } 208 } 209 210 /* Sends a kill signal to supplicant. To be used when we have lost connection 211 or when the supplicant is hung */ killSupplicantNative(boolean p2pSupported)212 private native static boolean killSupplicantNative(boolean p2pSupported); killSupplicant(boolean p2pSupported)213 public boolean killSupplicant(boolean p2pSupported) { 214 synchronized (sLock) { 215 return killSupplicantNative(p2pSupported); 216 } 217 } 218 connectToSupplicantNative()219 private native static boolean connectToSupplicantNative(); connectToSupplicant()220 public boolean connectToSupplicant() { 221 synchronized (sLock) { 222 localLog(mInterfacePrefix + "connectToSupplicant"); 223 return connectToSupplicantNative(); 224 } 225 } 226 closeSupplicantConnectionNative()227 private native static void closeSupplicantConnectionNative(); closeSupplicantConnection()228 public void closeSupplicantConnection() { 229 synchronized (sLock) { 230 localLog(mInterfacePrefix + "closeSupplicantConnection"); 231 closeSupplicantConnectionNative(); 232 } 233 } 234 235 /** 236 * Wait for the supplicant to send an event, returning the event string. 237 * @return the event string sent by the supplicant. 238 */ waitForEventNative()239 private native static String waitForEventNative(); waitForEvent()240 public String waitForEvent() { 241 // No synchronization necessary .. it is implemented in WifiMonitor 242 return waitForEventNative(); 243 } 244 245 246 /* 247 * Supplicant Command Primitives 248 */ doBooleanCommandNative(String command)249 private native boolean doBooleanCommandNative(String command); 250 doIntCommandNative(String command)251 private native int doIntCommandNative(String command); 252 doStringCommandNative(String command)253 private native String doStringCommandNative(String command); 254 doBooleanCommand(String command)255 private boolean doBooleanCommand(String command) { 256 if (DBG) Log.d(mTAG, "doBoolean: " + command); 257 synchronized (sLock) { 258 String toLog = mInterfacePrefix + command; 259 boolean result = doBooleanCommandNative(mInterfacePrefix + command); 260 localLog(toLog + " -> " + result); 261 if (DBG) Log.d(mTAG, command + ": returned " + result); 262 return result; 263 } 264 } 265 doBooleanCommandWithoutLogging(String command)266 private boolean doBooleanCommandWithoutLogging(String command) { 267 if (DBG) Log.d(mTAG, "doBooleanCommandWithoutLogging: " + command); 268 synchronized (sLock) { 269 boolean result = doBooleanCommandNative(mInterfacePrefix + command); 270 if (DBG) Log.d(mTAG, command + ": returned " + result); 271 return result; 272 } 273 } 274 doIntCommand(String command)275 private int doIntCommand(String command) { 276 if (DBG) Log.d(mTAG, "doInt: " + command); 277 synchronized (sLock) { 278 String toLog = mInterfacePrefix + command; 279 int result = doIntCommandNative(mInterfacePrefix + command); 280 localLog(toLog + " -> " + result); 281 if (DBG) Log.d(mTAG, " returned " + result); 282 return result; 283 } 284 } 285 doStringCommand(String command)286 private String doStringCommand(String command) { 287 if (DBG) { 288 //GET_NETWORK commands flood the logs 289 if (!command.startsWith("GET_NETWORK")) { 290 Log.d(mTAG, "doString: [" + command + "]"); 291 } 292 } 293 synchronized (sLock) { 294 String toLog = mInterfacePrefix + command; 295 String result = doStringCommandNative(mInterfacePrefix + command); 296 if (result == null) { 297 if (DBG) Log.d(mTAG, "doStringCommandNative no result"); 298 } else { 299 if (!command.startsWith("STATUS-")) { 300 localLog(toLog + " -> " + result); 301 } 302 if (DBG) Log.d(mTAG, " returned " + result.replace("\n", " ")); 303 } 304 return result; 305 } 306 } 307 doStringCommandWithoutLogging(String command)308 private String doStringCommandWithoutLogging(String command) { 309 if (DBG) { 310 //GET_NETWORK commands flood the logs 311 if (!command.startsWith("GET_NETWORK")) { 312 Log.d(mTAG, "doString: [" + command + "]"); 313 } 314 } 315 synchronized (sLock) { 316 return doStringCommandNative(mInterfacePrefix + command); 317 } 318 } 319 doCustomSupplicantCommand(String command)320 public String doCustomSupplicantCommand(String command) { 321 return doStringCommand(command); 322 } 323 324 /* 325 * Wrappers for supplicant commands 326 */ ping()327 public boolean ping() { 328 String pong = doStringCommand("PING"); 329 return (pong != null && pong.equals("PONG")); 330 } 331 setSupplicantLogLevel(String level)332 public void setSupplicantLogLevel(String level) { 333 doStringCommand("LOG_LEVEL " + level); 334 } 335 getFreqCapability()336 public String getFreqCapability() { 337 return doStringCommand("GET_CAPABILITY freq"); 338 } 339 340 /** 341 * Create a comma separate string from integer set. 342 * @param values List of integers. 343 * @return comma separated string. 344 */ createCSVStringFromIntegerSet(Set<Integer> values)345 private static String createCSVStringFromIntegerSet(Set<Integer> values) { 346 StringBuilder list = new StringBuilder(); 347 boolean first = true; 348 for (Integer value : values) { 349 if (!first) { 350 list.append(","); 351 } 352 list.append(value); 353 first = false; 354 } 355 return list.toString(); 356 } 357 358 /** 359 * Start a scan using wpa_supplicant for the given frequencies. 360 * @param freqs list of frequencies to scan for, if null scan all supported channels. 361 * @param hiddenNetworkIds List of hidden networks to be scanned for. 362 */ scan(Set<Integer> freqs, Set<Integer> hiddenNetworkIds)363 public boolean scan(Set<Integer> freqs, Set<Integer> hiddenNetworkIds) { 364 String freqList = null; 365 String hiddenNetworkIdList = null; 366 if (freqs != null && freqs.size() != 0) { 367 freqList = createCSVStringFromIntegerSet(freqs); 368 } 369 if (hiddenNetworkIds != null && hiddenNetworkIds.size() != 0) { 370 hiddenNetworkIdList = createCSVStringFromIntegerSet(hiddenNetworkIds); 371 } 372 return scanWithParams(freqList, hiddenNetworkIdList); 373 } 374 scanWithParams(String freqList, String hiddenNetworkIdList)375 private boolean scanWithParams(String freqList, String hiddenNetworkIdList) { 376 StringBuilder scanCommand = new StringBuilder(); 377 scanCommand.append("SCAN TYPE=ONLY"); 378 if (freqList != null) { 379 scanCommand.append(" freq=" + freqList); 380 } 381 if (hiddenNetworkIdList != null) { 382 scanCommand.append(" scan_id=" + hiddenNetworkIdList); 383 } 384 return doBooleanCommand(scanCommand.toString()); 385 } 386 387 /* Does a graceful shutdown of supplicant. Is a common stop function for both p2p and sta. 388 * 389 * Note that underneath we use a harsh-sounding "terminate" supplicant command 390 * for a graceful stop and a mild-sounding "stop" interface 391 * to kill the process 392 */ stopSupplicant()393 public boolean stopSupplicant() { 394 return doBooleanCommand("TERMINATE"); 395 } 396 listNetworks()397 public String listNetworks() { 398 return doStringCommand("LIST_NETWORKS"); 399 } 400 listNetworks(int last_id)401 public String listNetworks(int last_id) { 402 return doStringCommand("LIST_NETWORKS LAST_ID=" + last_id); 403 } 404 addNetwork()405 public int addNetwork() { 406 return doIntCommand("ADD_NETWORK"); 407 } 408 setNetworkExtra(int netId, String name, Map<String, String> values)409 public boolean setNetworkExtra(int netId, String name, Map<String, String> values) { 410 final String encoded; 411 try { 412 encoded = URLEncoder.encode(new JSONObject(values).toString(), "UTF-8"); 413 } catch (NullPointerException e) { 414 Log.e(TAG, "Unable to serialize networkExtra: " + e.toString()); 415 return false; 416 } catch (UnsupportedEncodingException e) { 417 Log.e(TAG, "Unable to serialize networkExtra: " + e.toString()); 418 return false; 419 } 420 return setNetworkVariable(netId, name, "\"" + encoded + "\""); 421 } 422 setNetworkVariable(int netId, String name, String value)423 public boolean setNetworkVariable(int netId, String name, String value) { 424 if (TextUtils.isEmpty(name) || TextUtils.isEmpty(value)) return false; 425 if (name.equals(WifiConfiguration.pskVarName) 426 || name.equals(WifiEnterpriseConfig.PASSWORD_KEY)) { 427 return doBooleanCommandWithoutLogging("SET_NETWORK " + netId + " " + name + " " + value); 428 } else { 429 return doBooleanCommand("SET_NETWORK " + netId + " " + name + " " + value); 430 } 431 } 432 getNetworkExtra(int netId, String name)433 public Map<String, String> getNetworkExtra(int netId, String name) { 434 final String wrapped = getNetworkVariable(netId, name); 435 if (wrapped == null || !wrapped.startsWith("\"") || !wrapped.endsWith("\"")) { 436 return null; 437 } 438 try { 439 final String encoded = wrapped.substring(1, wrapped.length() - 1); 440 // This method reads a JSON dictionary that was written by setNetworkExtra(). However, 441 // on devices that upgraded from Marshmallow, it may encounter a legacy value instead - 442 // an FQDN stored as a plain string. If such a value is encountered, the JSONObject 443 // constructor will thrown a JSONException and the method will return null. 444 final JSONObject json = new JSONObject(URLDecoder.decode(encoded, "UTF-8")); 445 final Map<String, String> values = new HashMap<String, String>(); 446 final Iterator<?> it = json.keys(); 447 while (it.hasNext()) { 448 final String key = (String) it.next(); 449 final Object value = json.get(key); 450 if (value instanceof String) { 451 values.put(key, (String) value); 452 } 453 } 454 return values; 455 } catch (UnsupportedEncodingException e) { 456 Log.e(TAG, "Unable to deserialize networkExtra: " + e.toString()); 457 return null; 458 } catch (JSONException e) { 459 // This is not necessarily an error. This exception will also occur if we encounter a 460 // legacy FQDN stored as a plain string. We want to return null in this case as no JSON 461 // dictionary of extras was found. 462 return null; 463 } 464 } 465 getNetworkVariable(int netId, String name)466 public String getNetworkVariable(int netId, String name) { 467 if (TextUtils.isEmpty(name)) return null; 468 469 // GET_NETWORK will likely flood the logs ... 470 return doStringCommandWithoutLogging("GET_NETWORK " + netId + " " + name); 471 } 472 removeNetwork(int netId)473 public boolean removeNetwork(int netId) { 474 return doBooleanCommand("REMOVE_NETWORK " + netId); 475 } 476 477 logDbg(String debug)478 private void logDbg(String debug) { 479 long now = SystemClock.elapsedRealtimeNanos(); 480 String ts = String.format("[%,d us] ", now/1000); 481 Log.e("WifiNative: ", ts+debug+ " stack:" 482 + Thread.currentThread().getStackTrace()[2].getMethodName() +" - " 483 + Thread.currentThread().getStackTrace()[3].getMethodName() +" - " 484 + Thread.currentThread().getStackTrace()[4].getMethodName() +" - " 485 + Thread.currentThread().getStackTrace()[5].getMethodName()+" - " 486 + Thread.currentThread().getStackTrace()[6].getMethodName()); 487 488 } 489 490 /** 491 * Enables a network in wpa_supplicant. 492 * @param netId - Network ID of the network to be enabled. 493 * @return true if command succeeded, false otherwise. 494 */ enableNetwork(int netId)495 public boolean enableNetwork(int netId) { 496 if (DBG) logDbg("enableNetwork nid=" + Integer.toString(netId)); 497 return doBooleanCommand("ENABLE_NETWORK " + netId); 498 } 499 500 /** 501 * Enable a network in wpa_supplicant, do not connect. 502 * @param netId - Network ID of the network to be enabled. 503 * @return true if command succeeded, false otherwise. 504 */ enableNetworkWithoutConnect(int netId)505 public boolean enableNetworkWithoutConnect(int netId) { 506 if (DBG) logDbg("enableNetworkWithoutConnect nid=" + Integer.toString(netId)); 507 return doBooleanCommand("ENABLE_NETWORK " + netId + " " + "no-connect"); 508 } 509 510 /** 511 * Disables a network in wpa_supplicant. 512 * @param netId - Network ID of the network to be disabled. 513 * @return true if command succeeded, false otherwise. 514 */ disableNetwork(int netId)515 public boolean disableNetwork(int netId) { 516 if (DBG) logDbg("disableNetwork nid=" + Integer.toString(netId)); 517 return doBooleanCommand("DISABLE_NETWORK " + netId); 518 } 519 520 /** 521 * Select a network in wpa_supplicant (Disables all others). 522 * @param netId - Network ID of the network to be selected. 523 * @return true if command succeeded, false otherwise. 524 */ selectNetwork(int netId)525 public boolean selectNetwork(int netId) { 526 if (DBG) logDbg("selectNetwork nid=" + Integer.toString(netId)); 527 return doBooleanCommand("SELECT_NETWORK " + netId); 528 } 529 reconnect()530 public boolean reconnect() { 531 if (DBG) logDbg("RECONNECT "); 532 return doBooleanCommand("RECONNECT"); 533 } 534 reassociate()535 public boolean reassociate() { 536 if (DBG) logDbg("REASSOCIATE "); 537 return doBooleanCommand("REASSOCIATE"); 538 } 539 disconnect()540 public boolean disconnect() { 541 if (DBG) logDbg("DISCONNECT "); 542 return doBooleanCommand("DISCONNECT"); 543 } 544 status()545 public String status() { 546 return status(false); 547 } 548 status(boolean noEvents)549 public String status(boolean noEvents) { 550 if (noEvents) { 551 return doStringCommand("STATUS-NO_EVENTS"); 552 } else { 553 return doStringCommand("STATUS"); 554 } 555 } 556 getMacAddress()557 public String getMacAddress() { 558 //Macaddr = XX.XX.XX.XX.XX.XX 559 String ret = doStringCommand("DRIVER MACADDR"); 560 if (!TextUtils.isEmpty(ret)) { 561 String[] tokens = ret.split(" = "); 562 if (tokens.length == 2) return tokens[1]; 563 } 564 return null; 565 } 566 567 568 569 /** 570 * Format of results: 571 * ================= 572 * id=1 573 * bssid=68:7f:76:d7:1a:6e 574 * freq=2412 575 * level=-44 576 * tsf=1344626243700342 577 * flags=[WPA2-PSK-CCMP][WPS][ESS] 578 * ssid=zfdy 579 * ==== 580 * id=2 581 * bssid=68:5f:74:d7:1a:6f 582 * freq=5180 583 * level=-73 584 * tsf=1344626243700373 585 * flags=[WPA2-PSK-CCMP][WPS][ESS] 586 * ssid=zuby 587 * ==== 588 * 589 * RANGE=ALL gets all scan results 590 * RANGE=ID- gets results from ID 591 * MASK=<N> BSS command information mask. 592 * 593 * The mask used in this method, 0x29d87, gets the following fields: 594 * 595 * WPA_BSS_MASK_ID (Bit 0) 596 * WPA_BSS_MASK_BSSID (Bit 1) 597 * WPA_BSS_MASK_FREQ (Bit 2) 598 * WPA_BSS_MASK_LEVEL (Bit 7) 599 * WPA_BSS_MASK_TSF (Bit 8) 600 * WPA_BSS_MASK_IE (Bit 10) 601 * WPA_BSS_MASK_FLAGS (Bit 11) 602 * WPA_BSS_MASK_SSID (Bit 12) 603 * WPA_BSS_MASK_INTERNETW (Bit 15) (adds ANQP info) 604 * WPA_BSS_MASK_DELIM (Bit 17) 605 * 606 * See wpa_supplicant/src/common/wpa_ctrl.h for details. 607 */ getRawScanResults(String range)608 private String getRawScanResults(String range) { 609 return doStringCommandWithoutLogging("BSS RANGE=" + range + " MASK=0x29d87"); 610 } 611 612 private static final String BSS_IE_STR = "ie="; 613 private static final String BSS_ID_STR = "id="; 614 private static final String BSS_BSSID_STR = "bssid="; 615 private static final String BSS_FREQ_STR = "freq="; 616 private static final String BSS_LEVEL_STR = "level="; 617 private static final String BSS_TSF_STR = "tsf="; 618 private static final String BSS_FLAGS_STR = "flags="; 619 private static final String BSS_SSID_STR = "ssid="; 620 private static final String BSS_DELIMITER_STR = "===="; 621 private static final String BSS_END_STR = "####"; 622 getScanResults()623 public ArrayList<ScanDetail> getScanResults() { 624 int next_sid = 0; 625 ArrayList<ScanDetail> results = new ArrayList<>(); 626 while(next_sid >= 0) { 627 String rawResult = getRawScanResults(next_sid+"-"); 628 next_sid = -1; 629 630 if (TextUtils.isEmpty(rawResult)) 631 break; 632 633 String[] lines = rawResult.split("\n"); 634 635 636 // note that all these splits and substrings keep references to the original 637 // huge string buffer while the amount we really want is generally pretty small 638 // so make copies instead (one example b/11087956 wasted 400k of heap here). 639 final int bssidStrLen = BSS_BSSID_STR.length(); 640 final int flagLen = BSS_FLAGS_STR.length(); 641 642 String bssid = ""; 643 int level = 0; 644 int freq = 0; 645 long tsf = 0; 646 String flags = ""; 647 WifiSsid wifiSsid = null; 648 String infoElementsStr = null; 649 List<String> anqpLines = null; 650 651 for (String line : lines) { 652 if (line.startsWith(BSS_ID_STR)) { // Will find the last id line 653 try { 654 next_sid = Integer.parseInt(line.substring(BSS_ID_STR.length())) + 1; 655 } catch (NumberFormatException e) { 656 // Nothing to do 657 } 658 } else if (line.startsWith(BSS_BSSID_STR)) { 659 bssid = new String(line.getBytes(), bssidStrLen, line.length() - bssidStrLen); 660 } else if (line.startsWith(BSS_FREQ_STR)) { 661 try { 662 freq = Integer.parseInt(line.substring(BSS_FREQ_STR.length())); 663 } catch (NumberFormatException e) { 664 freq = 0; 665 } 666 } else if (line.startsWith(BSS_LEVEL_STR)) { 667 try { 668 level = Integer.parseInt(line.substring(BSS_LEVEL_STR.length())); 669 /* some implementations avoid negative values by adding 256 670 * so we need to adjust for that here. 671 */ 672 if (level > 0) level -= 256; 673 } catch (NumberFormatException e) { 674 level = 0; 675 } 676 } else if (line.startsWith(BSS_TSF_STR)) { 677 try { 678 tsf = Long.parseLong(line.substring(BSS_TSF_STR.length())); 679 } catch (NumberFormatException e) { 680 tsf = 0; 681 } 682 } else if (line.startsWith(BSS_FLAGS_STR)) { 683 flags = new String(line.getBytes(), flagLen, line.length() - flagLen); 684 } else if (line.startsWith(BSS_SSID_STR)) { 685 wifiSsid = WifiSsid.createFromAsciiEncoded( 686 line.substring(BSS_SSID_STR.length())); 687 } else if (line.startsWith(BSS_IE_STR)) { 688 infoElementsStr = line; 689 } else if (SupplicantBridge.isAnqpAttribute(line)) { 690 if (anqpLines == null) { 691 anqpLines = new ArrayList<>(); 692 } 693 anqpLines.add(line); 694 } else if (line.startsWith(BSS_DELIMITER_STR) || line.startsWith(BSS_END_STR)) { 695 if (bssid != null) { 696 try { 697 if (infoElementsStr == null) { 698 throw new IllegalArgumentException("Null information element data"); 699 } 700 int seperator = infoElementsStr.indexOf('='); 701 if (seperator < 0) { 702 throw new IllegalArgumentException("No element separator"); 703 } 704 705 ScanResult.InformationElement[] infoElements = 706 InformationElementUtil.parseInformationElements( 707 Utils.hexToBytes(infoElementsStr.substring(seperator + 1))); 708 709 NetworkDetail networkDetail = new NetworkDetail(bssid, 710 infoElements, anqpLines, freq); 711 String xssid = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE; 712 if (!xssid.equals(networkDetail.getTrimmedSSID())) { 713 Log.d(TAG, String.format( 714 "Inconsistent SSID on BSSID '%s': '%s' vs '%s': %s", 715 bssid, xssid, networkDetail.getSSID(), infoElementsStr)); 716 } 717 718 if (networkDetail.hasInterworking()) { 719 if (DBG) Log.d(TAG, "HSNwk: '" + networkDetail); 720 } 721 ScanDetail scan = new ScanDetail(networkDetail, wifiSsid, bssid, flags, 722 level, freq, tsf, infoElements, anqpLines); 723 results.add(scan); 724 } catch (IllegalArgumentException iae) { 725 Log.d(TAG, "Failed to parse information elements: " + iae); 726 } 727 } 728 bssid = null; 729 level = 0; 730 freq = 0; 731 tsf = 0; 732 flags = ""; 733 wifiSsid = null; 734 infoElementsStr = null; 735 anqpLines = null; 736 } 737 } 738 } 739 return results; 740 } 741 742 /** 743 * Format of result: 744 * id=1016 745 * bssid=00:03:7f:40:84:10 746 * freq=2462 747 * beacon_int=200 748 * capabilities=0x0431 749 * qual=0 750 * noise=0 751 * level=-46 752 * tsf=0000002669008476 753 * age=5 754 * ie=00105143412d485332302d52322d54455354010882848b960c12182403010b0706555... 755 * flags=[WPA2-EAP-CCMP][ESS][P2P][HS20] 756 * ssid=QCA-HS20-R2-TEST 757 * p2p_device_name= 758 * p2p_config_methods=0x0SET_NE 759 * anqp_venue_name=02083d656e6757692d466920416c6c69616e63650a3239383920436f... 760 * anqp_network_auth_type=010000 761 * anqp_roaming_consortium=03506f9a05001bc504bd 762 * anqp_ip_addr_type_availability=0c 763 * anqp_nai_realm=0200300000246d61696c2e6578616d706c652e636f6d3b636973636f2... 764 * anqp_3gpp=000600040132f465 765 * anqp_domain_name=0b65786d61706c652e636f6d 766 * hs20_operator_friendly_name=11656e6757692d466920416c6c69616e63650e636869... 767 * hs20_wan_metrics=01c40900008001000000000a00 768 * hs20_connection_capability=0100000006140001061600000650000106bb010106bb0... 769 * hs20_osu_providers_list=0b5143412d4f53552d425353010901310015656e6757692d... 770 */ scanResult(String bssid)771 public String scanResult(String bssid) { 772 return doStringCommand("BSS " + bssid); 773 } 774 startDriver()775 public boolean startDriver() { 776 return doBooleanCommand("DRIVER START"); 777 } 778 stopDriver()779 public boolean stopDriver() { 780 return doBooleanCommand("DRIVER STOP"); 781 } 782 783 784 /** 785 * Start filtering out Multicast V4 packets 786 * @return {@code true} if the operation succeeded, {@code false} otherwise 787 * 788 * Multicast filtering rules work as follows: 789 * 790 * The driver can filter multicast (v4 and/or v6) and broadcast packets when in 791 * a power optimized mode (typically when screen goes off). 792 * 793 * In order to prevent the driver from filtering the multicast/broadcast packets, we have to 794 * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective 795 * 796 * DRIVER RXFILTER-ADD Num 797 * where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6 798 * 799 * and DRIVER RXFILTER-START 800 * In order to stop the usage of these rules, we do 801 * 802 * DRIVER RXFILTER-STOP 803 * DRIVER RXFILTER-REMOVE Num 804 * where Num is as described for RXFILTER-ADD 805 * 806 * The SETSUSPENDOPT driver command overrides the filtering rules 807 */ startFilteringMulticastV4Packets()808 public boolean startFilteringMulticastV4Packets() { 809 return doBooleanCommand("DRIVER RXFILTER-STOP") 810 && doBooleanCommand("DRIVER RXFILTER-REMOVE 2") 811 && doBooleanCommand("DRIVER RXFILTER-START"); 812 } 813 814 /** 815 * Stop filtering out Multicast V4 packets. 816 * @return {@code true} if the operation succeeded, {@code false} otherwise 817 */ stopFilteringMulticastV4Packets()818 public boolean stopFilteringMulticastV4Packets() { 819 return doBooleanCommand("DRIVER RXFILTER-STOP") 820 && doBooleanCommand("DRIVER RXFILTER-ADD 2") 821 && doBooleanCommand("DRIVER RXFILTER-START"); 822 } 823 824 /** 825 * Start filtering out Multicast V6 packets 826 * @return {@code true} if the operation succeeded, {@code false} otherwise 827 */ startFilteringMulticastV6Packets()828 public boolean startFilteringMulticastV6Packets() { 829 return doBooleanCommand("DRIVER RXFILTER-STOP") 830 && doBooleanCommand("DRIVER RXFILTER-REMOVE 3") 831 && doBooleanCommand("DRIVER RXFILTER-START"); 832 } 833 834 /** 835 * Stop filtering out Multicast V6 packets. 836 * @return {@code true} if the operation succeeded, {@code false} otherwise 837 */ stopFilteringMulticastV6Packets()838 public boolean stopFilteringMulticastV6Packets() { 839 return doBooleanCommand("DRIVER RXFILTER-STOP") 840 && doBooleanCommand("DRIVER RXFILTER-ADD 3") 841 && doBooleanCommand("DRIVER RXFILTER-START"); 842 } 843 844 /** 845 * Set the operational frequency band 846 * @param band One of 847 * {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO}, 848 * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ}, 849 * {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ}, 850 * @return {@code true} if the operation succeeded, {@code false} otherwise 851 */ setBand(int band)852 public boolean setBand(int band) { 853 String bandstr; 854 855 if (band == WifiManager.WIFI_FREQUENCY_BAND_5GHZ) 856 bandstr = "5G"; 857 else if (band == WifiManager.WIFI_FREQUENCY_BAND_2GHZ) 858 bandstr = "2G"; 859 else 860 bandstr = "AUTO"; 861 return doBooleanCommand("SET SETBAND " + bandstr); 862 } 863 864 public static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0; 865 public static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1; 866 public static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2; 867 /** 868 * Sets the bluetooth coexistence mode. 869 * 870 * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED}, 871 * {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or 872 * {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}. 873 * @return Whether the mode was successfully set. 874 */ setBluetoothCoexistenceMode(int mode)875 public boolean setBluetoothCoexistenceMode(int mode) { 876 return doBooleanCommand("DRIVER BTCOEXMODE " + mode); 877 } 878 879 /** 880 * Enable or disable Bluetooth coexistence scan mode. When this mode is on, 881 * some of the low-level scan parameters used by the driver are changed to 882 * reduce interference with A2DP streaming. 883 * 884 * @param isSet whether to enable or disable this mode 885 * @return {@code true} if the command succeeded, {@code false} otherwise. 886 */ setBluetoothCoexistenceScanMode(boolean setCoexScanMode)887 public boolean setBluetoothCoexistenceScanMode(boolean setCoexScanMode) { 888 if (setCoexScanMode) { 889 return doBooleanCommand("DRIVER BTCOEXSCAN-START"); 890 } else { 891 return doBooleanCommand("DRIVER BTCOEXSCAN-STOP"); 892 } 893 } 894 enableSaveConfig()895 public void enableSaveConfig() { 896 doBooleanCommand("SET update_config 1"); 897 } 898 saveConfig()899 public boolean saveConfig() { 900 return doBooleanCommand("SAVE_CONFIG"); 901 } 902 addToBlacklist(String bssid)903 public boolean addToBlacklist(String bssid) { 904 if (TextUtils.isEmpty(bssid)) return false; 905 return doBooleanCommand("BLACKLIST " + bssid); 906 } 907 clearBlacklist()908 public boolean clearBlacklist() { 909 return doBooleanCommand("BLACKLIST clear"); 910 } 911 setSuspendOptimizations(boolean enabled)912 public boolean setSuspendOptimizations(boolean enabled) { 913 if (enabled) { 914 return doBooleanCommand("DRIVER SETSUSPENDMODE 1"); 915 } else { 916 return doBooleanCommand("DRIVER SETSUSPENDMODE 0"); 917 } 918 } 919 setCountryCode(String countryCode)920 public boolean setCountryCode(String countryCode) { 921 if (countryCode != null) 922 return doBooleanCommand("DRIVER COUNTRY " + countryCode.toUpperCase(Locale.ROOT)); 923 else 924 return doBooleanCommand("DRIVER COUNTRY"); 925 } 926 927 /** 928 * Start/Stop PNO scan. 929 * @param enable boolean indicating whether PNO is being enabled or disabled. 930 */ setPnoScan(boolean enable)931 public boolean setPnoScan(boolean enable) { 932 String cmd = enable ? "SET pno 1" : "SET pno 0"; 933 return doBooleanCommand(cmd); 934 } 935 enableAutoConnect(boolean enable)936 public void enableAutoConnect(boolean enable) { 937 if (enable) { 938 doBooleanCommand("STA_AUTOCONNECT 1"); 939 } else { 940 doBooleanCommand("STA_AUTOCONNECT 0"); 941 } 942 } 943 setScanInterval(int scanInterval)944 public void setScanInterval(int scanInterval) { 945 doBooleanCommand("SCAN_INTERVAL " + scanInterval); 946 } 947 setHs20(boolean hs20)948 public void setHs20(boolean hs20) { 949 if (hs20) { 950 doBooleanCommand("SET HS20 1"); 951 } else { 952 doBooleanCommand("SET HS20 0"); 953 } 954 } 955 startTdls(String macAddr, boolean enable)956 public void startTdls(String macAddr, boolean enable) { 957 if (enable) { 958 synchronized (sLock) { 959 doBooleanCommand("TDLS_DISCOVER " + macAddr); 960 doBooleanCommand("TDLS_SETUP " + macAddr); 961 } 962 } else { 963 doBooleanCommand("TDLS_TEARDOWN " + macAddr); 964 } 965 } 966 967 /** Example output: 968 * RSSI=-65 969 * LINKSPEED=48 970 * NOISE=9999 971 * FREQUENCY=0 972 */ signalPoll()973 public String signalPoll() { 974 return doStringCommandWithoutLogging("SIGNAL_POLL"); 975 } 976 977 /** Example outout: 978 * TXGOOD=396 979 * TXBAD=1 980 */ pktcntPoll()981 public String pktcntPoll() { 982 return doStringCommand("PKTCNT_POLL"); 983 } 984 bssFlush()985 public void bssFlush() { 986 doBooleanCommand("BSS_FLUSH 0"); 987 } 988 startWpsPbc(String bssid)989 public boolean startWpsPbc(String bssid) { 990 if (TextUtils.isEmpty(bssid)) { 991 return doBooleanCommand("WPS_PBC"); 992 } else { 993 return doBooleanCommand("WPS_PBC " + bssid); 994 } 995 } 996 startWpsPbc(String iface, String bssid)997 public boolean startWpsPbc(String iface, String bssid) { 998 synchronized (sLock) { 999 if (TextUtils.isEmpty(bssid)) { 1000 return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC"); 1001 } else { 1002 return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC " + bssid); 1003 } 1004 } 1005 } 1006 startWpsPinKeypad(String pin)1007 public boolean startWpsPinKeypad(String pin) { 1008 if (TextUtils.isEmpty(pin)) return false; 1009 return doBooleanCommand("WPS_PIN any " + pin); 1010 } 1011 startWpsPinKeypad(String iface, String pin)1012 public boolean startWpsPinKeypad(String iface, String pin) { 1013 if (TextUtils.isEmpty(pin)) return false; 1014 synchronized (sLock) { 1015 return doBooleanCommandNative("IFNAME=" + iface + " WPS_PIN any " + pin); 1016 } 1017 } 1018 1019 startWpsPinDisplay(String bssid)1020 public String startWpsPinDisplay(String bssid) { 1021 if (TextUtils.isEmpty(bssid)) { 1022 return doStringCommand("WPS_PIN any"); 1023 } else { 1024 return doStringCommand("WPS_PIN " + bssid); 1025 } 1026 } 1027 startWpsPinDisplay(String iface, String bssid)1028 public String startWpsPinDisplay(String iface, String bssid) { 1029 synchronized (sLock) { 1030 if (TextUtils.isEmpty(bssid)) { 1031 return doStringCommandNative("IFNAME=" + iface + " WPS_PIN any"); 1032 } else { 1033 return doStringCommandNative("IFNAME=" + iface + " WPS_PIN " + bssid); 1034 } 1035 } 1036 } 1037 setExternalSim(boolean external)1038 public boolean setExternalSim(boolean external) { 1039 String value = external ? "1" : "0"; 1040 Log.d(TAG, "Setting external_sim to " + value); 1041 return doBooleanCommand("SET external_sim " + value); 1042 } 1043 simAuthResponse(int id, String type, String response)1044 public boolean simAuthResponse(int id, String type, String response) { 1045 // with type = GSM-AUTH, UMTS-AUTH or UMTS-AUTS 1046 return doBooleanCommand("CTRL-RSP-SIM-" + id + ":" + type + response); 1047 } 1048 simAuthFailedResponse(int id)1049 public boolean simAuthFailedResponse(int id) { 1050 // should be used with type GSM-AUTH 1051 return doBooleanCommand("CTRL-RSP-SIM-" + id + ":GSM-FAIL"); 1052 } 1053 umtsAuthFailedResponse(int id)1054 public boolean umtsAuthFailedResponse(int id) { 1055 // should be used with type UMTS-AUTH 1056 return doBooleanCommand("CTRL-RSP-SIM-" + id + ":UMTS-FAIL"); 1057 } 1058 simIdentityResponse(int id, String response)1059 public boolean simIdentityResponse(int id, String response) { 1060 return doBooleanCommand("CTRL-RSP-IDENTITY-" + id + ":" + response); 1061 } 1062 1063 /* Configures an access point connection */ startWpsRegistrar(String bssid, String pin)1064 public boolean startWpsRegistrar(String bssid, String pin) { 1065 if (TextUtils.isEmpty(bssid) || TextUtils.isEmpty(pin)) return false; 1066 return doBooleanCommand("WPS_REG " + bssid + " " + pin); 1067 } 1068 cancelWps()1069 public boolean cancelWps() { 1070 return doBooleanCommand("WPS_CANCEL"); 1071 } 1072 setPersistentReconnect(boolean enabled)1073 public boolean setPersistentReconnect(boolean enabled) { 1074 int value = (enabled == true) ? 1 : 0; 1075 return doBooleanCommand("SET persistent_reconnect " + value); 1076 } 1077 setDeviceName(String name)1078 public boolean setDeviceName(String name) { 1079 return doBooleanCommand("SET device_name " + name); 1080 } 1081 setDeviceType(String type)1082 public boolean setDeviceType(String type) { 1083 return doBooleanCommand("SET device_type " + type); 1084 } 1085 setConfigMethods(String cfg)1086 public boolean setConfigMethods(String cfg) { 1087 return doBooleanCommand("SET config_methods " + cfg); 1088 } 1089 setManufacturer(String value)1090 public boolean setManufacturer(String value) { 1091 return doBooleanCommand("SET manufacturer " + value); 1092 } 1093 setModelName(String value)1094 public boolean setModelName(String value) { 1095 return doBooleanCommand("SET model_name " + value); 1096 } 1097 setModelNumber(String value)1098 public boolean setModelNumber(String value) { 1099 return doBooleanCommand("SET model_number " + value); 1100 } 1101 setSerialNumber(String value)1102 public boolean setSerialNumber(String value) { 1103 return doBooleanCommand("SET serial_number " + value); 1104 } 1105 setP2pSsidPostfix(String postfix)1106 public boolean setP2pSsidPostfix(String postfix) { 1107 return doBooleanCommand("SET p2p_ssid_postfix " + postfix); 1108 } 1109 setP2pGroupIdle(String iface, int time)1110 public boolean setP2pGroupIdle(String iface, int time) { 1111 synchronized (sLock) { 1112 return doBooleanCommandNative("IFNAME=" + iface + " SET p2p_group_idle " + time); 1113 } 1114 } 1115 setPowerSave(boolean enabled)1116 public void setPowerSave(boolean enabled) { 1117 if (enabled) { 1118 doBooleanCommand("SET ps 1"); 1119 } else { 1120 doBooleanCommand("SET ps 0"); 1121 } 1122 } 1123 setP2pPowerSave(String iface, boolean enabled)1124 public boolean setP2pPowerSave(String iface, boolean enabled) { 1125 synchronized (sLock) { 1126 if (enabled) { 1127 return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 1"); 1128 } else { 1129 return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 0"); 1130 } 1131 } 1132 } 1133 setWfdEnable(boolean enable)1134 public boolean setWfdEnable(boolean enable) { 1135 return doBooleanCommand("SET wifi_display " + (enable ? "1" : "0")); 1136 } 1137 setWfdDeviceInfo(String hex)1138 public boolean setWfdDeviceInfo(String hex) { 1139 return doBooleanCommand("WFD_SUBELEM_SET 0 " + hex); 1140 } 1141 1142 /** 1143 * "sta" prioritizes STA connection over P2P and "p2p" prioritizes 1144 * P2P connection over STA 1145 */ setConcurrencyPriority(String s)1146 public boolean setConcurrencyPriority(String s) { 1147 return doBooleanCommand("P2P_SET conc_pref " + s); 1148 } 1149 p2pFind()1150 public boolean p2pFind() { 1151 return doBooleanCommand("P2P_FIND"); 1152 } 1153 p2pFind(int timeout)1154 public boolean p2pFind(int timeout) { 1155 if (timeout <= 0) { 1156 return p2pFind(); 1157 } 1158 return doBooleanCommand("P2P_FIND " + timeout); 1159 } 1160 p2pStopFind()1161 public boolean p2pStopFind() { 1162 return doBooleanCommand("P2P_STOP_FIND"); 1163 } 1164 p2pListen()1165 public boolean p2pListen() { 1166 return doBooleanCommand("P2P_LISTEN"); 1167 } 1168 p2pListen(int timeout)1169 public boolean p2pListen(int timeout) { 1170 if (timeout <= 0) { 1171 return p2pListen(); 1172 } 1173 return doBooleanCommand("P2P_LISTEN " + timeout); 1174 } 1175 p2pExtListen(boolean enable, int period, int interval)1176 public boolean p2pExtListen(boolean enable, int period, int interval) { 1177 if (enable && interval < period) { 1178 return false; 1179 } 1180 return doBooleanCommand("P2P_EXT_LISTEN" 1181 + (enable ? (" " + period + " " + interval) : "")); 1182 } 1183 p2pSetChannel(int lc, int oc)1184 public boolean p2pSetChannel(int lc, int oc) { 1185 if (DBG) Log.d(mTAG, "p2pSetChannel: lc="+lc+", oc="+oc); 1186 1187 synchronized (sLock) { 1188 if (lc >=1 && lc <= 11) { 1189 if (!doBooleanCommand("P2P_SET listen_channel " + lc)) { 1190 return false; 1191 } 1192 } else if (lc != 0) { 1193 return false; 1194 } 1195 1196 if (oc >= 1 && oc <= 165 ) { 1197 int freq = (oc <= 14 ? 2407 : 5000) + oc * 5; 1198 return doBooleanCommand("P2P_SET disallow_freq 1000-" 1199 + (freq - 5) + "," + (freq + 5) + "-6000"); 1200 } else if (oc == 0) { 1201 /* oc==0 disables "P2P_SET disallow_freq" (enables all freqs) */ 1202 return doBooleanCommand("P2P_SET disallow_freq \"\""); 1203 } 1204 } 1205 return false; 1206 } 1207 p2pFlush()1208 public boolean p2pFlush() { 1209 return doBooleanCommand("P2P_FLUSH"); 1210 } 1211 1212 private static final int DEFAULT_GROUP_OWNER_INTENT = 6; 1213 /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad] 1214 [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */ p2pConnect(WifiP2pConfig config, boolean joinExistingGroup)1215 public String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) { 1216 if (config == null) return null; 1217 List<String> args = new ArrayList<String>(); 1218 WpsInfo wps = config.wps; 1219 args.add(config.deviceAddress); 1220 1221 switch (wps.setup) { 1222 case WpsInfo.PBC: 1223 args.add("pbc"); 1224 break; 1225 case WpsInfo.DISPLAY: 1226 if (TextUtils.isEmpty(wps.pin)) { 1227 args.add("pin"); 1228 } else { 1229 args.add(wps.pin); 1230 } 1231 args.add("display"); 1232 break; 1233 case WpsInfo.KEYPAD: 1234 args.add(wps.pin); 1235 args.add("keypad"); 1236 break; 1237 case WpsInfo.LABEL: 1238 args.add(wps.pin); 1239 args.add("label"); 1240 default: 1241 break; 1242 } 1243 1244 if (config.netId == WifiP2pGroup.PERSISTENT_NET_ID) { 1245 args.add("persistent"); 1246 } 1247 1248 if (joinExistingGroup) { 1249 args.add("join"); 1250 } else { 1251 //TODO: This can be adapted based on device plugged in state and 1252 //device battery state 1253 int groupOwnerIntent = config.groupOwnerIntent; 1254 if (groupOwnerIntent < 0 || groupOwnerIntent > 15) { 1255 groupOwnerIntent = DEFAULT_GROUP_OWNER_INTENT; 1256 } 1257 args.add("go_intent=" + groupOwnerIntent); 1258 } 1259 1260 String command = "P2P_CONNECT "; 1261 for (String s : args) command += s + " "; 1262 1263 return doStringCommand(command); 1264 } 1265 p2pCancelConnect()1266 public boolean p2pCancelConnect() { 1267 return doBooleanCommand("P2P_CANCEL"); 1268 } 1269 p2pProvisionDiscovery(WifiP2pConfig config)1270 public boolean p2pProvisionDiscovery(WifiP2pConfig config) { 1271 if (config == null) return false; 1272 1273 switch (config.wps.setup) { 1274 case WpsInfo.PBC: 1275 return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " pbc"); 1276 case WpsInfo.DISPLAY: 1277 //We are doing display, so provision discovery is keypad 1278 return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " keypad"); 1279 case WpsInfo.KEYPAD: 1280 //We are doing keypad, so provision discovery is display 1281 return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " display"); 1282 default: 1283 break; 1284 } 1285 return false; 1286 } 1287 p2pGroupAdd(boolean persistent)1288 public boolean p2pGroupAdd(boolean persistent) { 1289 if (persistent) { 1290 return doBooleanCommand("P2P_GROUP_ADD persistent"); 1291 } 1292 return doBooleanCommand("P2P_GROUP_ADD"); 1293 } 1294 p2pGroupAdd(int netId)1295 public boolean p2pGroupAdd(int netId) { 1296 return doBooleanCommand("P2P_GROUP_ADD persistent=" + netId); 1297 } 1298 p2pGroupRemove(String iface)1299 public boolean p2pGroupRemove(String iface) { 1300 if (TextUtils.isEmpty(iface)) return false; 1301 synchronized (sLock) { 1302 return doBooleanCommandNative("IFNAME=" + iface + " P2P_GROUP_REMOVE " + iface); 1303 } 1304 } 1305 p2pReject(String deviceAddress)1306 public boolean p2pReject(String deviceAddress) { 1307 return doBooleanCommand("P2P_REJECT " + deviceAddress); 1308 } 1309 1310 /* Invite a peer to a group */ p2pInvite(WifiP2pGroup group, String deviceAddress)1311 public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) { 1312 if (TextUtils.isEmpty(deviceAddress)) return false; 1313 1314 if (group == null) { 1315 return doBooleanCommand("P2P_INVITE peer=" + deviceAddress); 1316 } else { 1317 return doBooleanCommand("P2P_INVITE group=" + group.getInterface() 1318 + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress); 1319 } 1320 } 1321 1322 /* Reinvoke a persistent connection */ p2pReinvoke(int netId, String deviceAddress)1323 public boolean p2pReinvoke(int netId, String deviceAddress) { 1324 if (TextUtils.isEmpty(deviceAddress) || netId < 0) return false; 1325 1326 return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress); 1327 } 1328 p2pGetSsid(String deviceAddress)1329 public String p2pGetSsid(String deviceAddress) { 1330 return p2pGetParam(deviceAddress, "oper_ssid"); 1331 } 1332 p2pGetDeviceAddress()1333 public String p2pGetDeviceAddress() { 1334 Log.d(TAG, "p2pGetDeviceAddress"); 1335 1336 String status = null; 1337 1338 /* Explicitly calling the API without IFNAME= prefix to take care of the devices that 1339 don't have p2p0 interface. Supplicant seems to be returning the correct address anyway. */ 1340 1341 synchronized (sLock) { 1342 status = doStringCommandNative("STATUS"); 1343 } 1344 1345 String result = ""; 1346 if (status != null) { 1347 String[] tokens = status.split("\n"); 1348 for (String token : tokens) { 1349 if (token.startsWith("p2p_device_address=")) { 1350 String[] nameValue = token.split("="); 1351 if (nameValue.length != 2) 1352 break; 1353 result = nameValue[1]; 1354 } 1355 } 1356 } 1357 1358 Log.d(TAG, "p2pGetDeviceAddress returning " + result); 1359 return result; 1360 } 1361 getGroupCapability(String deviceAddress)1362 public int getGroupCapability(String deviceAddress) { 1363 int gc = 0; 1364 if (TextUtils.isEmpty(deviceAddress)) return gc; 1365 String peerInfo = p2pPeer(deviceAddress); 1366 if (TextUtils.isEmpty(peerInfo)) return gc; 1367 1368 String[] tokens = peerInfo.split("\n"); 1369 for (String token : tokens) { 1370 if (token.startsWith("group_capab=")) { 1371 String[] nameValue = token.split("="); 1372 if (nameValue.length != 2) break; 1373 try { 1374 return Integer.decode(nameValue[1]); 1375 } catch(NumberFormatException e) { 1376 return gc; 1377 } 1378 } 1379 } 1380 return gc; 1381 } 1382 p2pPeer(String deviceAddress)1383 public String p2pPeer(String deviceAddress) { 1384 return doStringCommand("P2P_PEER " + deviceAddress); 1385 } 1386 p2pGetParam(String deviceAddress, String key)1387 private String p2pGetParam(String deviceAddress, String key) { 1388 if (deviceAddress == null) return null; 1389 1390 String peerInfo = p2pPeer(deviceAddress); 1391 if (peerInfo == null) return null; 1392 String[] tokens= peerInfo.split("\n"); 1393 1394 key += "="; 1395 for (String token : tokens) { 1396 if (token.startsWith(key)) { 1397 String[] nameValue = token.split("="); 1398 if (nameValue.length != 2) break; 1399 return nameValue[1]; 1400 } 1401 } 1402 return null; 1403 } 1404 p2pServiceAdd(WifiP2pServiceInfo servInfo)1405 public boolean p2pServiceAdd(WifiP2pServiceInfo servInfo) { 1406 /* 1407 * P2P_SERVICE_ADD bonjour <query hexdump> <RDATA hexdump> 1408 * P2P_SERVICE_ADD upnp <version hex> <service> 1409 * 1410 * e.g) 1411 * [Bonjour] 1412 * # IP Printing over TCP (PTR) (RDATA=MyPrinter._ipp._tcp.local.) 1413 * P2P_SERVICE_ADD bonjour 045f697070c00c000c01 094d795072696e746572c027 1414 * # IP Printing over TCP (TXT) (RDATA=txtvers=1,pdl=application/postscript) 1415 * P2P_SERVICE_ADD bonjour 096d797072696e746572045f697070c00c001001 1416 * 09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074 1417 * 1418 * [UPnP] 1419 * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012 1420 * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice 1421 * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp 1422 * -org:device:InternetGatewayDevice:1 1423 * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9322-123456789012::urn:schemas-upnp 1424 * -org:service:ContentDirectory:2 1425 */ 1426 synchronized (sLock) { 1427 for (String s : servInfo.getSupplicantQueryList()) { 1428 String command = "P2P_SERVICE_ADD"; 1429 command += (" " + s); 1430 if (!doBooleanCommand(command)) { 1431 return false; 1432 } 1433 } 1434 } 1435 return true; 1436 } 1437 p2pServiceDel(WifiP2pServiceInfo servInfo)1438 public boolean p2pServiceDel(WifiP2pServiceInfo servInfo) { 1439 /* 1440 * P2P_SERVICE_DEL bonjour <query hexdump> 1441 * P2P_SERVICE_DEL upnp <version hex> <service> 1442 */ 1443 synchronized (sLock) { 1444 for (String s : servInfo.getSupplicantQueryList()) { 1445 String command = "P2P_SERVICE_DEL "; 1446 1447 String[] data = s.split(" "); 1448 if (data.length < 2) { 1449 return false; 1450 } 1451 if ("upnp".equals(data[0])) { 1452 command += s; 1453 } else if ("bonjour".equals(data[0])) { 1454 command += data[0]; 1455 command += (" " + data[1]); 1456 } else { 1457 return false; 1458 } 1459 if (!doBooleanCommand(command)) { 1460 return false; 1461 } 1462 } 1463 } 1464 return true; 1465 } 1466 p2pServiceFlush()1467 public boolean p2pServiceFlush() { 1468 return doBooleanCommand("P2P_SERVICE_FLUSH"); 1469 } 1470 p2pServDiscReq(String addr, String query)1471 public String p2pServDiscReq(String addr, String query) { 1472 String command = "P2P_SERV_DISC_REQ"; 1473 command += (" " + addr); 1474 command += (" " + query); 1475 1476 return doStringCommand(command); 1477 } 1478 p2pServDiscCancelReq(String id)1479 public boolean p2pServDiscCancelReq(String id) { 1480 return doBooleanCommand("P2P_SERV_DISC_CANCEL_REQ " + id); 1481 } 1482 1483 /* Set the current mode of miracast operation. 1484 * 0 = disabled 1485 * 1 = operating as source 1486 * 2 = operating as sink 1487 */ setMiracastMode(int mode)1488 public void setMiracastMode(int mode) { 1489 // Note: optional feature on the driver. It is ok for this to fail. 1490 doBooleanCommand("DRIVER MIRACAST " + mode); 1491 } 1492 fetchAnqp(String bssid, String subtypes)1493 public boolean fetchAnqp(String bssid, String subtypes) { 1494 return doBooleanCommand("ANQP_GET " + bssid + " " + subtypes); 1495 } 1496 1497 /* 1498 * NFC-related calls 1499 */ getNfcWpsConfigurationToken(int netId)1500 public String getNfcWpsConfigurationToken(int netId) { 1501 return doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId); 1502 } 1503 getNfcHandoverRequest()1504 public String getNfcHandoverRequest() { 1505 return doStringCommand("NFC_GET_HANDOVER_REQ NDEF P2P-CR"); 1506 } 1507 getNfcHandoverSelect()1508 public String getNfcHandoverSelect() { 1509 return doStringCommand("NFC_GET_HANDOVER_SEL NDEF P2P-CR"); 1510 } 1511 initiatorReportNfcHandover(String selectMessage)1512 public boolean initiatorReportNfcHandover(String selectMessage) { 1513 return doBooleanCommand("NFC_REPORT_HANDOVER INIT P2P 00 " + selectMessage); 1514 } 1515 responderReportNfcHandover(String requestMessage)1516 public boolean responderReportNfcHandover(String requestMessage) { 1517 return doBooleanCommand("NFC_REPORT_HANDOVER RESP P2P " + requestMessage + " 00"); 1518 } 1519 1520 1521 /* kernel logging support */ readKernelLogNative()1522 private static native byte[] readKernelLogNative(); 1523 readKernelLog()1524 synchronized public String readKernelLog() { 1525 byte[] bytes = readKernelLogNative(); 1526 if (bytes != null) { 1527 CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder(); 1528 try { 1529 CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes)); 1530 return decoded.toString(); 1531 } catch (CharacterCodingException cce) { 1532 return new String(bytes, StandardCharsets.ISO_8859_1); 1533 } 1534 } else { 1535 return "*** failed to read kernel log ***"; 1536 } 1537 } 1538 1539 /* WIFI HAL support */ 1540 1541 // HAL command ids 1542 private static int sCmdId = 1; getNewCmdIdLocked()1543 private static int getNewCmdIdLocked() { 1544 return sCmdId++; 1545 } 1546 1547 private static final String TAG = "WifiNative-HAL"; 1548 private static long sWifiHalHandle = 0; /* used by JNI to save wifi_handle */ 1549 private static long[] sWifiIfaceHandles = null; /* used by JNI to save interface handles */ 1550 public static int sWlan0Index = -1; 1551 private static MonitorThread sThread; 1552 private static final int STOP_HAL_TIMEOUT_MS = 1000; 1553 startHalNative()1554 private static native boolean startHalNative(); stopHalNative()1555 private static native void stopHalNative(); waitForHalEventNative()1556 private static native void waitForHalEventNative(); 1557 1558 private static class MonitorThread extends Thread { run()1559 public void run() { 1560 Log.i(TAG, "Waiting for HAL events mWifiHalHandle=" + Long.toString(sWifiHalHandle)); 1561 waitForHalEventNative(); 1562 } 1563 } 1564 startHal()1565 public boolean startHal() { 1566 String debugLog = "startHal stack: "; 1567 java.lang.StackTraceElement[] elements = Thread.currentThread().getStackTrace(); 1568 for (int i = 2; i < elements.length && i <= 7; i++ ) { 1569 debugLog = debugLog + " - " + elements[i].getMethodName(); 1570 } 1571 1572 sLocalLog.log(debugLog); 1573 1574 synchronized (sLock) { 1575 if (startHalNative()) { 1576 int wlan0Index = queryInterfaceIndex(mInterfaceName); 1577 if (wlan0Index == -1) { 1578 if (DBG) sLocalLog.log("Could not find interface with name: " + mInterfaceName); 1579 return false; 1580 } 1581 sWlan0Index = wlan0Index; 1582 sThread = new MonitorThread(); 1583 sThread.start(); 1584 return true; 1585 } else { 1586 if (DBG) sLocalLog.log("Could not start hal"); 1587 Log.e(TAG, "Could not start hal"); 1588 return false; 1589 } 1590 } 1591 } 1592 stopHal()1593 public void stopHal() { 1594 synchronized (sLock) { 1595 if (isHalStarted()) { 1596 stopHalNative(); 1597 try { 1598 sThread.join(STOP_HAL_TIMEOUT_MS); 1599 Log.d(TAG, "HAL event thread stopped successfully"); 1600 } catch (InterruptedException e) { 1601 Log.e(TAG, "Could not stop HAL cleanly"); 1602 } 1603 sThread = null; 1604 sWifiHalHandle = 0; 1605 sWifiIfaceHandles = null; 1606 sWlan0Index = -1; 1607 } 1608 } 1609 } 1610 isHalStarted()1611 public boolean isHalStarted() { 1612 return (sWifiHalHandle != 0); 1613 } getInterfacesNative()1614 private static native int getInterfacesNative(); 1615 queryInterfaceIndex(String interfaceName)1616 public int queryInterfaceIndex(String interfaceName) { 1617 synchronized (sLock) { 1618 if (isHalStarted()) { 1619 int num = getInterfacesNative(); 1620 for (int i = 0; i < num; i++) { 1621 String name = getInterfaceNameNative(i); 1622 if (name.equals(interfaceName)) { 1623 return i; 1624 } 1625 } 1626 } 1627 } 1628 return -1; 1629 } 1630 getInterfaceNameNative(int index)1631 private static native String getInterfaceNameNative(int index); getInterfaceName(int index)1632 public String getInterfaceName(int index) { 1633 synchronized (sLock) { 1634 return getInterfaceNameNative(index); 1635 } 1636 } 1637 1638 // TODO: Change variable names to camel style. 1639 public static class ScanCapabilities { 1640 public int max_scan_cache_size; 1641 public int max_scan_buckets; 1642 public int max_ap_cache_per_scan; 1643 public int max_rssi_sample_size; 1644 public int max_scan_reporting_threshold; 1645 public int max_hotlist_bssids; 1646 public int max_significant_wifi_change_aps; 1647 public int max_bssid_history_entries; 1648 public int max_number_epno_networks; 1649 public int max_number_epno_networks_by_ssid; 1650 public int max_number_of_white_listed_ssid; 1651 } 1652 getScanCapabilities(ScanCapabilities capabilities)1653 public boolean getScanCapabilities(ScanCapabilities capabilities) { 1654 synchronized (sLock) { 1655 return isHalStarted() && getScanCapabilitiesNative(sWlan0Index, capabilities); 1656 } 1657 } 1658 getScanCapabilitiesNative( int iface, ScanCapabilities capabilities)1659 private static native boolean getScanCapabilitiesNative( 1660 int iface, ScanCapabilities capabilities); 1661 startScanNative(int iface, int id, ScanSettings settings)1662 private static native boolean startScanNative(int iface, int id, ScanSettings settings); stopScanNative(int iface, int id)1663 private static native boolean stopScanNative(int iface, int id); getScanResultsNative(int iface, boolean flush)1664 private static native WifiScanner.ScanData[] getScanResultsNative(int iface, boolean flush); getWifiLinkLayerStatsNative(int iface)1665 private static native WifiLinkLayerStats getWifiLinkLayerStatsNative(int iface); setWifiLinkLayerStatsNative(int iface, int enable)1666 private static native void setWifiLinkLayerStatsNative(int iface, int enable); 1667 1668 public static class ChannelSettings { 1669 public int frequency; 1670 public int dwell_time_ms; 1671 public boolean passive; 1672 } 1673 1674 public static class BucketSettings { 1675 public int bucket; 1676 public int band; 1677 public int period_ms; 1678 public int max_period_ms; 1679 public int step_count; 1680 public int report_events; 1681 public int num_channels; 1682 public ChannelSettings[] channels; 1683 } 1684 1685 public static class ScanSettings { 1686 public int base_period_ms; 1687 public int max_ap_per_scan; 1688 public int report_threshold_percent; 1689 public int report_threshold_num_scans; 1690 public int num_buckets; 1691 /* Not part of gscan HAL API. Used only for wpa_supplicant scanning */ 1692 public int[] hiddenNetworkIds; 1693 public BucketSettings[] buckets; 1694 } 1695 1696 /** 1697 * Network parameters to start PNO scan. 1698 */ 1699 public static class PnoNetwork { 1700 public String ssid; 1701 public int networkId; 1702 public int priority; 1703 public byte flags; 1704 public byte auth_bit_field; 1705 } 1706 1707 /** 1708 * Parameters to start PNO scan. This holds the list of networks which are going to used for 1709 * PNO scan. 1710 */ 1711 public static class PnoSettings { 1712 public int min5GHzRssi; 1713 public int min24GHzRssi; 1714 public int initialScoreMax; 1715 public int currentConnectionBonus; 1716 public int sameNetworkBonus; 1717 public int secureBonus; 1718 public int band5GHzBonus; 1719 public boolean isConnected; 1720 public PnoNetwork[] networkList; 1721 } 1722 1723 /** 1724 * Wi-Fi channel information. 1725 */ 1726 public static class WifiChannelInfo { 1727 int mPrimaryFrequency; 1728 int mCenterFrequency0; 1729 int mCenterFrequency1; 1730 int mChannelWidth; 1731 // TODO: add preamble once available in HAL. 1732 } 1733 1734 public static interface ScanEventHandler { 1735 /** 1736 * Called for each AP as it is found with the entire contents of the beacon/probe response. 1737 * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified. 1738 */ onFullScanResult(ScanResult fullScanResult, int bucketsScanned)1739 void onFullScanResult(ScanResult fullScanResult, int bucketsScanned); 1740 /** 1741 * Callback on an event during a gscan scan. 1742 * See WifiNative.WIFI_SCAN_* for possible values. 1743 */ onScanStatus(int event)1744 void onScanStatus(int event); 1745 /** 1746 * Called with the current cached scan results when gscan is paused. 1747 */ onScanPaused(WifiScanner.ScanData[] data)1748 void onScanPaused(WifiScanner.ScanData[] data); 1749 /** 1750 * Called with the current cached scan results when gscan is resumed. 1751 */ onScanRestarted()1752 void onScanRestarted(); 1753 } 1754 1755 /** 1756 * Handler to notify the occurrence of various events during PNO scan. 1757 */ 1758 public interface PnoEventHandler { 1759 /** 1760 * Callback to notify when one of the shortlisted networks is found during PNO scan. 1761 * @param results List of Scan results received. 1762 */ onPnoNetworkFound(ScanResult[] results)1763 void onPnoNetworkFound(ScanResult[] results); 1764 1765 /** 1766 * Callback to notify when the PNO scan schedule fails. 1767 */ onPnoScanFailed()1768 void onPnoScanFailed(); 1769 } 1770 1771 /* scan status, keep these values in sync with gscan.h */ 1772 public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0; 1773 public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1; 1774 public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2; 1775 public static final int WIFI_SCAN_FAILED = 3; 1776 1777 // Callback from native onScanStatus(int id, int event)1778 private static void onScanStatus(int id, int event) { 1779 ScanEventHandler handler = sScanEventHandler; 1780 if (handler != null) { 1781 handler.onScanStatus(event); 1782 } 1783 } 1784 createWifiSsid(byte[] rawSsid)1785 public static WifiSsid createWifiSsid(byte[] rawSsid) { 1786 String ssidHexString = String.valueOf(HexEncoding.encode(rawSsid)); 1787 1788 if (ssidHexString == null) { 1789 return null; 1790 } 1791 1792 WifiSsid wifiSsid = WifiSsid.createFromHex(ssidHexString); 1793 1794 return wifiSsid; 1795 } 1796 ssidConvert(byte[] rawSsid)1797 public static String ssidConvert(byte[] rawSsid) { 1798 String ssid; 1799 1800 CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder(); 1801 try { 1802 CharBuffer decoded = decoder.decode(ByteBuffer.wrap(rawSsid)); 1803 ssid = decoded.toString(); 1804 } catch (CharacterCodingException cce) { 1805 ssid = null; 1806 } 1807 1808 if (ssid == null) { 1809 ssid = new String(rawSsid, StandardCharsets.ISO_8859_1); 1810 } 1811 1812 return ssid; 1813 } 1814 1815 // Called from native setSsid(byte[] rawSsid, ScanResult result)1816 public static boolean setSsid(byte[] rawSsid, ScanResult result) { 1817 if (rawSsid == null || rawSsid.length == 0 || result == null) { 1818 return false; 1819 } 1820 1821 result.SSID = ssidConvert(rawSsid); 1822 result.wifiSsid = createWifiSsid(rawSsid); 1823 return true; 1824 } 1825 populateScanResult(ScanResult result, int beaconCap, String dbg)1826 private static void populateScanResult(ScanResult result, int beaconCap, String dbg) { 1827 if (dbg == null) dbg = ""; 1828 1829 InformationElementUtil.HtOperation htOperation = new InformationElementUtil.HtOperation(); 1830 InformationElementUtil.VhtOperation vhtOperation = 1831 new InformationElementUtil.VhtOperation(); 1832 InformationElementUtil.ExtendedCapabilities extendedCaps = 1833 new InformationElementUtil.ExtendedCapabilities(); 1834 1835 ScanResult.InformationElement elements[] = 1836 InformationElementUtil.parseInformationElements(result.bytes); 1837 for (ScanResult.InformationElement ie : elements) { 1838 if(ie.id == ScanResult.InformationElement.EID_HT_OPERATION) { 1839 htOperation.from(ie); 1840 } else if(ie.id == ScanResult.InformationElement.EID_VHT_OPERATION) { 1841 vhtOperation.from(ie); 1842 } else if (ie.id == ScanResult.InformationElement.EID_EXTENDED_CAPS) { 1843 extendedCaps.from(ie); 1844 } 1845 } 1846 1847 if (extendedCaps.is80211McRTTResponder) { 1848 result.setFlag(ScanResult.FLAG_80211mc_RESPONDER); 1849 } else { 1850 result.clearFlag(ScanResult.FLAG_80211mc_RESPONDER); 1851 } 1852 1853 //handle RTT related information 1854 if (vhtOperation.isValid()) { 1855 result.channelWidth = vhtOperation.getChannelWidth(); 1856 result.centerFreq0 = vhtOperation.getCenterFreq0(); 1857 result.centerFreq1 = vhtOperation.getCenterFreq1(); 1858 } else { 1859 result.channelWidth = htOperation.getChannelWidth(); 1860 result.centerFreq0 = htOperation.getCenterFreq0(result.frequency); 1861 result.centerFreq1 = 0; 1862 } 1863 1864 // build capabilities string 1865 BitSet beaconCapBits = new BitSet(16); 1866 for (int i = 0; i < 16; i++) { 1867 if ((beaconCap & (1 << i)) != 0) { 1868 beaconCapBits.set(i); 1869 } 1870 } 1871 result.capabilities = InformationElementUtil.Capabilities.buildCapabilities(elements, 1872 beaconCapBits); 1873 1874 if(DBG) { 1875 Log.d(TAG, dbg + "SSID: " + result.SSID + " ChannelWidth is: " + result.channelWidth 1876 + " PrimaryFreq: " + result.frequency + " mCenterfreq0: " + result.centerFreq0 1877 + " mCenterfreq1: " + result.centerFreq1 + (extendedCaps.is80211McRTTResponder 1878 ? "Support RTT reponder: " : "Do not support RTT responder") 1879 + " Capabilities: " + result.capabilities); 1880 } 1881 1882 result.informationElements = elements; 1883 } 1884 1885 // Callback from native onFullScanResult(int id, ScanResult result, int bucketsScanned, int beaconCap)1886 private static void onFullScanResult(int id, ScanResult result, 1887 int bucketsScanned, int beaconCap) { 1888 if (DBG) Log.i(TAG, "Got a full scan results event, ssid = " + result.SSID); 1889 1890 ScanEventHandler handler = sScanEventHandler; 1891 if (handler != null) { 1892 populateScanResult(result, beaconCap, " onFullScanResult "); 1893 handler.onFullScanResult(result, bucketsScanned); 1894 } 1895 } 1896 1897 private static int sScanCmdId = 0; 1898 private static ScanEventHandler sScanEventHandler; 1899 private static ScanSettings sScanSettings; 1900 startScan(ScanSettings settings, ScanEventHandler eventHandler)1901 public boolean startScan(ScanSettings settings, ScanEventHandler eventHandler) { 1902 synchronized (sLock) { 1903 if (isHalStarted()) { 1904 if (sScanCmdId != 0) { 1905 stopScan(); 1906 } else if (sScanSettings != null || sScanEventHandler != null) { 1907 /* current scan is paused; no need to stop it */ 1908 } 1909 1910 sScanCmdId = getNewCmdIdLocked(); 1911 1912 sScanSettings = settings; 1913 sScanEventHandler = eventHandler; 1914 1915 if (startScanNative(sWlan0Index, sScanCmdId, settings) == false) { 1916 sScanEventHandler = null; 1917 sScanSettings = null; 1918 sScanCmdId = 0; 1919 return false; 1920 } 1921 1922 return true; 1923 } else { 1924 return false; 1925 } 1926 } 1927 } 1928 stopScan()1929 public void stopScan() { 1930 synchronized (sLock) { 1931 if (isHalStarted()) { 1932 if (sScanCmdId != 0) { 1933 stopScanNative(sWlan0Index, sScanCmdId); 1934 } 1935 sScanSettings = null; 1936 sScanEventHandler = null; 1937 sScanCmdId = 0; 1938 } 1939 } 1940 } 1941 pauseScan()1942 public void pauseScan() { 1943 synchronized (sLock) { 1944 if (isHalStarted()) { 1945 if (sScanCmdId != 0 && sScanSettings != null && sScanEventHandler != null) { 1946 Log.d(TAG, "Pausing scan"); 1947 WifiScanner.ScanData scanData[] = getScanResultsNative(sWlan0Index, true); 1948 stopScanNative(sWlan0Index, sScanCmdId); 1949 sScanCmdId = 0; 1950 sScanEventHandler.onScanPaused(scanData); 1951 } 1952 } 1953 } 1954 } 1955 restartScan()1956 public void restartScan() { 1957 synchronized (sLock) { 1958 if (isHalStarted()) { 1959 if (sScanCmdId == 0 && sScanSettings != null && sScanEventHandler != null) { 1960 Log.d(TAG, "Restarting scan"); 1961 ScanEventHandler handler = sScanEventHandler; 1962 ScanSettings settings = sScanSettings; 1963 if (startScan(sScanSettings, sScanEventHandler)) { 1964 sScanEventHandler.onScanRestarted(); 1965 } else { 1966 /* we are still paused; don't change state */ 1967 sScanEventHandler = handler; 1968 sScanSettings = settings; 1969 } 1970 } 1971 } 1972 } 1973 } 1974 getScanResults(boolean flush)1975 public WifiScanner.ScanData[] getScanResults(boolean flush) { 1976 synchronized (sLock) { 1977 WifiScanner.ScanData[] sd = null; 1978 if (isHalStarted()) { 1979 sd = getScanResultsNative(sWlan0Index, flush); 1980 } 1981 1982 if (sd != null) { 1983 return sd; 1984 } else { 1985 return new WifiScanner.ScanData[0]; 1986 } 1987 } 1988 } 1989 1990 public static interface HotlistEventHandler { onHotlistApFound(ScanResult[] result)1991 void onHotlistApFound (ScanResult[] result); onHotlistApLost(ScanResult[] result)1992 void onHotlistApLost (ScanResult[] result); 1993 } 1994 1995 private static int sHotlistCmdId = 0; 1996 private static HotlistEventHandler sHotlistEventHandler; 1997 setHotlistNative(int iface, int id, WifiScanner.HotlistSettings settings)1998 private native static boolean setHotlistNative(int iface, int id, 1999 WifiScanner.HotlistSettings settings); resetHotlistNative(int iface, int id)2000 private native static boolean resetHotlistNative(int iface, int id); 2001 setHotlist(WifiScanner.HotlistSettings settings, HotlistEventHandler eventHandler)2002 public boolean setHotlist(WifiScanner.HotlistSettings settings, 2003 HotlistEventHandler eventHandler) { 2004 synchronized (sLock) { 2005 if (isHalStarted()) { 2006 if (sHotlistCmdId != 0) { 2007 return false; 2008 } else { 2009 sHotlistCmdId = getNewCmdIdLocked(); 2010 } 2011 2012 sHotlistEventHandler = eventHandler; 2013 if (setHotlistNative(sWlan0Index, sHotlistCmdId, settings) == false) { 2014 sHotlistEventHandler = null; 2015 return false; 2016 } 2017 2018 return true; 2019 } else { 2020 return false; 2021 } 2022 } 2023 } 2024 resetHotlist()2025 public void resetHotlist() { 2026 synchronized (sLock) { 2027 if (isHalStarted()) { 2028 if (sHotlistCmdId != 0) { 2029 resetHotlistNative(sWlan0Index, sHotlistCmdId); 2030 sHotlistCmdId = 0; 2031 sHotlistEventHandler = null; 2032 } 2033 } 2034 } 2035 } 2036 2037 // Callback from native onHotlistApFound(int id, ScanResult[] results)2038 private static void onHotlistApFound(int id, ScanResult[] results) { 2039 HotlistEventHandler handler = sHotlistEventHandler; 2040 if (handler != null) { 2041 handler.onHotlistApFound(results); 2042 } else { 2043 /* this can happen because of race conditions */ 2044 Log.d(TAG, "Ignoring hotlist AP found event"); 2045 } 2046 } 2047 2048 // Callback from native onHotlistApLost(int id, ScanResult[] results)2049 private static void onHotlistApLost(int id, ScanResult[] results) { 2050 HotlistEventHandler handler = sHotlistEventHandler; 2051 if (handler != null) { 2052 handler.onHotlistApLost(results); 2053 } else { 2054 /* this can happen because of race conditions */ 2055 Log.d(TAG, "Ignoring hotlist AP lost event"); 2056 } 2057 } 2058 2059 public static interface SignificantWifiChangeEventHandler { onChangesFound(ScanResult[] result)2060 void onChangesFound(ScanResult[] result); 2061 } 2062 2063 private static SignificantWifiChangeEventHandler sSignificantWifiChangeHandler; 2064 private static int sSignificantWifiChangeCmdId; 2065 trackSignificantWifiChangeNative( int iface, int id, WifiScanner.WifiChangeSettings settings)2066 private static native boolean trackSignificantWifiChangeNative( 2067 int iface, int id, WifiScanner.WifiChangeSettings settings); untrackSignificantWifiChangeNative(int iface, int id)2068 private static native boolean untrackSignificantWifiChangeNative(int iface, int id); 2069 trackSignificantWifiChange( WifiScanner.WifiChangeSettings settings, SignificantWifiChangeEventHandler handler)2070 public boolean trackSignificantWifiChange( 2071 WifiScanner.WifiChangeSettings settings, SignificantWifiChangeEventHandler handler) { 2072 synchronized (sLock) { 2073 if (isHalStarted()) { 2074 if (sSignificantWifiChangeCmdId != 0) { 2075 return false; 2076 } else { 2077 sSignificantWifiChangeCmdId = getNewCmdIdLocked(); 2078 } 2079 2080 sSignificantWifiChangeHandler = handler; 2081 if (trackSignificantWifiChangeNative(sWlan0Index, sSignificantWifiChangeCmdId, 2082 settings) == false) { 2083 sSignificantWifiChangeHandler = null; 2084 return false; 2085 } 2086 2087 return true; 2088 } else { 2089 return false; 2090 } 2091 2092 } 2093 } 2094 untrackSignificantWifiChange()2095 public void untrackSignificantWifiChange() { 2096 synchronized (sLock) { 2097 if (isHalStarted()) { 2098 if (sSignificantWifiChangeCmdId != 0) { 2099 untrackSignificantWifiChangeNative(sWlan0Index, sSignificantWifiChangeCmdId); 2100 sSignificantWifiChangeCmdId = 0; 2101 sSignificantWifiChangeHandler = null; 2102 } 2103 } 2104 } 2105 } 2106 2107 // Callback from native onSignificantWifiChange(int id, ScanResult[] results)2108 private static void onSignificantWifiChange(int id, ScanResult[] results) { 2109 SignificantWifiChangeEventHandler handler = sSignificantWifiChangeHandler; 2110 if (handler != null) { 2111 handler.onChangesFound(results); 2112 } else { 2113 /* this can happen because of race conditions */ 2114 Log.d(TAG, "Ignoring significant wifi change"); 2115 } 2116 } 2117 getWifiLinkLayerStats(String iface)2118 public WifiLinkLayerStats getWifiLinkLayerStats(String iface) { 2119 // TODO: use correct iface name to Index translation 2120 if (iface == null) return null; 2121 synchronized (sLock) { 2122 if (isHalStarted()) { 2123 return getWifiLinkLayerStatsNative(sWlan0Index); 2124 } else { 2125 return null; 2126 } 2127 } 2128 } 2129 setWifiLinkLayerStats(String iface, int enable)2130 public void setWifiLinkLayerStats(String iface, int enable) { 2131 if (iface == null) return; 2132 synchronized (sLock) { 2133 if (isHalStarted()) { 2134 setWifiLinkLayerStatsNative(sWlan0Index, enable); 2135 } 2136 } 2137 } 2138 getSupportedFeatureSetNative(int iface)2139 public static native int getSupportedFeatureSetNative(int iface); getSupportedFeatureSet()2140 public int getSupportedFeatureSet() { 2141 synchronized (sLock) { 2142 if (isHalStarted()) { 2143 return getSupportedFeatureSetNative(sWlan0Index); 2144 } else { 2145 Log.d(TAG, "Failing getSupportedFeatureset because HAL isn't started"); 2146 return 0; 2147 } 2148 } 2149 } 2150 2151 /* Rtt related commands/events */ 2152 public static interface RttEventHandler { onRttResults(RttManager.RttResult[] result)2153 void onRttResults(RttManager.RttResult[] result); 2154 } 2155 2156 private static RttEventHandler sRttEventHandler; 2157 private static int sRttCmdId; 2158 2159 // Callback from native onRttResults(int id, RttManager.RttResult[] results)2160 private static void onRttResults(int id, RttManager.RttResult[] results) { 2161 RttEventHandler handler = sRttEventHandler; 2162 if (handler != null && id == sRttCmdId) { 2163 Log.d(TAG, "Received " + results.length + " rtt results"); 2164 handler.onRttResults(results); 2165 sRttCmdId = 0; 2166 } else { 2167 Log.d(TAG, "RTT Received event for unknown cmd = " + id + 2168 ", current id = " + sRttCmdId); 2169 } 2170 } 2171 requestRangeNative( int iface, int id, RttManager.RttParams[] params)2172 private static native boolean requestRangeNative( 2173 int iface, int id, RttManager.RttParams[] params); cancelRangeRequestNative( int iface, int id, RttManager.RttParams[] params)2174 private static native boolean cancelRangeRequestNative( 2175 int iface, int id, RttManager.RttParams[] params); 2176 requestRtt( RttManager.RttParams[] params, RttEventHandler handler)2177 public boolean requestRtt( 2178 RttManager.RttParams[] params, RttEventHandler handler) { 2179 synchronized (sLock) { 2180 if (isHalStarted()) { 2181 if (sRttCmdId != 0) { 2182 Log.v("TAG", "Last one is still under measurement!"); 2183 return false; 2184 } else { 2185 sRttCmdId = getNewCmdIdLocked(); 2186 } 2187 sRttEventHandler = handler; 2188 Log.v(TAG, "native issue RTT request"); 2189 return requestRangeNative(sWlan0Index, sRttCmdId, params); 2190 } else { 2191 return false; 2192 } 2193 } 2194 } 2195 cancelRtt(RttManager.RttParams[] params)2196 public boolean cancelRtt(RttManager.RttParams[] params) { 2197 synchronized (sLock) { 2198 if (isHalStarted()) { 2199 if (sRttCmdId == 0) { 2200 return false; 2201 } 2202 2203 sRttCmdId = 0; 2204 2205 if (cancelRangeRequestNative(sWlan0Index, sRttCmdId, params)) { 2206 sRttEventHandler = null; 2207 Log.v(TAG, "RTT cancel Request Successfully"); 2208 return true; 2209 } else { 2210 Log.e(TAG, "RTT cancel Request failed"); 2211 return false; 2212 } 2213 } else { 2214 return false; 2215 } 2216 } 2217 } 2218 2219 private static int sRttResponderCmdId = 0; 2220 enableRttResponderNative(int iface, int commandId, int timeoutSeconds, WifiChannelInfo channelHint)2221 private static native ResponderConfig enableRttResponderNative(int iface, int commandId, 2222 int timeoutSeconds, WifiChannelInfo channelHint); 2223 /** 2224 * Enable RTT responder role on the device. Returns {@link ResponderConfig} if the responder 2225 * role is successfully enabled, {@code null} otherwise. 2226 */ 2227 @Nullable enableRttResponder(int timeoutSeconds)2228 public ResponderConfig enableRttResponder(int timeoutSeconds) { 2229 synchronized (sLock) { 2230 if (!isHalStarted()) return null; 2231 if (sRttResponderCmdId != 0) { 2232 if (DBG) Log.e(mTAG, "responder mode already enabled - this shouldn't happen"); 2233 return null; 2234 } 2235 int id = getNewCmdIdLocked(); 2236 ResponderConfig config = enableRttResponderNative( 2237 sWlan0Index, id, timeoutSeconds, null); 2238 if (config != null) sRttResponderCmdId = id; 2239 if (DBG) Log.d(TAG, "enabling rtt " + (config != null)); 2240 return config; 2241 } 2242 } 2243 disableRttResponderNative(int iface, int commandId)2244 private static native boolean disableRttResponderNative(int iface, int commandId); 2245 /** 2246 * Disable RTT responder role. Returns {@code true} if responder role is successfully disabled, 2247 * {@code false} otherwise. 2248 */ disableRttResponder()2249 public boolean disableRttResponder() { 2250 synchronized (sLock) { 2251 if (!isHalStarted()) return false; 2252 if (sRttResponderCmdId == 0) { 2253 Log.e(mTAG, "responder role not enabled yet"); 2254 return true; 2255 } 2256 sRttResponderCmdId = 0; 2257 return disableRttResponderNative(sWlan0Index, sRttResponderCmdId); 2258 } 2259 } 2260 setScanningMacOuiNative(int iface, byte[] oui)2261 private static native boolean setScanningMacOuiNative(int iface, byte[] oui); 2262 setScanningMacOui(byte[] oui)2263 public boolean setScanningMacOui(byte[] oui) { 2264 synchronized (sLock) { 2265 if (isHalStarted()) { 2266 return setScanningMacOuiNative(sWlan0Index, oui); 2267 } else { 2268 return false; 2269 } 2270 } 2271 } 2272 getChannelsForBandNative( int iface, int band)2273 private static native int[] getChannelsForBandNative( 2274 int iface, int band); 2275 getChannelsForBand(int band)2276 public int [] getChannelsForBand(int band) { 2277 synchronized (sLock) { 2278 if (isHalStarted()) { 2279 return getChannelsForBandNative(sWlan0Index, band); 2280 } else { 2281 return null; 2282 } 2283 } 2284 } 2285 isGetChannelsForBandSupportedNative()2286 private static native boolean isGetChannelsForBandSupportedNative(); isGetChannelsForBandSupported()2287 public boolean isGetChannelsForBandSupported(){ 2288 synchronized (sLock) { 2289 if (isHalStarted()) { 2290 return isGetChannelsForBandSupportedNative(); 2291 } else { 2292 return false; 2293 } 2294 } 2295 } 2296 setDfsFlagNative(int iface, boolean dfsOn)2297 private static native boolean setDfsFlagNative(int iface, boolean dfsOn); setDfsFlag(boolean dfsOn)2298 public boolean setDfsFlag(boolean dfsOn) { 2299 synchronized (sLock) { 2300 if (isHalStarted()) { 2301 return setDfsFlagNative(sWlan0Index, dfsOn); 2302 } else { 2303 return false; 2304 } 2305 } 2306 } 2307 setInterfaceUpNative(boolean up)2308 private static native boolean setInterfaceUpNative(boolean up); setInterfaceUp(boolean up)2309 public boolean setInterfaceUp(boolean up) { 2310 synchronized (sLock) { 2311 if (isHalStarted()) { 2312 return setInterfaceUpNative(up); 2313 } else { 2314 return false; 2315 } 2316 } 2317 } 2318 getRttCapabilitiesNative(int iface)2319 private static native RttManager.RttCapabilities getRttCapabilitiesNative(int iface); getRttCapabilities()2320 public RttManager.RttCapabilities getRttCapabilities() { 2321 synchronized (sLock) { 2322 if (isHalStarted()) { 2323 return getRttCapabilitiesNative(sWlan0Index); 2324 } else { 2325 return null; 2326 } 2327 } 2328 } 2329 getApfCapabilitiesNative(int iface)2330 private static native ApfCapabilities getApfCapabilitiesNative(int iface); getApfCapabilities()2331 public ApfCapabilities getApfCapabilities() { 2332 synchronized (sLock) { 2333 if (isHalStarted()) { 2334 return getApfCapabilitiesNative(sWlan0Index); 2335 } else { 2336 return null; 2337 } 2338 } 2339 } 2340 installPacketFilterNative(int iface, byte[] filter)2341 private static native boolean installPacketFilterNative(int iface, byte[] filter); installPacketFilter(byte[] filter)2342 public boolean installPacketFilter(byte[] filter) { 2343 synchronized (sLock) { 2344 if (isHalStarted()) { 2345 return installPacketFilterNative(sWlan0Index, filter); 2346 } else { 2347 return false; 2348 } 2349 } 2350 } 2351 setCountryCodeHalNative(int iface, String CountryCode)2352 private static native boolean setCountryCodeHalNative(int iface, String CountryCode); setCountryCodeHal(String CountryCode)2353 public boolean setCountryCodeHal(String CountryCode) { 2354 synchronized (sLock) { 2355 if (isHalStarted()) { 2356 return setCountryCodeHalNative(sWlan0Index, CountryCode); 2357 } else { 2358 return false; 2359 } 2360 } 2361 } 2362 2363 /* Rtt related commands/events */ 2364 public abstract class TdlsEventHandler { onTdlsStatus(String macAddr, int status, int reason)2365 abstract public void onTdlsStatus(String macAddr, int status, int reason); 2366 } 2367 2368 private static TdlsEventHandler sTdlsEventHandler; 2369 enableDisableTdlsNative(int iface, boolean enable, String macAddr)2370 private static native boolean enableDisableTdlsNative(int iface, boolean enable, 2371 String macAddr); enableDisableTdls(boolean enable, String macAdd, TdlsEventHandler tdlsCallBack)2372 public boolean enableDisableTdls(boolean enable, String macAdd, TdlsEventHandler tdlsCallBack) { 2373 synchronized (sLock) { 2374 sTdlsEventHandler = tdlsCallBack; 2375 return enableDisableTdlsNative(sWlan0Index, enable, macAdd); 2376 } 2377 } 2378 2379 // Once TDLS per mac and event feature is implemented, this class definition should be 2380 // moved to the right place, like WifiManager etc 2381 public static class TdlsStatus { 2382 int channel; 2383 int global_operating_class; 2384 int state; 2385 int reason; 2386 } getTdlsStatusNative(int iface, String macAddr)2387 private static native TdlsStatus getTdlsStatusNative(int iface, String macAddr); getTdlsStatus(String macAdd)2388 public TdlsStatus getTdlsStatus(String macAdd) { 2389 synchronized (sLock) { 2390 if (isHalStarted()) { 2391 return getTdlsStatusNative(sWlan0Index, macAdd); 2392 } else { 2393 return null; 2394 } 2395 } 2396 } 2397 2398 //ToFix: Once TDLS per mac and event feature is implemented, this class definition should be 2399 // moved to the right place, like WifiStateMachine etc 2400 public static class TdlsCapabilities { 2401 /* Maximum TDLS session number can be supported by the Firmware and hardware */ 2402 int maxConcurrentTdlsSessionNumber; 2403 boolean isGlobalTdlsSupported; 2404 boolean isPerMacTdlsSupported; 2405 boolean isOffChannelTdlsSupported; 2406 } 2407 2408 2409 getTdlsCapabilitiesNative(int iface)2410 private static native TdlsCapabilities getTdlsCapabilitiesNative(int iface); getTdlsCapabilities()2411 public TdlsCapabilities getTdlsCapabilities () { 2412 synchronized (sLock) { 2413 if (isHalStarted()) { 2414 return getTdlsCapabilitiesNative(sWlan0Index); 2415 } else { 2416 return null; 2417 } 2418 } 2419 } 2420 onTdlsStatus(String macAddr, int status, int reason)2421 private static boolean onTdlsStatus(String macAddr, int status, int reason) { 2422 TdlsEventHandler handler = sTdlsEventHandler; 2423 if (handler == null) { 2424 return false; 2425 } else { 2426 handler.onTdlsStatus(macAddr, status, reason); 2427 return true; 2428 } 2429 } 2430 2431 //--------------------------------------------------------------------------------- 2432 2433 /* Wifi Logger commands/events */ 2434 2435 public static interface WifiLoggerEventHandler { onRingBufferData(RingBufferStatus status, byte[] buffer)2436 void onRingBufferData(RingBufferStatus status, byte[] buffer); onWifiAlert(int errorCode, byte[] buffer)2437 void onWifiAlert(int errorCode, byte[] buffer); 2438 } 2439 2440 private static WifiLoggerEventHandler sWifiLoggerEventHandler = null; 2441 2442 // Callback from native onRingBufferData(RingBufferStatus status, byte[] buffer)2443 private static void onRingBufferData(RingBufferStatus status, byte[] buffer) { 2444 WifiLoggerEventHandler handler = sWifiLoggerEventHandler; 2445 if (handler != null) 2446 handler.onRingBufferData(status, buffer); 2447 } 2448 2449 // Callback from native onWifiAlert(byte[] buffer, int errorCode)2450 private static void onWifiAlert(byte[] buffer, int errorCode) { 2451 WifiLoggerEventHandler handler = sWifiLoggerEventHandler; 2452 if (handler != null) 2453 handler.onWifiAlert(errorCode, buffer); 2454 } 2455 2456 private static int sLogCmdId = -1; setLoggingEventHandlerNative(int iface, int id)2457 private static native boolean setLoggingEventHandlerNative(int iface, int id); setLoggingEventHandler(WifiLoggerEventHandler handler)2458 public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) { 2459 synchronized (sLock) { 2460 if (isHalStarted()) { 2461 int oldId = sLogCmdId; 2462 sLogCmdId = getNewCmdIdLocked(); 2463 if (!setLoggingEventHandlerNative(sWlan0Index, sLogCmdId)) { 2464 sLogCmdId = oldId; 2465 return false; 2466 } 2467 sWifiLoggerEventHandler = handler; 2468 return true; 2469 } else { 2470 return false; 2471 } 2472 } 2473 } 2474 startLoggingRingBufferNative(int iface, int verboseLevel, int flags, int minIntervalSec ,int minDataSize, String ringName)2475 private static native boolean startLoggingRingBufferNative(int iface, int verboseLevel, 2476 int flags, int minIntervalSec ,int minDataSize, String ringName); startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, int minDataSize, String ringName)2477 public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, 2478 int minDataSize, String ringName){ 2479 synchronized (sLock) { 2480 if (isHalStarted()) { 2481 return startLoggingRingBufferNative(sWlan0Index, verboseLevel, flags, maxInterval, 2482 minDataSize, ringName); 2483 } else { 2484 return false; 2485 } 2486 } 2487 } 2488 getSupportedLoggerFeatureSetNative(int iface)2489 private static native int getSupportedLoggerFeatureSetNative(int iface); getSupportedLoggerFeatureSet()2490 public int getSupportedLoggerFeatureSet() { 2491 synchronized (sLock) { 2492 if (isHalStarted()) { 2493 return getSupportedLoggerFeatureSetNative(sWlan0Index); 2494 } else { 2495 return 0; 2496 } 2497 } 2498 } 2499 resetLogHandlerNative(int iface, int id)2500 private static native boolean resetLogHandlerNative(int iface, int id); resetLogHandler()2501 public boolean resetLogHandler() { 2502 synchronized (sLock) { 2503 if (isHalStarted()) { 2504 if (sLogCmdId == -1) { 2505 Log.e(TAG,"Can not reset handler Before set any handler"); 2506 return false; 2507 } 2508 sWifiLoggerEventHandler = null; 2509 if (resetLogHandlerNative(sWlan0Index, sLogCmdId)) { 2510 sLogCmdId = -1; 2511 return true; 2512 } else { 2513 return false; 2514 } 2515 } else { 2516 return false; 2517 } 2518 } 2519 } 2520 getDriverVersionNative(int iface)2521 private static native String getDriverVersionNative(int iface); getDriverVersion()2522 public String getDriverVersion() { 2523 synchronized (sLock) { 2524 if (isHalStarted()) { 2525 return getDriverVersionNative(sWlan0Index); 2526 } else { 2527 return ""; 2528 } 2529 } 2530 } 2531 2532 getFirmwareVersionNative(int iface)2533 private static native String getFirmwareVersionNative(int iface); getFirmwareVersion()2534 public String getFirmwareVersion() { 2535 synchronized (sLock) { 2536 if (isHalStarted()) { 2537 return getFirmwareVersionNative(sWlan0Index); 2538 } else { 2539 return ""; 2540 } 2541 } 2542 } 2543 2544 public static class RingBufferStatus{ 2545 String name; 2546 int flag; 2547 int ringBufferId; 2548 int ringBufferByteSize; 2549 int verboseLevel; 2550 int writtenBytes; 2551 int readBytes; 2552 int writtenRecords; 2553 2554 @Override toString()2555 public String toString() { 2556 return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId + 2557 " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel + 2558 " writtenBytes: " + writtenBytes + " readBytes: " + readBytes + 2559 " writtenRecords: " + writtenRecords; 2560 } 2561 } 2562 getRingBufferStatusNative(int iface)2563 private static native RingBufferStatus[] getRingBufferStatusNative(int iface); getRingBufferStatus()2564 public RingBufferStatus[] getRingBufferStatus() { 2565 synchronized (sLock) { 2566 if (isHalStarted()) { 2567 return getRingBufferStatusNative(sWlan0Index); 2568 } else { 2569 return null; 2570 } 2571 } 2572 } 2573 getRingBufferDataNative(int iface, String ringName)2574 private static native boolean getRingBufferDataNative(int iface, String ringName); getRingBufferData(String ringName)2575 public boolean getRingBufferData(String ringName) { 2576 synchronized (sLock) { 2577 if (isHalStarted()) { 2578 return getRingBufferDataNative(sWlan0Index, ringName); 2579 } else { 2580 return false; 2581 } 2582 } 2583 } 2584 2585 private static byte[] mFwMemoryDump; 2586 // Callback from native onWifiFwMemoryAvailable(byte[] buffer)2587 private static void onWifiFwMemoryAvailable(byte[] buffer) { 2588 mFwMemoryDump = buffer; 2589 if (DBG) { 2590 Log.d(TAG, "onWifiFwMemoryAvailable is called and buffer length is: " + 2591 (buffer == null ? 0 : buffer.length)); 2592 } 2593 } 2594 getFwMemoryDumpNative(int iface)2595 private static native boolean getFwMemoryDumpNative(int iface); getFwMemoryDump()2596 public byte[] getFwMemoryDump() { 2597 synchronized (sLock) { 2598 if (isHalStarted()) { 2599 if(getFwMemoryDumpNative(sWlan0Index)) { 2600 byte[] fwMemoryDump = mFwMemoryDump; 2601 mFwMemoryDump = null; 2602 return fwMemoryDump; 2603 } else { 2604 return null; 2605 } 2606 } 2607 return null; 2608 } 2609 } 2610 getDriverStateDumpNative(int iface)2611 private static native byte[] getDriverStateDumpNative(int iface); 2612 /** Fetch the driver state, for driver debugging. */ getDriverStateDump()2613 public byte[] getDriverStateDump() { 2614 synchronized (sLock) { 2615 if (isHalStarted()) { 2616 return getDriverStateDumpNative(sWlan0Index); 2617 } else { 2618 return null; 2619 } 2620 } 2621 } 2622 2623 //--------------------------------------------------------------------------------- 2624 /* Packet fate API */ 2625 2626 @Immutable 2627 abstract static class FateReport { 2628 final static int USEC_PER_MSEC = 1000; 2629 // The driver timestamp is a 32-bit counter, in microseconds. This field holds the 2630 // maximal value of a driver timestamp in milliseconds. 2631 final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000); 2632 final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS"); 2633 2634 final byte mFate; 2635 final long mDriverTimestampUSec; 2636 final byte mFrameType; 2637 final byte[] mFrameBytes; 2638 final long mEstimatedWallclockMSec; 2639 FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes)2640 FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 2641 mFate = fate; 2642 mDriverTimestampUSec = driverTimestampUSec; 2643 mEstimatedWallclockMSec = 2644 convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec); 2645 mFrameType = frameType; 2646 mFrameBytes = frameBytes; 2647 } 2648 toTableRowString()2649 public String toTableRowString() { 2650 StringWriter sw = new StringWriter(); 2651 PrintWriter pw = new PrintWriter(sw); 2652 FrameParser parser = new FrameParser(mFrameType, mFrameBytes); 2653 dateFormatter.setTimeZone(TimeZone.getDefault()); 2654 pw.format("%-15s %12s %-9s %-32s %-12s %-23s %s\n", 2655 mDriverTimestampUSec, 2656 dateFormatter.format(new Date(mEstimatedWallclockMSec)), 2657 directionToString(), fateToString(), parser.mMostSpecificProtocolString, 2658 parser.mTypeString, parser.mResultString); 2659 return sw.toString(); 2660 } 2661 toVerboseStringWithPiiAllowed()2662 public String toVerboseStringWithPiiAllowed() { 2663 StringWriter sw = new StringWriter(); 2664 PrintWriter pw = new PrintWriter(sw); 2665 FrameParser parser = new FrameParser(mFrameType, mFrameBytes); 2666 pw.format("Frame direction: %s\n", directionToString()); 2667 pw.format("Frame timestamp: %d\n", mDriverTimestampUSec); 2668 pw.format("Frame fate: %s\n", fateToString()); 2669 pw.format("Frame type: %s\n", frameTypeToString(mFrameType)); 2670 pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString); 2671 pw.format("Frame protocol type: %s\n", parser.mTypeString); 2672 pw.format("Frame length: %d\n", mFrameBytes.length); 2673 pw.append("Frame bytes"); 2674 pw.append(HexDump.dumpHexString(mFrameBytes)); // potentially contains PII 2675 pw.append("\n"); 2676 return sw.toString(); 2677 } 2678 2679 /* Returns a header to match the output of toTableRowString(). */ getTableHeader()2680 public static String getTableHeader() { 2681 StringWriter sw = new StringWriter(); 2682 PrintWriter pw = new PrintWriter(sw); 2683 pw.format("\n%-15s %-12s %-9s %-32s %-12s %-23s %s\n", 2684 "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result"); 2685 pw.format("%-15s %-12s %-9s %-32s %-12s %-23s %s\n", 2686 "---------", "--------", "---------", "----", "--------", "----", "------"); 2687 return sw.toString(); 2688 } 2689 directionToString()2690 protected abstract String directionToString(); 2691 fateToString()2692 protected abstract String fateToString(); 2693 frameTypeToString(byte frameType)2694 private static String frameTypeToString(byte frameType) { 2695 switch (frameType) { 2696 case WifiLoggerHal.FRAME_TYPE_UNKNOWN: 2697 return "unknown"; 2698 case WifiLoggerHal.FRAME_TYPE_ETHERNET_II: 2699 return "data"; 2700 case WifiLoggerHal.FRAME_TYPE_80211_MGMT: 2701 return "802.11 management"; 2702 default: 2703 return Byte.toString(frameType); 2704 } 2705 } 2706 2707 /** 2708 * Converts a driver timestamp to a wallclock time, based on the current 2709 * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of 2710 * microseconds, with the same base as BOOTTIME. 2711 */ convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec)2712 private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) { 2713 final long wallclockMillisNow = System.currentTimeMillis(); 2714 final long boottimeMillisNow = SystemClock.elapsedRealtime(); 2715 final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC; 2716 2717 long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC; 2718 if (boottimeTimestampMillis < driverTimestampMillis) { 2719 // The 32-bit microsecond count has wrapped between the time that the driver 2720 // recorded the packet, and the call to this function. Adjust the BOOTTIME 2721 // timestamp, to compensate. 2722 // 2723 // Note that overflow is not a concern here, since the result is less than 2724 // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above, 2725 // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since 2726 // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit 2727 // within a long. 2728 boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC; 2729 } 2730 2731 final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis; 2732 return wallclockMillisNow - millisSincePacketTimestamp; 2733 } 2734 } 2735 2736 /** 2737 * Represents the fate information for one outbound packet. 2738 */ 2739 @Immutable 2740 public static final class TxFateReport extends FateReport { TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes)2741 TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 2742 super(fate, driverTimestampUSec, frameType, frameBytes); 2743 } 2744 2745 @Override directionToString()2746 protected String directionToString() { 2747 return "TX"; 2748 } 2749 2750 @Override fateToString()2751 protected String fateToString() { 2752 switch (mFate) { 2753 case WifiLoggerHal.TX_PKT_FATE_ACKED: 2754 return "acked"; 2755 case WifiLoggerHal.TX_PKT_FATE_SENT: 2756 return "sent"; 2757 case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED: 2758 return "firmware queued"; 2759 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID: 2760 return "firmware dropped (invalid frame)"; 2761 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS: 2762 return "firmware dropped (no bufs)"; 2763 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER: 2764 return "firmware dropped (other)"; 2765 case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED: 2766 return "driver queued"; 2767 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID: 2768 return "driver dropped (invalid frame)"; 2769 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS: 2770 return "driver dropped (no bufs)"; 2771 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER: 2772 return "driver dropped (other)"; 2773 default: 2774 return Byte.toString(mFate); 2775 } 2776 } 2777 } 2778 2779 /** 2780 * Represents the fate information for one inbound packet. 2781 */ 2782 @Immutable 2783 public static final class RxFateReport extends FateReport { RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes)2784 RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 2785 super(fate, driverTimestampUSec, frameType, frameBytes); 2786 } 2787 2788 @Override directionToString()2789 protected String directionToString() { 2790 return "RX"; 2791 } 2792 2793 @Override fateToString()2794 protected String fateToString() { 2795 switch (mFate) { 2796 case WifiLoggerHal.RX_PKT_FATE_SUCCESS: 2797 return "success"; 2798 case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED: 2799 return "firmware queued"; 2800 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER: 2801 return "firmware dropped (filter)"; 2802 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID: 2803 return "firmware dropped (invalid frame)"; 2804 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS: 2805 return "firmware dropped (no bufs)"; 2806 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER: 2807 return "firmware dropped (other)"; 2808 case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED: 2809 return "driver queued"; 2810 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER: 2811 return "driver dropped (filter)"; 2812 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID: 2813 return "driver dropped (invalid frame)"; 2814 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS: 2815 return "driver dropped (no bufs)"; 2816 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER: 2817 return "driver dropped (other)"; 2818 default: 2819 return Byte.toString(mFate); 2820 } 2821 } 2822 } 2823 startPktFateMonitoringNative(int iface)2824 private static native int startPktFateMonitoringNative(int iface); 2825 /** 2826 * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started. 2827 */ startPktFateMonitoring()2828 public boolean startPktFateMonitoring() { 2829 synchronized (sLock) { 2830 if (isHalStarted()) { 2831 return startPktFateMonitoringNative(sWlan0Index) == WIFI_SUCCESS; 2832 } else { 2833 return false; 2834 } 2835 } 2836 } 2837 getTxPktFatesNative(int iface, TxFateReport[] reportBufs)2838 private static native int getTxPktFatesNative(int iface, TxFateReport[] reportBufs); 2839 /** 2840 * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started. 2841 */ getTxPktFates(TxFateReport[] reportBufs)2842 public boolean getTxPktFates(TxFateReport[] reportBufs) { 2843 synchronized (sLock) { 2844 if (isHalStarted()) { 2845 int res = getTxPktFatesNative(sWlan0Index, reportBufs); 2846 if (res != WIFI_SUCCESS) { 2847 Log.e(TAG, "getTxPktFatesNative returned " + res); 2848 return false; 2849 } else { 2850 return true; 2851 } 2852 } else { 2853 return false; 2854 } 2855 } 2856 } 2857 getRxPktFatesNative(int iface, RxFateReport[] reportBufs)2858 private static native int getRxPktFatesNative(int iface, RxFateReport[] reportBufs); 2859 /** 2860 * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started. 2861 */ getRxPktFates(RxFateReport[] reportBufs)2862 public boolean getRxPktFates(RxFateReport[] reportBufs) { 2863 synchronized (sLock) { 2864 if (isHalStarted()) { 2865 int res = getRxPktFatesNative(sWlan0Index, reportBufs); 2866 if (res != WIFI_SUCCESS) { 2867 Log.e(TAG, "getRxPktFatesNative returned " + res); 2868 return false; 2869 } else { 2870 return true; 2871 } 2872 } else { 2873 return false; 2874 } 2875 } 2876 } 2877 2878 //--------------------------------------------------------------------------------- 2879 /* Configure ePNO/PNO */ 2880 private static PnoEventHandler sPnoEventHandler; 2881 private static int sPnoCmdId = 0; 2882 setPnoListNative(int iface, int id, PnoSettings settings)2883 private static native boolean setPnoListNative(int iface, int id, PnoSettings settings); 2884 2885 /** 2886 * Set the PNO settings & the network list in HAL to start PNO. 2887 * @param settings PNO settings and network list. 2888 * @param eventHandler Handler to receive notifications back during PNO scan. 2889 * @return true if success, false otherwise 2890 */ setPnoList(PnoSettings settings, PnoEventHandler eventHandler)2891 public boolean setPnoList(PnoSettings settings, PnoEventHandler eventHandler) { 2892 Log.e(TAG, "setPnoList cmd " + sPnoCmdId); 2893 2894 synchronized (sLock) { 2895 if (isHalStarted()) { 2896 sPnoCmdId = getNewCmdIdLocked(); 2897 sPnoEventHandler = eventHandler; 2898 if (setPnoListNative(sWlan0Index, sPnoCmdId, settings)) { 2899 return true; 2900 } 2901 } 2902 sPnoEventHandler = null; 2903 return false; 2904 } 2905 } 2906 2907 /** 2908 * Set the PNO network list in HAL to start PNO. 2909 * @param list PNO network list. 2910 * @param eventHandler Handler to receive notifications back during PNO scan. 2911 * @return true if success, false otherwise 2912 */ setPnoList(PnoNetwork[] list, PnoEventHandler eventHandler)2913 public boolean setPnoList(PnoNetwork[] list, PnoEventHandler eventHandler) { 2914 PnoSettings settings = new PnoSettings(); 2915 settings.networkList = list; 2916 return setPnoList(settings, eventHandler); 2917 } 2918 resetPnoListNative(int iface, int id)2919 private static native boolean resetPnoListNative(int iface, int id); 2920 2921 /** 2922 * Reset the PNO settings in HAL to stop PNO. 2923 * @return true if success, false otherwise 2924 */ resetPnoList()2925 public boolean resetPnoList() { 2926 Log.e(TAG, "resetPnoList cmd " + sPnoCmdId); 2927 2928 synchronized (sLock) { 2929 if (isHalStarted()) { 2930 sPnoCmdId = getNewCmdIdLocked(); 2931 sPnoEventHandler = null; 2932 if (resetPnoListNative(sWlan0Index, sPnoCmdId)) { 2933 return true; 2934 } 2935 } 2936 return false; 2937 } 2938 } 2939 2940 // Callback from native onPnoNetworkFound(int id, ScanResult[] results, int[] beaconCaps)2941 private static void onPnoNetworkFound(int id, ScanResult[] results, int[] beaconCaps) { 2942 if (results == null) { 2943 Log.e(TAG, "onPnoNetworkFound null results"); 2944 return; 2945 2946 } 2947 Log.d(TAG, "WifiNative.onPnoNetworkFound result " + results.length); 2948 2949 PnoEventHandler handler = sPnoEventHandler; 2950 if (sPnoCmdId != 0 && handler != null) { 2951 for (int i=0; i<results.length; i++) { 2952 Log.e(TAG, "onPnoNetworkFound SSID " + results[i].SSID 2953 + " " + results[i].level + " " + results[i].frequency); 2954 2955 populateScanResult(results[i], beaconCaps[i], "onPnoNetworkFound "); 2956 results[i].wifiSsid = WifiSsid.createFromAsciiEncoded(results[i].SSID); 2957 } 2958 2959 handler.onPnoNetworkFound(results); 2960 } else { 2961 /* this can happen because of race conditions */ 2962 Log.d(TAG, "Ignoring Pno Network found event"); 2963 } 2964 } 2965 setBssidBlacklistNative(int iface, int id, String list[])2966 private native static boolean setBssidBlacklistNative(int iface, int id, 2967 String list[]); 2968 setBssidBlacklist(String list[])2969 public boolean setBssidBlacklist(String list[]) { 2970 int size = 0; 2971 if (list != null) { 2972 size = list.length; 2973 } 2974 Log.e(TAG, "setBssidBlacklist cmd " + sPnoCmdId + " size " + size); 2975 2976 synchronized (sLock) { 2977 if (isHalStarted()) { 2978 sPnoCmdId = getNewCmdIdLocked(); 2979 return setBssidBlacklistNative(sWlan0Index, sPnoCmdId, list); 2980 } else { 2981 return false; 2982 } 2983 } 2984 } 2985 startSendingOffloadedPacketNative(int iface, int idx, byte[] srcMac, byte[] dstMac, byte[] pktData, int period)2986 private native static int startSendingOffloadedPacketNative(int iface, int idx, 2987 byte[] srcMac, byte[] dstMac, byte[] pktData, int period); 2988 2989 public int startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket, int period)2990 startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket, int period) { 2991 Log.d(TAG, "startSendingOffloadedPacket slot=" + slot + " period=" + period); 2992 2993 String[] macAddrStr = getMacAddress().split(":"); 2994 byte[] srcMac = new byte[6]; 2995 for(int i = 0; i < 6; i++) { 2996 Integer hexVal = Integer.parseInt(macAddrStr[i], 16); 2997 srcMac[i] = hexVal.byteValue(); 2998 } 2999 synchronized (sLock) { 3000 if (isHalStarted()) { 3001 return startSendingOffloadedPacketNative(sWlan0Index, slot, srcMac, 3002 keepAlivePacket.dstMac, keepAlivePacket.data, period); 3003 } else { 3004 return -1; 3005 } 3006 } 3007 } 3008 stopSendingOffloadedPacketNative(int iface, int idx)3009 private native static int stopSendingOffloadedPacketNative(int iface, int idx); 3010 3011 public int stopSendingOffloadedPacket(int slot)3012 stopSendingOffloadedPacket(int slot) { 3013 Log.d(TAG, "stopSendingOffloadedPacket " + slot); 3014 synchronized (sLock) { 3015 if (isHalStarted()) { 3016 return stopSendingOffloadedPacketNative(sWlan0Index, slot); 3017 } else { 3018 return -1; 3019 } 3020 } 3021 } 3022 3023 public static interface WifiRssiEventHandler { onRssiThresholdBreached(byte curRssi)3024 void onRssiThresholdBreached(byte curRssi); 3025 } 3026 3027 private static WifiRssiEventHandler sWifiRssiEventHandler; 3028 3029 // Callback from native onRssiThresholdBreached(int id, byte curRssi)3030 private static void onRssiThresholdBreached(int id, byte curRssi) { 3031 WifiRssiEventHandler handler = sWifiRssiEventHandler; 3032 if (handler != null) { 3033 handler.onRssiThresholdBreached(curRssi); 3034 } 3035 } 3036 startRssiMonitoringNative(int iface, int id, byte maxRssi, byte minRssi)3037 private native static int startRssiMonitoringNative(int iface, int id, 3038 byte maxRssi, byte minRssi); 3039 3040 private static int sRssiMonitorCmdId = 0; 3041 startRssiMonitoring(byte maxRssi, byte minRssi, WifiRssiEventHandler rssiEventHandler)3042 public int startRssiMonitoring(byte maxRssi, byte minRssi, 3043 WifiRssiEventHandler rssiEventHandler) { 3044 Log.d(TAG, "startRssiMonitoring: maxRssi=" + maxRssi + " minRssi=" + minRssi); 3045 synchronized (sLock) { 3046 sWifiRssiEventHandler = rssiEventHandler; 3047 if (isHalStarted()) { 3048 if (sRssiMonitorCmdId != 0) { 3049 stopRssiMonitoring(); 3050 } 3051 3052 sRssiMonitorCmdId = getNewCmdIdLocked(); 3053 Log.d(TAG, "sRssiMonitorCmdId = " + sRssiMonitorCmdId); 3054 int ret = startRssiMonitoringNative(sWlan0Index, sRssiMonitorCmdId, 3055 maxRssi, minRssi); 3056 if (ret != 0) { // if not success 3057 sRssiMonitorCmdId = 0; 3058 } 3059 return ret; 3060 } else { 3061 return -1; 3062 } 3063 } 3064 } 3065 stopRssiMonitoringNative(int iface, int idx)3066 private native static int stopRssiMonitoringNative(int iface, int idx); 3067 stopRssiMonitoring()3068 public int stopRssiMonitoring() { 3069 Log.d(TAG, "stopRssiMonitoring, cmdId " + sRssiMonitorCmdId); 3070 synchronized (sLock) { 3071 if (isHalStarted()) { 3072 int ret = 0; 3073 if (sRssiMonitorCmdId != 0) { 3074 ret = stopRssiMonitoringNative(sWlan0Index, sRssiMonitorCmdId); 3075 } 3076 sRssiMonitorCmdId = 0; 3077 return ret; 3078 } else { 3079 return -1; 3080 } 3081 } 3082 } 3083 getWlanWakeReasonCountNative(int iface)3084 private static native WifiWakeReasonAndCounts getWlanWakeReasonCountNative(int iface); 3085 3086 /** 3087 * Fetch the host wakeup reasons stats from wlan driver. 3088 * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver. 3089 */ getWlanWakeReasonCount()3090 public WifiWakeReasonAndCounts getWlanWakeReasonCount() { 3091 Log.d(TAG, "getWlanWakeReasonCount " + sWlan0Index); 3092 synchronized (sLock) { 3093 if (isHalStarted()) { 3094 return getWlanWakeReasonCountNative(sWlan0Index); 3095 } else { 3096 return null; 3097 } 3098 } 3099 } 3100 configureNeighborDiscoveryOffload(int iface, boolean enabled)3101 private static native int configureNeighborDiscoveryOffload(int iface, boolean enabled); 3102 configureNeighborDiscoveryOffload(boolean enabled)3103 public boolean configureNeighborDiscoveryOffload(boolean enabled) { 3104 final String logMsg = "configureNeighborDiscoveryOffload(" + enabled + ")"; 3105 Log.d(mTAG, logMsg); 3106 synchronized (sLock) { 3107 if (isHalStarted()) { 3108 final int ret = configureNeighborDiscoveryOffload(sWlan0Index, enabled); 3109 if (ret != 0) { 3110 Log.d(mTAG, logMsg + " returned: " + ret); 3111 } 3112 return (ret == 0); 3113 } 3114 } 3115 return false; 3116 } 3117 } 3118