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.net.apf.ApfCapabilities; 21 import android.net.wifi.IApInterface; 22 import android.net.wifi.IClientInterface; 23 import android.net.wifi.RttManager; 24 import android.net.wifi.RttManager.ResponderConfig; 25 import android.net.wifi.ScanResult; 26 import android.net.wifi.WifiConfiguration; 27 import android.net.wifi.WifiLinkLayerStats; 28 import android.net.wifi.WifiScanner; 29 import android.net.wifi.WifiWakeReasonAndCounts; 30 import android.os.SystemClock; 31 import android.util.Log; 32 import android.util.SparseArray; 33 34 import com.android.internal.annotations.Immutable; 35 import com.android.internal.util.HexDump; 36 import com.android.server.connectivity.KeepalivePacketData; 37 import com.android.server.wifi.util.FrameParser; 38 39 import java.io.PrintWriter; 40 import java.io.StringWriter; 41 import java.nio.ByteBuffer; 42 import java.nio.CharBuffer; 43 import java.nio.charset.CharacterCodingException; 44 import java.nio.charset.CharsetDecoder; 45 import java.nio.charset.StandardCharsets; 46 import java.text.SimpleDateFormat; 47 import java.util.ArrayList; 48 import java.util.Date; 49 import java.util.Map; 50 import java.util.Objects; 51 import java.util.Set; 52 import java.util.TimeZone; 53 54 55 /** 56 * Native calls for bring up/shut down of the supplicant daemon and for 57 * sending requests to the supplicant daemon 58 * 59 * {@hide} 60 */ 61 public class WifiNative { 62 private final String mTAG; 63 private final String mInterfaceName; 64 private final SupplicantStaIfaceHal mSupplicantStaIfaceHal; 65 private final WifiVendorHal mWifiVendorHal; 66 private final WificondControl mWificondControl; 67 68 public WifiNative(String interfaceName, WifiVendorHal vendorHal, 69 SupplicantStaIfaceHal staIfaceHal, WificondControl condControl) { 70 mTAG = "WifiNative-" + interfaceName; 71 mInterfaceName = interfaceName; 72 mWifiVendorHal = vendorHal; 73 mSupplicantStaIfaceHal = staIfaceHal; 74 mWificondControl = condControl; 75 } 76 77 public String getInterfaceName() { 78 return mInterfaceName; 79 } 80 81 /** 82 * Enable verbose logging for all sub modules. 83 */ 84 public void enableVerboseLogging(int verbose) { 85 mWificondControl.enableVerboseLogging(verbose > 0 ? true : false); 86 mSupplicantStaIfaceHal.enableVerboseLogging(verbose > 0); 87 mWifiVendorHal.enableVerboseLogging(verbose > 0); 88 } 89 90 /******************************************************** 91 * Native Initialization/Deinitialization 92 ********************************************************/ 93 94 /** 95 * Setup wifi native for Client mode operations. 96 * 97 * 1. Starts the Wifi HAL and configures it in client/STA mode. 98 * 2. Setup Wificond to operate in client mode and retrieve the handle to use for client 99 * operations. 100 * 101 * @return An IClientInterface as wificond client interface binder handler. 102 * Returns null on failure. 103 */ 104 public IClientInterface setupForClientMode() { 105 if (!startHalIfNecessary(true)) { 106 Log.e(mTAG, "Failed to start HAL for client mode"); 107 return null; 108 } 109 return mWificondControl.setupDriverForClientMode(); 110 } 111 112 /** 113 * Setup wifi native for AP mode operations. 114 * 115 * 1. Starts the Wifi HAL and configures it in AP mode. 116 * 2. Setup Wificond to operate in AP mode and retrieve the handle to use for ap operations. 117 * 118 * @return An IApInterface as wificond Ap interface binder handler. 119 * Returns null on failure. 120 */ 121 public IApInterface setupForSoftApMode() { 122 if (!startHalIfNecessary(false)) { 123 Log.e(mTAG, "Failed to start HAL for AP mode"); 124 return null; 125 } 126 return mWificondControl.setupDriverForSoftApMode(); 127 } 128 129 /** 130 * Teardown all mode configurations in wifi native. 131 * 132 * 1. Tears down all the interfaces from Wificond. 133 * 2. Stops the Wifi HAL. 134 * 135 * @return Returns true on success. 136 */ 137 public boolean tearDown() { 138 if (!mWificondControl.tearDownInterfaces()) { 139 // TODO(b/34859006): Handle failures. 140 Log.e(mTAG, "Failed to teardown interfaces from Wificond"); 141 return false; 142 } 143 stopHalIfNecessary(); 144 return true; 145 } 146 147 /******************************************************** 148 * Wificond operations 149 ********************************************************/ 150 /** 151 * Result of a signal poll. 152 */ 153 public static class SignalPollResult { 154 // RSSI value in dBM. 155 public int currentRssi; 156 //Transmission bit rate in Mbps. 157 public int txBitrate; 158 // Association frequency in MHz. 159 public int associationFrequency; 160 } 161 162 /** 163 * WiFi interface transimission counters. 164 */ 165 public static class TxPacketCounters { 166 // Number of successfully transmitted packets. 167 public int txSucceeded; 168 // Number of tramsmission failures. 169 public int txFailed; 170 } 171 172 /** 173 * Disable wpa_supplicant via wificond. 174 * @return Returns true on success. 175 */ 176 public boolean disableSupplicant() { 177 return mWificondControl.disableSupplicant(); 178 } 179 180 /** 181 * Enable wpa_supplicant via wificond. 182 * @return Returns true on success. 183 */ 184 public boolean enableSupplicant() { 185 return mWificondControl.enableSupplicant(); 186 } 187 188 /** 189 * Request signal polling to wificond. 190 * Returns an SignalPollResult object. 191 * Returns null on failure. 192 */ 193 public SignalPollResult signalPoll() { 194 return mWificondControl.signalPoll(); 195 } 196 197 /** 198 * Fetch TX packet counters on current connection from wificond. 199 * Returns an TxPacketCounters object. 200 * Returns null on failure. 201 */ 202 public TxPacketCounters getTxPacketCounters() { 203 return mWificondControl.getTxPacketCounters(); 204 } 205 206 /** 207 * Start a scan using wificond for the given parameters. 208 * @param freqs list of frequencies to scan for, if null scan all supported channels. 209 * @param hiddenNetworkSSIDs List of hidden networks to be scanned for. 210 * @return Returns true on success. 211 */ 212 public boolean scan(Set<Integer> freqs, Set<String> hiddenNetworkSSIDs) { 213 return mWificondControl.scan(freqs, hiddenNetworkSSIDs); 214 } 215 216 /** 217 * Fetch the latest scan result from kernel via wificond. 218 * @return Returns an ArrayList of ScanDetail. 219 * Returns an empty ArrayList on failure. 220 */ 221 public ArrayList<ScanDetail> getScanResults() { 222 return mWificondControl.getScanResults(); 223 } 224 225 /** 226 * Start PNO scan. 227 * @param pnoSettings Pno scan configuration. 228 * @return true on success. 229 */ 230 public boolean startPnoScan(PnoSettings pnoSettings) { 231 return mWificondControl.startPnoScan(pnoSettings); 232 } 233 234 /** 235 * Stop PNO scan. 236 * @return true on success. 237 */ 238 public boolean stopPnoScan() { 239 return mWificondControl.stopPnoScan(); 240 } 241 242 /******************************************************** 243 * Supplicant operations 244 ********************************************************/ 245 246 /** 247 * This method is called repeatedly until the connection to wpa_supplicant is established. 248 * 249 * @return true if connection is established, false otherwise. 250 * TODO: Add unit tests for these once we remove the legacy code. 251 */ 252 public boolean connectToSupplicant() { 253 // Start initialization if not already started. 254 if (!mSupplicantStaIfaceHal.isInitializationStarted() 255 && !mSupplicantStaIfaceHal.initialize()) { 256 return false; 257 } 258 // Check if the initialization is complete. 259 return mSupplicantStaIfaceHal.isInitializationComplete(); 260 } 261 262 /** 263 * Close supplicant connection. 264 */ 265 public void closeSupplicantConnection() { 266 // Nothing to do for HIDL. 267 } 268 269 /** 270 * Set supplicant log level 271 * 272 * @param turnOnVerbose Whether to turn on verbose logging or not. 273 */ 274 public void setSupplicantLogLevel(boolean turnOnVerbose) { 275 mSupplicantStaIfaceHal.setLogLevel(turnOnVerbose); 276 } 277 278 /** 279 * Trigger a reconnection if the iface is disconnected. 280 * 281 * @return true if request is sent successfully, false otherwise. 282 */ 283 public boolean reconnect() { 284 return mSupplicantStaIfaceHal.reconnect(); 285 } 286 287 /** 288 * Trigger a reassociation even if the iface is currently connected. 289 * 290 * @return true if request is sent successfully, false otherwise. 291 */ 292 public boolean reassociate() { 293 return mSupplicantStaIfaceHal.reassociate(); 294 } 295 296 /** 297 * Trigger a disconnection from the currently connected network. 298 * 299 * @return true if request is sent successfully, false otherwise. 300 */ 301 public boolean disconnect() { 302 return mSupplicantStaIfaceHal.disconnect(); 303 } 304 305 /** 306 * Makes a callback to HIDL to getMacAddress from supplicant 307 * 308 * @return string containing the MAC address, or null on a failed call 309 */ 310 public String getMacAddress() { 311 return mSupplicantStaIfaceHal.getMacAddress(); 312 } 313 314 public static final int RX_FILTER_TYPE_V4_MULTICAST = 0; 315 public static final int RX_FILTER_TYPE_V6_MULTICAST = 1; 316 /** 317 * Start filtering out Multicast V4 packets 318 * @return {@code true} if the operation succeeded, {@code false} otherwise 319 * 320 * Multicast filtering rules work as follows: 321 * 322 * The driver can filter multicast (v4 and/or v6) and broadcast packets when in 323 * a power optimized mode (typically when screen goes off). 324 * 325 * In order to prevent the driver from filtering the multicast/broadcast packets, we have to 326 * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective 327 * 328 * DRIVER RXFILTER-ADD Num 329 * where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6 330 * 331 * and DRIVER RXFILTER-START 332 * In order to stop the usage of these rules, we do 333 * 334 * DRIVER RXFILTER-STOP 335 * DRIVER RXFILTER-REMOVE Num 336 * where Num is as described for RXFILTER-ADD 337 * 338 * The SETSUSPENDOPT driver command overrides the filtering rules 339 */ 340 public boolean startFilteringMulticastV4Packets() { 341 return mSupplicantStaIfaceHal.stopRxFilter() 342 && mSupplicantStaIfaceHal.removeRxFilter( 343 RX_FILTER_TYPE_V4_MULTICAST) 344 && mSupplicantStaIfaceHal.startRxFilter(); 345 } 346 347 /** 348 * Stop filtering out Multicast V4 packets. 349 * @return {@code true} if the operation succeeded, {@code false} otherwise 350 */ 351 public boolean stopFilteringMulticastV4Packets() { 352 return mSupplicantStaIfaceHal.stopRxFilter() 353 && mSupplicantStaIfaceHal.addRxFilter( 354 RX_FILTER_TYPE_V4_MULTICAST) 355 && mSupplicantStaIfaceHal.startRxFilter(); 356 } 357 358 /** 359 * Start filtering out Multicast V6 packets 360 * @return {@code true} if the operation succeeded, {@code false} otherwise 361 */ 362 public boolean startFilteringMulticastV6Packets() { 363 return mSupplicantStaIfaceHal.stopRxFilter() 364 && mSupplicantStaIfaceHal.removeRxFilter( 365 RX_FILTER_TYPE_V6_MULTICAST) 366 && mSupplicantStaIfaceHal.startRxFilter(); 367 } 368 369 /** 370 * Stop filtering out Multicast V6 packets. 371 * @return {@code true} if the operation succeeded, {@code false} otherwise 372 */ 373 public boolean stopFilteringMulticastV6Packets() { 374 return mSupplicantStaIfaceHal.stopRxFilter() 375 && mSupplicantStaIfaceHal.addRxFilter( 376 RX_FILTER_TYPE_V6_MULTICAST) 377 && mSupplicantStaIfaceHal.startRxFilter(); 378 } 379 380 public static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0; 381 public static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1; 382 public static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2; 383 /** 384 * Sets the bluetooth coexistence mode. 385 * 386 * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED}, 387 * {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or 388 * {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}. 389 * @return Whether the mode was successfully set. 390 */ 391 public boolean setBluetoothCoexistenceMode(int mode) { 392 return mSupplicantStaIfaceHal.setBtCoexistenceMode(mode); 393 } 394 395 /** 396 * Enable or disable Bluetooth coexistence scan mode. When this mode is on, 397 * some of the low-level scan parameters used by the driver are changed to 398 * reduce interference with A2DP streaming. 399 * 400 * @param setCoexScanMode whether to enable or disable this mode 401 * @return {@code true} if the command succeeded, {@code false} otherwise. 402 */ 403 public boolean setBluetoothCoexistenceScanMode(boolean setCoexScanMode) { 404 return mSupplicantStaIfaceHal.setBtCoexistenceScanModeEnabled(setCoexScanMode); 405 } 406 407 /** 408 * Enable or disable suspend mode optimizations. 409 * 410 * @param enabled true to enable, false otherwise. 411 * @return true if request is sent successfully, false otherwise. 412 */ 413 public boolean setSuspendOptimizations(boolean enabled) { 414 return mSupplicantStaIfaceHal.setSuspendModeEnabled(enabled); 415 } 416 417 /** 418 * Set country code. 419 * 420 * @param countryCode 2 byte ASCII string. For ex: US, CA. 421 * @return true if request is sent successfully, false otherwise. 422 */ 423 public boolean setCountryCode(String countryCode) { 424 return mSupplicantStaIfaceHal.setCountryCode(countryCode); 425 } 426 427 /** 428 * Initiate TDLS discover and setup or teardown with the specified peer. 429 * 430 * @param macAddr MAC Address of the peer. 431 * @param enable true to start discovery and setup, false to teardown. 432 */ 433 public void startTdls(String macAddr, boolean enable) { 434 if (enable) { 435 mSupplicantStaIfaceHal.initiateTdlsDiscover(macAddr); 436 mSupplicantStaIfaceHal.initiateTdlsSetup(macAddr); 437 } else { 438 mSupplicantStaIfaceHal.initiateTdlsTeardown(macAddr); 439 } 440 } 441 442 /** 443 * Start WPS pin display operation with the specified peer. 444 * 445 * @param bssid BSSID of the peer. 446 * @return true if request is sent successfully, false otherwise. 447 */ 448 public boolean startWpsPbc(String bssid) { 449 return mSupplicantStaIfaceHal.startWpsPbc(bssid); 450 } 451 452 /** 453 * Start WPS pin keypad operation with the specified pin. 454 * 455 * @param pin Pin to be used. 456 * @return true if request is sent successfully, false otherwise. 457 */ 458 public boolean startWpsPinKeypad(String pin) { 459 return mSupplicantStaIfaceHal.startWpsPinKeypad(pin); 460 } 461 462 /** 463 * Start WPS pin display operation with the specified peer. 464 * 465 * @param bssid BSSID of the peer. 466 * @return new pin generated on success, null otherwise. 467 */ 468 public String startWpsPinDisplay(String bssid) { 469 return mSupplicantStaIfaceHal.startWpsPinDisplay(bssid); 470 } 471 472 /** 473 * Sets whether to use external sim for SIM/USIM processing. 474 * 475 * @param external true to enable, false otherwise. 476 * @return true if request is sent successfully, false otherwise. 477 */ 478 public boolean setExternalSim(boolean external) { 479 return mSupplicantStaIfaceHal.setExternalSim(external); 480 } 481 482 /** 483 * Sim auth response types. 484 */ 485 public static final String SIM_AUTH_RESP_TYPE_GSM_AUTH = "GSM-AUTH"; 486 public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTH = "UMTS-AUTH"; 487 public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTS = "UMTS-AUTS"; 488 489 /** 490 * Send the sim auth response for the currently configured network. 491 * 492 * @param type |GSM-AUTH|, |UMTS-AUTH| or |UMTS-AUTS|. 493 * @param response Response params. 494 * @return true if succeeds, false otherwise. 495 */ 496 public boolean simAuthResponse(int id, String type, String response) { 497 if (SIM_AUTH_RESP_TYPE_GSM_AUTH.equals(type)) { 498 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthResponse(response); 499 } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTH.equals(type)) { 500 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthResponse(response); 501 } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTS.equals(type)) { 502 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAutsResponse(response); 503 } else { 504 return false; 505 } 506 } 507 508 /** 509 * Send the eap sim gsm auth failure for the currently configured network. 510 * 511 * @return true if succeeds, false otherwise. 512 */ 513 public boolean simAuthFailedResponse(int id) { 514 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthFailure(); 515 } 516 517 /** 518 * Send the eap sim umts auth failure for the currently configured network. 519 * 520 * @return true if succeeds, false otherwise. 521 */ 522 public boolean umtsAuthFailedResponse(int id) { 523 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthFailure(); 524 } 525 526 /** 527 * Send the eap identity response for the currently configured network. 528 * 529 * @param response String to send. 530 * @return true if succeeds, false otherwise. 531 */ 532 public boolean simIdentityResponse(int id, String response) { 533 return mSupplicantStaIfaceHal.sendCurrentNetworkEapIdentityResponse(response); 534 } 535 536 /** 537 * This get anonymous identity from supplicant and returns it as a string. 538 * 539 * @return anonymous identity string if succeeds, null otherwise. 540 */ 541 public String getEapAnonymousIdentity() { 542 return mSupplicantStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(); 543 } 544 545 /** 546 * Start WPS pin registrar operation with the specified peer and pin. 547 * 548 * @param bssid BSSID of the peer. 549 * @param pin Pin to be used. 550 * @return true if request is sent successfully, false otherwise. 551 */ 552 public boolean startWpsRegistrar(String bssid, String pin) { 553 return mSupplicantStaIfaceHal.startWpsRegistrar(bssid, pin); 554 } 555 556 /** 557 * Cancels any ongoing WPS requests. 558 * 559 * @return true if request is sent successfully, false otherwise. 560 */ 561 public boolean cancelWps() { 562 return mSupplicantStaIfaceHal.cancelWps(); 563 } 564 565 /** 566 * Set WPS device name. 567 * 568 * @param name String to be set. 569 * @return true if request is sent successfully, false otherwise. 570 */ 571 public boolean setDeviceName(String name) { 572 return mSupplicantStaIfaceHal.setWpsDeviceName(name); 573 } 574 575 /** 576 * Set WPS device type. 577 * 578 * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg> 579 * @return true if request is sent successfully, false otherwise. 580 */ 581 public boolean setDeviceType(String type) { 582 return mSupplicantStaIfaceHal.setWpsDeviceType(type); 583 } 584 585 /** 586 * Set WPS config methods 587 * 588 * @param cfg List of config methods. 589 * @return true if request is sent successfully, false otherwise. 590 */ 591 public boolean setConfigMethods(String cfg) { 592 return mSupplicantStaIfaceHal.setWpsConfigMethods(cfg); 593 } 594 595 /** 596 * Set WPS manufacturer. 597 * 598 * @param value String to be set. 599 * @return true if request is sent successfully, false otherwise. 600 */ 601 public boolean setManufacturer(String value) { 602 return mSupplicantStaIfaceHal.setWpsManufacturer(value); 603 } 604 605 /** 606 * Set WPS model name. 607 * 608 * @param value String to be set. 609 * @return true if request is sent successfully, false otherwise. 610 */ 611 public boolean setModelName(String value) { 612 return mSupplicantStaIfaceHal.setWpsModelName(value); 613 } 614 615 /** 616 * Set WPS model number. 617 * 618 * @param value String to be set. 619 * @return true if request is sent successfully, false otherwise. 620 */ 621 public boolean setModelNumber(String value) { 622 return mSupplicantStaIfaceHal.setWpsModelNumber(value); 623 } 624 625 /** 626 * Set WPS serial number. 627 * 628 * @param value String to be set. 629 * @return true if request is sent successfully, false otherwise. 630 */ 631 public boolean setSerialNumber(String value) { 632 return mSupplicantStaIfaceHal.setWpsSerialNumber(value); 633 } 634 635 /** 636 * Enable or disable power save mode. 637 * 638 * @param enabled true to enable, false to disable. 639 */ 640 public void setPowerSave(boolean enabled) { 641 mSupplicantStaIfaceHal.setPowerSave(enabled); 642 } 643 644 /** 645 * Set concurrency priority between P2P & STA operations. 646 * 647 * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations, 648 * false otherwise. 649 * @return true if request is sent successfully, false otherwise. 650 */ 651 public boolean setConcurrencyPriority(boolean isStaHigherPriority) { 652 return mSupplicantStaIfaceHal.setConcurrencyPriority(isStaHigherPriority); 653 } 654 655 /** 656 * Enable/Disable auto reconnect functionality in wpa_supplicant. 657 * 658 * @param enable true to enable auto reconnecting, false to disable. 659 * @return true if request is sent successfully, false otherwise. 660 */ 661 public boolean enableStaAutoReconnect(boolean enable) { 662 return mSupplicantStaIfaceHal.enableAutoReconnect(enable); 663 } 664 665 /** 666 * Migrate all the configured networks from wpa_supplicant. 667 * 668 * @param configs Map of configuration key to configuration objects corresponding to all 669 * the networks. 670 * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf 671 * @return Max priority of all the configs. 672 */ 673 public boolean migrateNetworksFromSupplicant(Map<String, WifiConfiguration> configs, 674 SparseArray<Map<String, String>> networkExtras) { 675 return mSupplicantStaIfaceHal.loadNetworks(configs, networkExtras); 676 } 677 678 /** 679 * Add the provided network configuration to wpa_supplicant and initiate connection to it. 680 * This method does the following: 681 * 1. Abort any ongoing scan to unblock the connection request. 682 * 2. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect). 683 * 3. Add a new network to wpa_supplicant. 684 * 4. Save the provided configuration to wpa_supplicant. 685 * 5. Select the new network in wpa_supplicant. 686 * 6. Triggers reconnect command to wpa_supplicant. 687 * 688 * @param configuration WifiConfiguration parameters for the provided network. 689 * @return {@code true} if it succeeds, {@code false} otherwise 690 */ 691 public boolean connectToNetwork(WifiConfiguration configuration) { 692 // Abort ongoing scan before connect() to unblock connection request. 693 mWificondControl.abortScan(); 694 return mSupplicantStaIfaceHal.connectToNetwork(configuration); 695 } 696 697 /** 698 * Initiates roaming to the already configured network in wpa_supplicant. If the network 699 * configuration provided does not match the already configured network, then this triggers 700 * a new connection attempt (instead of roam). 701 * 1. Abort any ongoing scan to unblock the roam request. 702 * 2. First check if we're attempting to connect to the same network as we currently have 703 * configured. 704 * 3. Set the new bssid for the network in wpa_supplicant. 705 * 4. Triggers reassociate command to wpa_supplicant. 706 * 707 * @param configuration WifiConfiguration parameters for the provided network. 708 * @return {@code true} if it succeeds, {@code false} otherwise 709 */ 710 public boolean roamToNetwork(WifiConfiguration configuration) { 711 // Abort ongoing scan before connect() to unblock roaming request. 712 mWificondControl.abortScan(); 713 return mSupplicantStaIfaceHal.roamToNetwork(configuration); 714 } 715 716 /** 717 * Get the framework network ID corresponding to the provided supplicant network ID for the 718 * network configured in wpa_supplicant. 719 * 720 * @param supplicantNetworkId network ID in wpa_supplicant for the network. 721 * @return Corresponding framework network ID if found, -1 if network not found. 722 */ 723 public int getFrameworkNetworkId(int supplicantNetworkId) { 724 return supplicantNetworkId; 725 } 726 727 /** 728 * Remove all the networks. 729 * 730 * @return {@code true} if it succeeds, {@code false} otherwise 731 */ 732 public boolean removeAllNetworks() { 733 return mSupplicantStaIfaceHal.removeAllNetworks(); 734 } 735 736 /** 737 * Set the BSSID for the currently configured network in wpa_supplicant. 738 * 739 * @return true if successful, false otherwise. 740 */ 741 public boolean setConfiguredNetworkBSSID(String bssid) { 742 return mSupplicantStaIfaceHal.setCurrentNetworkBssid(bssid); 743 } 744 745 /** 746 * Initiate ANQP query. 747 * 748 * @param bssid BSSID of the AP to be queried 749 * @param anqpIds Set of anqp IDs. 750 * @param hs20Subtypes Set of HS20 subtypes. 751 * @return true on success, false otherwise. 752 */ 753 public boolean requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes) { 754 if (bssid == null || ((anqpIds == null || anqpIds.isEmpty()) 755 && (hs20Subtypes == null || hs20Subtypes.isEmpty()))) { 756 Log.e(mTAG, "Invalid arguments for ANQP request."); 757 return false; 758 } 759 ArrayList<Short> anqpIdList = new ArrayList<>(); 760 for (Integer anqpId : anqpIds) { 761 anqpIdList.add(anqpId.shortValue()); 762 } 763 ArrayList<Integer> hs20SubtypeList = new ArrayList<>(); 764 hs20SubtypeList.addAll(hs20Subtypes); 765 return mSupplicantStaIfaceHal.initiateAnqpQuery(bssid, anqpIdList, hs20SubtypeList); 766 } 767 768 /** 769 * Request a passpoint icon file |filename| from the specified AP |bssid|. 770 * @param bssid BSSID of the AP 771 * @param fileName name of the icon file 772 * @return true if request is sent successfully, false otherwise 773 */ 774 public boolean requestIcon(String bssid, String fileName) { 775 if (bssid == null || fileName == null) { 776 Log.e(mTAG, "Invalid arguments for Icon request."); 777 return false; 778 } 779 return mSupplicantStaIfaceHal.initiateHs20IconQuery(bssid, fileName); 780 } 781 782 /** 783 * Get the currently configured network's WPS NFC token. 784 * 785 * @return Hex string corresponding to the WPS NFC token. 786 */ 787 public String getCurrentNetworkWpsNfcConfigurationToken() { 788 return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken(); 789 } 790 791 /** Remove the request |networkId| from supplicant if it's the current network, 792 * if the current configured network matches |networkId|. 793 * 794 * @param networkId network id of the network to be removed from supplicant. 795 */ 796 public void removeNetworkIfCurrent(int networkId) { 797 mSupplicantStaIfaceHal.removeNetworkIfCurrent(networkId); 798 } 799 800 /******************************************************** 801 * Vendor HAL operations 802 ********************************************************/ 803 /** 804 * Callback to notify vendor HAL death. 805 */ 806 public interface VendorHalDeathEventHandler { 807 /** 808 * Invoked when the vendor HAL dies. 809 */ 810 void onDeath(); 811 } 812 813 /** 814 * Initializes the vendor HAL. This is just used to initialize the {@link HalDeviceManager}. 815 */ 816 public boolean initializeVendorHal(VendorHalDeathEventHandler handler) { 817 return mWifiVendorHal.initialize(handler); 818 } 819 820 /** 821 * Bring up the Vendor HAL and configure for STA mode or AP mode, if vendor HAL is supported. 822 * 823 * @param isStaMode true to start HAL in STA mode, false to start in AP mode. 824 * @return false if the HAL start fails, true if successful or if vendor HAL not supported. 825 */ 826 private boolean startHalIfNecessary(boolean isStaMode) { 827 if (!mWifiVendorHal.isVendorHalSupported()) { 828 Log.i(mTAG, "Vendor HAL not supported, Ignore start..."); 829 return true; 830 } 831 return mWifiVendorHal.startVendorHal(isStaMode); 832 } 833 834 /** 835 * Stops the HAL, if vendor HAL is supported. 836 */ 837 private void stopHalIfNecessary() { 838 if (!mWifiVendorHal.isVendorHalSupported()) { 839 Log.i(mTAG, "Vendor HAL not supported, Ignore stop..."); 840 return; 841 } 842 mWifiVendorHal.stopVendorHal(); 843 } 844 845 /** 846 * Tests whether the HAL is running or not 847 */ 848 public boolean isHalStarted() { 849 return mWifiVendorHal.isHalStarted(); 850 } 851 852 // TODO: Change variable names to camel style. 853 public static class ScanCapabilities { 854 public int max_scan_cache_size; 855 public int max_scan_buckets; 856 public int max_ap_cache_per_scan; 857 public int max_rssi_sample_size; 858 public int max_scan_reporting_threshold; 859 } 860 861 /** 862 * Gets the scan capabilities 863 * 864 * @param capabilities object to be filled in 865 * @return true for success. false for failure 866 */ 867 public boolean getBgScanCapabilities(ScanCapabilities capabilities) { 868 return mWifiVendorHal.getBgScanCapabilities(capabilities); 869 } 870 871 public static class ChannelSettings { 872 public int frequency; 873 public int dwell_time_ms; 874 public boolean passive; 875 } 876 877 public static class BucketSettings { 878 public int bucket; 879 public int band; 880 public int period_ms; 881 public int max_period_ms; 882 public int step_count; 883 public int report_events; 884 public int num_channels; 885 public ChannelSettings[] channels; 886 } 887 888 /** 889 * Network parameters for hidden networks to be scanned for. 890 */ 891 public static class HiddenNetwork { 892 public String ssid; 893 894 @Override 895 public boolean equals(Object otherObj) { 896 if (this == otherObj) { 897 return true; 898 } else if (otherObj == null || getClass() != otherObj.getClass()) { 899 return false; 900 } 901 HiddenNetwork other = (HiddenNetwork) otherObj; 902 return Objects.equals(ssid, other.ssid); 903 } 904 905 @Override 906 public int hashCode() { 907 return (ssid == null ? 0 : ssid.hashCode()); 908 } 909 } 910 911 public static class ScanSettings { 912 public int base_period_ms; 913 public int max_ap_per_scan; 914 public int report_threshold_percent; 915 public int report_threshold_num_scans; 916 public int num_buckets; 917 /* Not used for bg scans. Only works for single scans. */ 918 public HiddenNetwork[] hiddenNetworks; 919 public BucketSettings[] buckets; 920 } 921 922 /** 923 * Network parameters to start PNO scan. 924 */ 925 public static class PnoNetwork { 926 public String ssid; 927 public byte flags; 928 public byte auth_bit_field; 929 930 @Override 931 public boolean equals(Object otherObj) { 932 if (this == otherObj) { 933 return true; 934 } else if (otherObj == null || getClass() != otherObj.getClass()) { 935 return false; 936 } 937 PnoNetwork other = (PnoNetwork) otherObj; 938 return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags) 939 && (auth_bit_field == other.auth_bit_field)); 940 } 941 942 @Override 943 public int hashCode() { 944 int result = (ssid == null ? 0 : ssid.hashCode()); 945 result ^= ((int) flags * 31) + ((int) auth_bit_field << 8); 946 return result; 947 } 948 } 949 950 /** 951 * Parameters to start PNO scan. This holds the list of networks which are going to used for 952 * PNO scan. 953 */ 954 public static class PnoSettings { 955 public int min5GHzRssi; 956 public int min24GHzRssi; 957 public int initialScoreMax; 958 public int currentConnectionBonus; 959 public int sameNetworkBonus; 960 public int secureBonus; 961 public int band5GHzBonus; 962 public int periodInMs; 963 public boolean isConnected; 964 public PnoNetwork[] networkList; 965 } 966 967 public static interface ScanEventHandler { 968 /** 969 * Called for each AP as it is found with the entire contents of the beacon/probe response. 970 * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified. 971 */ 972 void onFullScanResult(ScanResult fullScanResult, int bucketsScanned); 973 /** 974 * Callback on an event during a gscan scan. 975 * See WifiNative.WIFI_SCAN_* for possible values. 976 */ 977 void onScanStatus(int event); 978 /** 979 * Called with the current cached scan results when gscan is paused. 980 */ 981 void onScanPaused(WifiScanner.ScanData[] data); 982 /** 983 * Called with the current cached scan results when gscan is resumed. 984 */ 985 void onScanRestarted(); 986 } 987 988 /** 989 * Handler to notify the occurrence of various events during PNO scan. 990 */ 991 public interface PnoEventHandler { 992 /** 993 * Callback to notify when one of the shortlisted networks is found during PNO scan. 994 * @param results List of Scan results received. 995 */ 996 void onPnoNetworkFound(ScanResult[] results); 997 998 /** 999 * Callback to notify when the PNO scan schedule fails. 1000 */ 1001 void onPnoScanFailed(); 1002 } 1003 1004 public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0; 1005 public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1; 1006 public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2; 1007 public static final int WIFI_SCAN_FAILED = 3; 1008 1009 /** 1010 * Starts a background scan. 1011 * Any ongoing scan will be stopped first 1012 * 1013 * @param settings to control the scan 1014 * @param eventHandler to call with the results 1015 * @return true for success 1016 */ 1017 public boolean startBgScan(ScanSettings settings, ScanEventHandler eventHandler) { 1018 return mWifiVendorHal.startBgScan(settings, eventHandler); 1019 } 1020 1021 /** 1022 * Stops any ongoing backgound scan 1023 */ 1024 public void stopBgScan() { 1025 mWifiVendorHal.stopBgScan(); 1026 } 1027 1028 /** 1029 * Pauses an ongoing backgound scan 1030 */ 1031 public void pauseBgScan() { 1032 mWifiVendorHal.pauseBgScan(); 1033 } 1034 1035 /** 1036 * Restarts a paused scan 1037 */ 1038 public void restartBgScan() { 1039 mWifiVendorHal.restartBgScan(); 1040 } 1041 1042 /** 1043 * Gets the latest scan results received. 1044 */ 1045 public WifiScanner.ScanData[] getBgScanResults() { 1046 return mWifiVendorHal.getBgScanResults(); 1047 } 1048 1049 public WifiLinkLayerStats getWifiLinkLayerStats(String iface) { 1050 return mWifiVendorHal.getWifiLinkLayerStats(); 1051 } 1052 1053 /** 1054 * Get the supported features 1055 * 1056 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 1057 */ 1058 public int getSupportedFeatureSet() { 1059 return mWifiVendorHal.getSupportedFeatureSet(); 1060 } 1061 1062 public static interface RttEventHandler { 1063 void onRttResults(RttManager.RttResult[] result); 1064 } 1065 1066 /** 1067 * Starts a new rtt request 1068 * 1069 * @param params RTT request params. Refer to {@link RttManager#RttParams}. 1070 * @param handler Callback to be invoked to notify any results. 1071 * @return true if the request was successful, false otherwise. 1072 */ 1073 public boolean requestRtt( 1074 RttManager.RttParams[] params, RttEventHandler handler) { 1075 return mWifiVendorHal.requestRtt(params, handler); 1076 } 1077 1078 /** 1079 * Cancels an outstanding rtt request 1080 * 1081 * @param params RTT request params. Refer to {@link RttManager#RttParams} 1082 * @return true if there was an outstanding request and it was successfully cancelled 1083 */ 1084 public boolean cancelRtt(RttManager.RttParams[] params) { 1085 return mWifiVendorHal.cancelRtt(params); 1086 } 1087 1088 /** 1089 * Enable RTT responder role on the device. Returns {@link ResponderConfig} if the responder 1090 * role is successfully enabled, {@code null} otherwise. 1091 * 1092 * @param timeoutSeconds timeout to use for the responder. 1093 */ 1094 @Nullable 1095 public ResponderConfig enableRttResponder(int timeoutSeconds) { 1096 return mWifiVendorHal.enableRttResponder(timeoutSeconds); 1097 } 1098 1099 /** 1100 * Disable RTT responder role. Returns {@code true} if responder role is successfully disabled, 1101 * {@code false} otherwise. 1102 */ 1103 public boolean disableRttResponder() { 1104 return mWifiVendorHal.disableRttResponder(); 1105 } 1106 1107 /** 1108 * Set the MAC OUI during scanning. 1109 * An OUI {Organizationally Unique Identifier} is a 24-bit number that 1110 * uniquely identifies a vendor or manufacturer. 1111 * 1112 * @param oui OUI to set. 1113 * @return true for success 1114 */ 1115 public boolean setScanningMacOui(byte[] oui) { 1116 return mWifiVendorHal.setScanningMacOui(oui); 1117 } 1118 1119 /** 1120 * Query the list of valid frequencies for the provided band. 1121 * The result depends on the on the country code that has been set. 1122 * 1123 * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants. 1124 * @return frequencies vector of valid frequencies (MHz), or null for error. 1125 * @throws IllegalArgumentException if band is not recognized. 1126 */ 1127 public int [] getChannelsForBand(int band) { 1128 return mWifiVendorHal.getChannelsForBand(band); 1129 } 1130 1131 /** 1132 * Indicates whether getChannelsForBand is supported. 1133 * 1134 * @return true if it is. 1135 */ 1136 public boolean isGetChannelsForBandSupported() { 1137 return mWifiVendorHal.isGetChannelsForBandSupported(); 1138 } 1139 1140 /** 1141 * RTT (Round Trip Time) measurement capabilities of the device. 1142 */ 1143 public RttManager.RttCapabilities getRttCapabilities() { 1144 return mWifiVendorHal.getRttCapabilities(); 1145 } 1146 1147 /** 1148 * Get the APF (Android Packet Filter) capabilities of the device 1149 */ 1150 public ApfCapabilities getApfCapabilities() { 1151 return mWifiVendorHal.getApfCapabilities(); 1152 } 1153 1154 /** 1155 * Installs an APF program on this iface, replacing any existing program. 1156 * 1157 * @param filter is the android packet filter program 1158 * @return true for success 1159 */ 1160 public boolean installPacketFilter(byte[] filter) { 1161 return mWifiVendorHal.installPacketFilter(filter); 1162 } 1163 1164 /** 1165 * Set country code for this AP iface. 1166 * 1167 * @param countryCode - two-letter country code (as ISO 3166) 1168 * @return true for success 1169 */ 1170 public boolean setCountryCodeHal(String countryCode) { 1171 return mWifiVendorHal.setCountryCodeHal(countryCode); 1172 } 1173 1174 //--------------------------------------------------------------------------------- 1175 /* Wifi Logger commands/events */ 1176 public static interface WifiLoggerEventHandler { 1177 void onRingBufferData(RingBufferStatus status, byte[] buffer); 1178 void onWifiAlert(int errorCode, byte[] buffer); 1179 } 1180 1181 /** 1182 * Registers the logger callback and enables alerts. 1183 * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked. 1184 * 1185 * @param handler Callback to be invoked. 1186 * @return true on success, false otherwise. 1187 */ 1188 public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) { 1189 return mWifiVendorHal.setLoggingEventHandler(handler); 1190 } 1191 1192 /** 1193 * Control debug data collection 1194 * 1195 * @param verboseLevel 0 to 3, inclusive. 0 stops logging. 1196 * @param flags Ignored. 1197 * @param maxInterval Maximum interval between reports; ignore if 0. 1198 * @param minDataSize Minimum data size in buffer for report; ignore if 0. 1199 * @param ringName Name of the ring for which data collection is to start. 1200 * @return true for success, false otherwise. 1201 */ 1202 public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, 1203 int minDataSize, String ringName){ 1204 return mWifiVendorHal.startLoggingRingBuffer( 1205 verboseLevel, flags, maxInterval, minDataSize, ringName); 1206 } 1207 1208 /** 1209 * Logger features exposed. 1210 * This is a no-op now, will always return -1. 1211 * 1212 * @return true on success, false otherwise. 1213 */ 1214 public int getSupportedLoggerFeatureSet() { 1215 return mWifiVendorHal.getSupportedLoggerFeatureSet(); 1216 } 1217 1218 /** 1219 * Stops all logging and resets the logger callback. 1220 * This stops both the alerts and ring buffer data collection. 1221 * @return true on success, false otherwise. 1222 */ 1223 public boolean resetLogHandler() { 1224 return mWifiVendorHal.resetLogHandler(); 1225 } 1226 1227 /** 1228 * Vendor-provided wifi driver version string 1229 * 1230 * @return String returned from the HAL. 1231 */ 1232 public String getDriverVersion() { 1233 return mWifiVendorHal.getDriverVersion(); 1234 } 1235 1236 /** 1237 * Vendor-provided wifi firmware version string 1238 * 1239 * @return String returned from the HAL. 1240 */ 1241 public String getFirmwareVersion() { 1242 return mWifiVendorHal.getFirmwareVersion(); 1243 } 1244 1245 public static class RingBufferStatus{ 1246 String name; 1247 int flag; 1248 int ringBufferId; 1249 int ringBufferByteSize; 1250 int verboseLevel; 1251 int writtenBytes; 1252 int readBytes; 1253 int writtenRecords; 1254 1255 // Bit masks for interpreting |flag| 1256 public static final int HAS_BINARY_ENTRIES = (1 << 0); 1257 public static final int HAS_ASCII_ENTRIES = (1 << 1); 1258 public static final int HAS_PER_PACKET_ENTRIES = (1 << 2); 1259 1260 @Override 1261 public String toString() { 1262 return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId + 1263 " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel + 1264 " writtenBytes: " + writtenBytes + " readBytes: " + readBytes + 1265 " writtenRecords: " + writtenRecords; 1266 } 1267 } 1268 1269 /** 1270 * API to get the status of all ring buffers supported by driver 1271 */ 1272 public RingBufferStatus[] getRingBufferStatus() { 1273 return mWifiVendorHal.getRingBufferStatus(); 1274 } 1275 1276 /** 1277 * Indicates to driver that all the data has to be uploaded urgently 1278 * 1279 * @param ringName Name of the ring buffer requested. 1280 * @return true on success, false otherwise. 1281 */ 1282 public boolean getRingBufferData(String ringName) { 1283 return mWifiVendorHal.getRingBufferData(ringName); 1284 } 1285 1286 /** 1287 * Request vendor debug info from the firmware 1288 * 1289 * @return Raw data obtained from the HAL. 1290 */ 1291 public byte[] getFwMemoryDump() { 1292 return mWifiVendorHal.getFwMemoryDump(); 1293 } 1294 1295 /** 1296 * Request vendor debug info from the driver 1297 * 1298 * @return Raw data obtained from the HAL. 1299 */ 1300 public byte[] getDriverStateDump() { 1301 return mWifiVendorHal.getDriverStateDump(); 1302 } 1303 1304 //--------------------------------------------------------------------------------- 1305 /* Packet fate API */ 1306 1307 @Immutable 1308 abstract static class FateReport { 1309 final static int USEC_PER_MSEC = 1000; 1310 // The driver timestamp is a 32-bit counter, in microseconds. This field holds the 1311 // maximal value of a driver timestamp in milliseconds. 1312 final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000); 1313 final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS"); 1314 1315 final byte mFate; 1316 final long mDriverTimestampUSec; 1317 final byte mFrameType; 1318 final byte[] mFrameBytes; 1319 final long mEstimatedWallclockMSec; 1320 1321 FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 1322 mFate = fate; 1323 mDriverTimestampUSec = driverTimestampUSec; 1324 mEstimatedWallclockMSec = 1325 convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec); 1326 mFrameType = frameType; 1327 mFrameBytes = frameBytes; 1328 } 1329 1330 public String toTableRowString() { 1331 StringWriter sw = new StringWriter(); 1332 PrintWriter pw = new PrintWriter(sw); 1333 FrameParser parser = new FrameParser(mFrameType, mFrameBytes); 1334 dateFormatter.setTimeZone(TimeZone.getDefault()); 1335 pw.format("%-15s %12s %-9s %-32s %-12s %-23s %s\n", 1336 mDriverTimestampUSec, 1337 dateFormatter.format(new Date(mEstimatedWallclockMSec)), 1338 directionToString(), fateToString(), parser.mMostSpecificProtocolString, 1339 parser.mTypeString, parser.mResultString); 1340 return sw.toString(); 1341 } 1342 1343 public String toVerboseStringWithPiiAllowed() { 1344 StringWriter sw = new StringWriter(); 1345 PrintWriter pw = new PrintWriter(sw); 1346 FrameParser parser = new FrameParser(mFrameType, mFrameBytes); 1347 pw.format("Frame direction: %s\n", directionToString()); 1348 pw.format("Frame timestamp: %d\n", mDriverTimestampUSec); 1349 pw.format("Frame fate: %s\n", fateToString()); 1350 pw.format("Frame type: %s\n", frameTypeToString(mFrameType)); 1351 pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString); 1352 pw.format("Frame protocol type: %s\n", parser.mTypeString); 1353 pw.format("Frame length: %d\n", mFrameBytes.length); 1354 pw.append("Frame bytes"); 1355 pw.append(HexDump.dumpHexString(mFrameBytes)); // potentially contains PII 1356 pw.append("\n"); 1357 return sw.toString(); 1358 } 1359 1360 /* Returns a header to match the output of toTableRowString(). */ 1361 public static String getTableHeader() { 1362 StringWriter sw = new StringWriter(); 1363 PrintWriter pw = new PrintWriter(sw); 1364 pw.format("\n%-15s %-12s %-9s %-32s %-12s %-23s %s\n", 1365 "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result"); 1366 pw.format("%-15s %-12s %-9s %-32s %-12s %-23s %s\n", 1367 "---------", "--------", "---------", "----", "--------", "----", "------"); 1368 return sw.toString(); 1369 } 1370 1371 protected abstract String directionToString(); 1372 1373 protected abstract String fateToString(); 1374 1375 private static String frameTypeToString(byte frameType) { 1376 switch (frameType) { 1377 case WifiLoggerHal.FRAME_TYPE_UNKNOWN: 1378 return "unknown"; 1379 case WifiLoggerHal.FRAME_TYPE_ETHERNET_II: 1380 return "data"; 1381 case WifiLoggerHal.FRAME_TYPE_80211_MGMT: 1382 return "802.11 management"; 1383 default: 1384 return Byte.toString(frameType); 1385 } 1386 } 1387 1388 /** 1389 * Converts a driver timestamp to a wallclock time, based on the current 1390 * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of 1391 * microseconds, with the same base as BOOTTIME. 1392 */ 1393 private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) { 1394 final long wallclockMillisNow = System.currentTimeMillis(); 1395 final long boottimeMillisNow = SystemClock.elapsedRealtime(); 1396 final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC; 1397 1398 long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC; 1399 if (boottimeTimestampMillis < driverTimestampMillis) { 1400 // The 32-bit microsecond count has wrapped between the time that the driver 1401 // recorded the packet, and the call to this function. Adjust the BOOTTIME 1402 // timestamp, to compensate. 1403 // 1404 // Note that overflow is not a concern here, since the result is less than 1405 // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above, 1406 // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since 1407 // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit 1408 // within a long. 1409 boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC; 1410 } 1411 1412 final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis; 1413 return wallclockMillisNow - millisSincePacketTimestamp; 1414 } 1415 } 1416 1417 /** 1418 * Represents the fate information for one outbound packet. 1419 */ 1420 @Immutable 1421 public static final class TxFateReport extends FateReport { 1422 TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 1423 super(fate, driverTimestampUSec, frameType, frameBytes); 1424 } 1425 1426 @Override 1427 protected String directionToString() { 1428 return "TX"; 1429 } 1430 1431 @Override 1432 protected String fateToString() { 1433 switch (mFate) { 1434 case WifiLoggerHal.TX_PKT_FATE_ACKED: 1435 return "acked"; 1436 case WifiLoggerHal.TX_PKT_FATE_SENT: 1437 return "sent"; 1438 case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED: 1439 return "firmware queued"; 1440 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID: 1441 return "firmware dropped (invalid frame)"; 1442 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS: 1443 return "firmware dropped (no bufs)"; 1444 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER: 1445 return "firmware dropped (other)"; 1446 case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED: 1447 return "driver queued"; 1448 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID: 1449 return "driver dropped (invalid frame)"; 1450 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS: 1451 return "driver dropped (no bufs)"; 1452 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER: 1453 return "driver dropped (other)"; 1454 default: 1455 return Byte.toString(mFate); 1456 } 1457 } 1458 } 1459 1460 /** 1461 * Represents the fate information for one inbound packet. 1462 */ 1463 @Immutable 1464 public static final class RxFateReport extends FateReport { 1465 RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 1466 super(fate, driverTimestampUSec, frameType, frameBytes); 1467 } 1468 1469 @Override 1470 protected String directionToString() { 1471 return "RX"; 1472 } 1473 1474 @Override 1475 protected String fateToString() { 1476 switch (mFate) { 1477 case WifiLoggerHal.RX_PKT_FATE_SUCCESS: 1478 return "success"; 1479 case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED: 1480 return "firmware queued"; 1481 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER: 1482 return "firmware dropped (filter)"; 1483 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID: 1484 return "firmware dropped (invalid frame)"; 1485 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS: 1486 return "firmware dropped (no bufs)"; 1487 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER: 1488 return "firmware dropped (other)"; 1489 case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED: 1490 return "driver queued"; 1491 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER: 1492 return "driver dropped (filter)"; 1493 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID: 1494 return "driver dropped (invalid frame)"; 1495 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS: 1496 return "driver dropped (no bufs)"; 1497 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER: 1498 return "driver dropped (other)"; 1499 default: 1500 return Byte.toString(mFate); 1501 } 1502 } 1503 } 1504 1505 /** 1506 * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started. 1507 * 1508 * @return true for success, false otherwise. 1509 */ 1510 public boolean startPktFateMonitoring() { 1511 return mWifiVendorHal.startPktFateMonitoring(); 1512 } 1513 1514 /** 1515 * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started. 1516 * 1517 * @return true for success, false otherwise. 1518 */ 1519 public boolean getTxPktFates(TxFateReport[] reportBufs) { 1520 return mWifiVendorHal.getTxPktFates(reportBufs); 1521 } 1522 1523 /** 1524 * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started. 1525 */ 1526 public boolean getRxPktFates(RxFateReport[] reportBufs) { 1527 return mWifiVendorHal.getRxPktFates(reportBufs); 1528 } 1529 1530 /** 1531 * Set the PNO settings & the network list in HAL to start PNO. 1532 * @param settings PNO settings and network list. 1533 * @param eventHandler Handler to receive notifications back during PNO scan. 1534 * @return true if success, false otherwise 1535 */ 1536 public boolean setPnoList(PnoSettings settings, PnoEventHandler eventHandler) { 1537 Log.e(mTAG, "setPnoList not supported"); 1538 return false; 1539 } 1540 1541 /** 1542 * Reset the PNO settings in HAL to stop PNO. 1543 * @return true if success, false otherwise 1544 */ 1545 public boolean resetPnoList() { 1546 Log.e(mTAG, "resetPnoList not supported"); 1547 return false; 1548 } 1549 1550 /** 1551 * Start sending the specified keep alive packets periodically. 1552 * 1553 * @param slot Integer used to identify each request. 1554 * @param keepAlivePacket Raw packet contents to send. 1555 * @param period Period to use for sending these packets. 1556 * @return 0 for success, -1 for error 1557 */ 1558 public int startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket, 1559 int period) { 1560 String[] macAddrStr = getMacAddress().split(":"); 1561 byte[] srcMac = new byte[6]; 1562 for (int i = 0; i < 6; i++) { 1563 Integer hexVal = Integer.parseInt(macAddrStr[i], 16); 1564 srcMac[i] = hexVal.byteValue(); 1565 } 1566 return mWifiVendorHal.startSendingOffloadedPacket( 1567 slot, srcMac, keepAlivePacket, period); 1568 } 1569 1570 /** 1571 * Stop sending the specified keep alive packets. 1572 * 1573 * @param slot id - same as startSendingOffloadedPacket call. 1574 * @return 0 for success, -1 for error 1575 */ 1576 public int stopSendingOffloadedPacket(int slot) { 1577 return mWifiVendorHal.stopSendingOffloadedPacket(slot); 1578 } 1579 1580 public static interface WifiRssiEventHandler { 1581 void onRssiThresholdBreached(byte curRssi); 1582 } 1583 1584 /** 1585 * Start RSSI monitoring on the currently connected access point. 1586 * 1587 * @param maxRssi Maximum RSSI threshold. 1588 * @param minRssi Minimum RSSI threshold. 1589 * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi 1590 * @return 0 for success, -1 for failure 1591 */ 1592 public int startRssiMonitoring(byte maxRssi, byte minRssi, 1593 WifiRssiEventHandler rssiEventHandler) { 1594 return mWifiVendorHal.startRssiMonitoring(maxRssi, minRssi, rssiEventHandler); 1595 } 1596 1597 public int stopRssiMonitoring() { 1598 return mWifiVendorHal.stopRssiMonitoring(); 1599 } 1600 1601 /** 1602 * Fetch the host wakeup reasons stats from wlan driver. 1603 * 1604 * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver. 1605 */ 1606 public WifiWakeReasonAndCounts getWlanWakeReasonCount() { 1607 return mWifiVendorHal.getWlanWakeReasonCount(); 1608 } 1609 1610 /** 1611 * Enable/Disable Neighbour discovery offload functionality in the firmware. 1612 * 1613 * @param enabled true to enable, false to disable. 1614 * @return true for success, false otherwise. 1615 */ 1616 public boolean configureNeighborDiscoveryOffload(boolean enabled) { 1617 return mWifiVendorHal.configureNeighborDiscoveryOffload(enabled); 1618 } 1619 1620 // Firmware roaming control. 1621 1622 /** 1623 * Class to retrieve firmware roaming capability parameters. 1624 */ 1625 public static class RoamingCapabilities { 1626 public int maxBlacklistSize; 1627 public int maxWhitelistSize; 1628 } 1629 1630 /** 1631 * Query the firmware roaming capabilities. 1632 * @return true for success, false otherwise. 1633 */ 1634 public boolean getRoamingCapabilities(RoamingCapabilities capabilities) { 1635 return mWifiVendorHal.getRoamingCapabilities(capabilities); 1636 } 1637 1638 /** 1639 * Macros for controlling firmware roaming. 1640 */ 1641 public static final int DISABLE_FIRMWARE_ROAMING = 0; 1642 public static final int ENABLE_FIRMWARE_ROAMING = 1; 1643 1644 /** 1645 * Enable/disable firmware roaming. 1646 * 1647 * @return error code returned from HAL. 1648 */ 1649 public int enableFirmwareRoaming(int state) { 1650 return mWifiVendorHal.enableFirmwareRoaming(state); 1651 } 1652 1653 /** 1654 * Class for specifying the roaming configurations. 1655 */ 1656 public static class RoamingConfig { 1657 public ArrayList<String> blacklistBssids; 1658 public ArrayList<String> whitelistSsids; 1659 } 1660 1661 /** 1662 * Set firmware roaming configurations. 1663 */ 1664 public boolean configureRoaming(RoamingConfig config) { 1665 Log.d(mTAG, "configureRoaming "); 1666 return mWifiVendorHal.configureRoaming(config); 1667 } 1668 1669 /** 1670 * Reset firmware roaming configuration. 1671 */ 1672 public boolean resetRoamingConfiguration() { 1673 // Pass in an empty RoamingConfig object which translates to zero size 1674 // blacklist and whitelist to reset the firmware roaming configuration. 1675 return mWifiVendorHal.configureRoaming(new RoamingConfig()); 1676 } 1677 1678 /******************************************************** 1679 * JNI operations 1680 ********************************************************/ 1681 /* Register native functions */ 1682 static { 1683 /* Native functions are defined in libwifi-service.so */ 1684 System.loadLibrary("wifi-service"); 1685 registerNatives(); 1686 } 1687 1688 private static native int registerNatives(); 1689 /* kernel logging support */ 1690 private static native byte[] readKernelLogNative(); 1691 1692 /** 1693 * Fetches the latest kernel logs. 1694 */ 1695 public synchronized String readKernelLog() { 1696 byte[] bytes = readKernelLogNative(); 1697 if (bytes != null) { 1698 CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder(); 1699 try { 1700 CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes)); 1701 return decoded.toString(); 1702 } catch (CharacterCodingException cce) { 1703 return new String(bytes, StandardCharsets.ISO_8859_1); 1704 } 1705 } else { 1706 return "*** failed to read kernel log ***"; 1707 } 1708 } 1709 } 1710