WifiVendorHal.java revision ccac1c69ee6559b567e34b9b19e368efaa600174
1/* 2 * Copyright (C) 2017 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 */ 16package com.android.server.wifi; 17 18import android.annotation.Nullable; 19import android.hardware.wifi.V1_0.IWifiApIface; 20import android.hardware.wifi.V1_0.IWifiChip; 21import android.hardware.wifi.V1_0.IWifiIface; 22import android.hardware.wifi.V1_0.IWifiRttController; 23import android.hardware.wifi.V1_0.IWifiStaIface; 24import android.hardware.wifi.V1_0.StaRoamingConfig; 25import android.hardware.wifi.V1_0.StaRoamingState; 26import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats; 27import android.hardware.wifi.V1_0.WifiStatus; 28import android.hardware.wifi.V1_0.WifiStatusCode; 29import android.net.apf.ApfCapabilities; 30import android.net.wifi.RttManager; 31import android.net.wifi.RttManager.ResponderConfig; 32import android.net.wifi.WifiInfo; 33import android.net.wifi.WifiLinkLayerStats; 34import android.net.wifi.WifiManager; 35import android.net.wifi.WifiScanner; 36import android.net.wifi.WifiWakeReasonAndCounts; 37import android.os.HandlerThread; 38import android.os.RemoteException; 39import android.util.Log; 40import android.util.MutableBoolean; 41import android.util.MutableInt; 42 43import com.android.internal.annotations.VisibleForTesting; 44import com.android.server.connectivity.KeepalivePacketData; 45 46import java.util.ArrayList; 47 48/** 49 * Vendor HAL via HIDL 50 */ 51public class WifiVendorHal { 52 53 private static final String TAG = "WifiVendorHal"; 54 55 // Vendor HAL HIDL interface objects. 56 private IWifiChip mIWifiChip; 57 private IWifiStaIface mIWifiStaIface; 58 private IWifiApIface mIWifiApIface; 59 private IWifiRttController mIWifiRttController; 60 private final HalDeviceManager mHalDeviceManager; 61 private final HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks; 62 private final HandlerThread mWifiStateMachineHandlerThread; 63 64 public WifiVendorHal(HalDeviceManager halDeviceManager, 65 HandlerThread wifiStateMachineHandlerThread) { 66 mHalDeviceManager = halDeviceManager; 67 mWifiStateMachineHandlerThread = wifiStateMachineHandlerThread; 68 mHalDeviceManagerStatusCallbacks = new HalDeviceManagerStatusListener(); 69 } 70 71 // TODO(mplass): figure out where we need locking in hidl world. b/33383725 72 public static final Object sLock = new Object(); 73 74 private void handleRemoteException(RemoteException e) { 75 kilroy(); 76 Log.e(TAG, "RemoteException in HIDL call " + e); 77 } 78 79 private void noteHidlError(WifiStatus status, String culprit) { 80 kilroy(); 81 Log.e(TAG, "Error in " + culprit + " code: " + status.code 82 + " (" + status.description + ")"); 83 } 84 85 /** 86 * Initialize the Hal device manager and register for status callbacks. 87 * @return 88 */ 89 public boolean initialize() { 90 mHalDeviceManager.initialize(); 91 mHalDeviceManager.registerStatusListener( 92 mHalDeviceManagerStatusCallbacks, mWifiStateMachineHandlerThread.getLooper()); 93 return true; 94 } 95 96 /** 97 * Bring up the HIDL Vendor HAL and configure for AP (Access Point) mode 98 * @return true for success 99 */ 100 public boolean startVendorHalAp() { 101 return startVendorHal(AP_MODE); 102 } 103 104 /** 105 * Bring up the HIDL Vendor HAL and configure for STA (Station) mode 106 * @return true for success 107 */ 108 public boolean startVendorHalSta() { 109 return startVendorHal(STA_MODE); 110 } 111 112 113 public static final boolean STA_MODE = true; 114 public static final boolean AP_MODE = false; 115 116 /** 117 * Bring up the HIDL Vendor HAL and configure for STA mode or AP mode. 118 * 119 * @param isStaMode true to start HAL in STA mode, false to start in AP mode. 120 */ 121 public boolean startVendorHal(boolean isStaMode) { 122 if (!mHalDeviceManager.start()) { 123 Log.e(TAG, "Failed to start the vendor HAL"); 124 return false; 125 } 126 IWifiIface iface; 127 if (isStaMode) { 128 mIWifiStaIface = mHalDeviceManager.createStaIface(null, null); 129 if (mIWifiStaIface == null) { 130 Log.e(TAG, "Failed to create STA Iface. Vendor Hal start failed"); 131 mHalDeviceManager.stop(); 132 return false; 133 } 134 iface = (IWifiIface) mIWifiStaIface; 135 mIWifiRttController = mHalDeviceManager.createRttController(iface); 136 if (mIWifiRttController == null) { 137 Log.e(TAG, "Failed to create RTT controller. Vendor Hal start failed"); 138 stopVendorHal(); 139 return false; 140 } 141 enableLinkLayerStats(); 142 } else { 143 mIWifiApIface = mHalDeviceManager.createApIface(null, null); 144 if (mIWifiApIface == null) { 145 Log.e(TAG, "Failed to create AP Iface. Vendor Hal start failed"); 146 stopVendorHal(); 147 return false; 148 } 149 iface = (IWifiIface) mIWifiApIface; 150 } 151 mIWifiChip = mHalDeviceManager.getChip(iface); 152 if (mIWifiChip == null) { 153 Log.e(TAG, "Failed to get the chip created for the Iface. Vendor Hal start failed"); 154 stopVendorHal(); 155 return false; 156 } 157 Log.i(TAG, "Vendor Hal started successfully"); 158 return true; 159 } 160 161 /** 162 * Stops the HAL 163 */ 164 public void stopVendorHal() { 165 mHalDeviceManager.stop(); 166 Log.i(TAG, "Vendor Hal stopped"); 167 } 168 169 /** 170 * Tests whether the HAL is running or not 171 */ 172 public boolean isHalStarted() { 173 return (mIWifiStaIface != null || mIWifiApIface != null); 174 } 175 176 /** 177 * Gets the scan capabilities 178 * 179 * @param capabilities object to be filled in 180 * @return true for success. false for failure 181 */ 182 public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) { 183 kilroy(); 184 throw new UnsupportedOperationException(); 185 } 186 187 /** 188 * to be implemented 189 */ 190 public boolean startScan(WifiNative.ScanSettings settings, 191 WifiNative.ScanEventHandler eventHandler) { 192 kilroy(); 193 throw new UnsupportedOperationException(); 194 } 195 196 /** 197 * to be implemented 198 */ 199 public void stopScan() { 200 kilroy(); 201 throw new UnsupportedOperationException(); 202 } 203 204 /** 205 * to be implemented 206 */ 207 public void pauseScan() { 208 kilroy(); 209 throw new UnsupportedOperationException(); 210 } 211 212 /** 213 * to be implemented 214 */ 215 public void restartScan() { 216 kilroy(); 217 throw new UnsupportedOperationException(); 218 } 219 220 /** 221 * to be implemented 222 */ 223 public WifiScanner.ScanData[] getScanResults(boolean flush) { 224 kilroy(); 225 throw new UnsupportedOperationException(); 226 } 227 228 /** 229 * Get the link layer statistics 230 * 231 * Note - we always enable link layer stats on a STA interface. 232 * 233 * @return the statistics, or null if unable to do so 234 */ 235 public WifiLinkLayerStats getWifiLinkLayerStats() { 236 kilroy(); 237 synchronized (sLock) { 238 try { 239 if (mIWifiStaIface == null) return null; 240 kilroy(); 241 WifiLinkLayerStats out = new WifiLinkLayerStats(); 242 MutableBoolean ok = new MutableBoolean(false); 243 kilroy(); 244 mIWifiStaIface.getLinkLayerStats((status, stats) -> { 245 kilroy(); 246 if (status.code != WifiStatusCode.SUCCESS) return; 247 out.status = 0; // TODO 248 out.SSID = null; // TODO 249 out.BSSID = null; // TODO 250 out.beacon_rx = stats.iface.beaconRx; 251 out.rssi_mgmt = stats.iface.avgRssiMgmt; 252 /* WME Best Effort Access Category */ 253 out.rxmpdu_be = stats.iface.wmeBePktStats.rxMpdu; 254 out.txmpdu_be = stats.iface.wmeBePktStats.txMpdu; 255 out.lostmpdu_be = stats.iface.wmeBePktStats.lostMpdu; 256 out.retries_be = stats.iface.wmeBePktStats.retries; 257 /* WME Background Access Category */ 258 out.rxmpdu_bk = stats.iface.wmeBkPktStats.rxMpdu; 259 out.txmpdu_bk = stats.iface.wmeBkPktStats.txMpdu; 260 out.lostmpdu_bk = stats.iface.wmeBkPktStats.lostMpdu; 261 out.retries_bk = stats.iface.wmeBkPktStats.retries; 262 /* WME Video Access Category */ 263 out.rxmpdu_vi = stats.iface.wmeViPktStats.rxMpdu; 264 out.txmpdu_vi = stats.iface.wmeViPktStats.txMpdu; 265 out.lostmpdu_vi = stats.iface.wmeViPktStats.lostMpdu; 266 out.retries_vi = stats.iface.wmeViPktStats.retries; 267 /* WME Voice Access Category */ 268 out.rxmpdu_vo = stats.iface.wmeVoPktStats.rxMpdu; 269 out.txmpdu_vo = stats.iface.wmeVoPktStats.txMpdu; 270 out.lostmpdu_vo = stats.iface.wmeVoPktStats.lostMpdu; 271 out.retries_vo = stats.iface.wmeVoPktStats.retries; 272 out.on_time = stats.radio.onTimeInMs; 273 out.tx_time = stats.radio.txTimeInMs; 274 out.tx_time_per_level = new int[stats.radio.txTimeInMsPerLevel.size()]; 275 for (int i = 0; i < out.tx_time_per_level.length; i++) { 276 out.tx_time_per_level[i] = stats.radio.txTimeInMsPerLevel.get(i); 277 } 278 out.rx_time = stats.radio.rxTimeInMs; 279 out.on_time_scan = stats.radio.onTimeInMsForScan; 280 kilroy(); 281 ok.value = true; 282 } 283 ); 284 return ok.value ? out : null; 285 } catch (RemoteException e) { 286 kilroy(); 287 handleRemoteException(e); 288 return null; 289 } 290 } 291 } 292 293 @VisibleForTesting 294 boolean mLinkLayerStatsDebug = false; // Passed to Hal 295 296 /** 297 * Enables the linkLayerStats in the Hal. 298 * 299 * This is called unconditionally whenever we create a STA interface. 300 * 301 */ 302 private void enableLinkLayerStats() { 303 synchronized (sLock) { 304 try { 305 kilroy(); 306 WifiStatus status; 307 status = mIWifiStaIface.enableLinkLayerStatsCollection(mLinkLayerStatsDebug); 308 if (status.code != WifiStatusCode.SUCCESS) { 309 kilroy(); 310 Log.e(TAG, "unable to enable link layer stats collection"); 311 } 312 } catch (RemoteException e) { 313 kilroy(); 314 handleRemoteException(e); 315 } 316 } 317 } 318 319 /** 320 * Translation table used by getSupportedFeatureSet for translating IWifiStaIface caps 321 */ 322 private static final int[][] sFeatureCapabilityTranslation = { 323 {WifiManager.WIFI_FEATURE_INFRA_5G, 324 IWifiStaIface.StaIfaceCapabilityMask.STA_5G 325 }, 326 {WifiManager.WIFI_FEATURE_PASSPOINT, 327 IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT 328 }, 329 {WifiManager.WIFI_FEATURE_SCANNER, 330 IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN, 331 }, 332 {WifiManager.WIFI_FEATURE_PNO, 333 IWifiStaIface.StaIfaceCapabilityMask.PNO 334 }, 335 {WifiManager.WIFI_FEATURE_TDLS, 336 IWifiStaIface.StaIfaceCapabilityMask.TDLS 337 }, 338 {WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL, 339 IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL 340 }, 341 {WifiManager.WIFI_FEATURE_LINK_LAYER_STATS, 342 IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS 343 }, 344 {WifiManager.WIFI_FEATURE_RSSI_MONITOR, 345 IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR 346 }, 347 {WifiManager.WIFI_FEATURE_MKEEP_ALIVE, 348 IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE 349 }, 350 {WifiManager.WIFI_FEATURE_CONFIG_NDO, 351 IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD 352 }, 353 {WifiManager.WIFI_FEATURE_CONTROL_ROAMING, 354 IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING 355 }, 356 {WifiManager.WIFI_FEATURE_IE_WHITELIST, 357 IWifiStaIface.StaIfaceCapabilityMask.PROBE_IE_WHITELIST 358 }, 359 {WifiManager.WIFI_FEATURE_SCAN_RAND, 360 IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND 361 }, 362 }; 363 364 /** 365 * Feature bit mask translation for STAs 366 * 367 * @param capabilities bitmask defined IWifiStaIface.StaIfaceCapabilityMask 368 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 369 */ 370 @VisibleForTesting 371 int wifiFeatureMaskFromStaCapabilities(int capabilities) { 372 int features = WifiManager.WIFI_FEATURE_INFRA; // Always set this if we have a STA interface 373 for (int i = 0; i < sFeatureCapabilityTranslation.length; i++) { 374 if ((capabilities & sFeatureCapabilityTranslation[i][1]) != 0) { 375 features |= sFeatureCapabilityTranslation[i][0]; 376 } 377 } 378 return features; 379 } 380 381 /** 382 * Get the supported features 383 * <p> 384 * Note that not all the WifiManager.WIFI_FEATURE_* bits are supplied through 385 * this call. //TODO(b/34900537) fix this 386 * 387 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 388 */ 389 public int getSupportedFeatureSet() { 390 try { 391 final MutableInt feat = new MutableInt(0); 392 synchronized (sLock) { 393 if (mIWifiStaIface != null) { 394 mIWifiStaIface.getCapabilities((status, capabilities) -> { 395 if (status.code != WifiStatusCode.SUCCESS) return; 396 feat.value = wifiFeatureMaskFromStaCapabilities(capabilities); 397 }); 398 } 399 } 400 return feat.value; 401 } catch (RemoteException e) { 402 handleRemoteException(e); 403 return 0; 404 } 405 } 406 407 /* RTT related commands/events */ 408 409 /** 410 * Starts a new rtt request 411 * 412 * @param params 413 * @param handler 414 * @return success indication 415 */ 416 public boolean requestRtt(RttManager.RttParams[] params, WifiNative.RttEventHandler handler) { 417 kilroy(); 418 throw new UnsupportedOperationException(); 419 } 420 421 /** 422 * Cancels an outstanding rtt request 423 * 424 * @param params 425 * @return true if there was an outstanding request and it was successfully cancelled 426 */ 427 public boolean cancelRtt(RttManager.RttParams[] params) { 428 kilroy(); 429 throw new UnsupportedOperationException(); 430 } 431 432 /** 433 * Enables RTT responder role on the device. 434 * 435 * @return {@link ResponderConfig} if the responder role is successfully enabled, 436 * {@code null} otherwise. 437 */ 438 @Nullable 439 public ResponderConfig enableRttResponder(int timeoutSeconds) { 440 kilroy(); 441 throw new UnsupportedOperationException(); 442 } 443 444 /** 445 * Disables RTT responder role. 446 * 447 * @return {@code true} if responder role is successfully disabled, 448 * {@code false} otherwise. 449 */ 450 public boolean disableRttResponder() { 451 kilroy(); 452 throw new UnsupportedOperationException(); 453 } 454 455 /** 456 * not supported 457 */ 458 public boolean setScanningMacOui(byte[] oui) { 459 kilroy(); 460 throw new UnsupportedOperationException(); 461 } 462 463 /** 464 * not supported 465 */ 466 public int[] getChannelsForBand(int band) { 467 kilroy(); 468 throw new UnsupportedOperationException(); 469 } 470 471 /** 472 * not supported 473 */ 474 public boolean isGetChannelsForBandSupported() { 475 kilroy(); 476 throw new UnsupportedOperationException(); 477 } 478 479 /** 480 * Set DFS - actually, this is always on. 481 * 482 * @param dfsOn 483 * @return success indication 484 */ 485 public boolean setDfsFlag(boolean dfsOn) { 486 kilroy(); 487 throw new UnsupportedOperationException(); 488 } 489 490 /** 491 * RTT (Round Trip Time) measurement capabilities of the device. 492 */ 493 public RttManager.RttCapabilities getRttCapabilities() { 494 kilroy(); 495 throw new UnsupportedOperationException(); 496 } 497 498 /** 499 * Get the APF (Android Packet Filter) capabilities of the device 500 */ 501 public ApfCapabilities getApfCapabilities() { 502 class AnswerBox { 503 public ApfCapabilities value = sNoApfCapabilities; 504 } 505 synchronized (sLock) { 506 try { 507 if (mIWifiStaIface == null) return sNoApfCapabilities; 508 AnswerBox box = new AnswerBox(); 509 mIWifiStaIface.getApfPacketFilterCapabilities((status, capabilities) -> { 510 if (status.code != WifiStatusCode.SUCCESS) return; 511 box.value = new ApfCapabilities( 512 /* apfVersionSupported */ capabilities.version, 513 /* maximumApfProgramSize */ capabilities.maxLength, 514 /* apfPacketFormat */ android.system.OsConstants.ARPHRD_ETHER); 515 }); 516 return box.value; 517 } catch (RemoteException e) { 518 handleRemoteException(e); 519 return sNoApfCapabilities; 520 } 521 } 522 } 523 524 private static final ApfCapabilities sNoApfCapabilities = new ApfCapabilities(0, 0, 0); 525 526 /** 527 * Installs an APF program on this iface, replacing any existing program. 528 * 529 * @param filter is the android packet filter program 530 * @return true for success 531 */ 532 public boolean installPacketFilter(byte[] filter) { 533 kilroy(); 534 int cmdId = 0; //TODO(b/34901818) We only aspire to support one program at a time 535 if (filter == null) return false; 536 // Copy the program before taking the lock. 537 ArrayList<Byte> program = new ArrayList<>(filter.length); 538 for (byte b : filter) { 539 program.add(b); 540 } 541 synchronized (sLock) { 542 try { 543 if (mIWifiStaIface == null) return false; 544 WifiStatus status = mIWifiStaIface.installApfPacketFilter(cmdId, program); 545 if (status.code != WifiStatusCode.SUCCESS) return false; 546 kilroy(); 547 return true; 548 } catch (RemoteException e) { 549 handleRemoteException(e); 550 return false; 551 } 552 } 553 } 554 555 /** 556 * to be implemented 557 */ 558 public boolean setCountryCodeHal(String countryCode) { 559 kilroy(); 560 throw new UnsupportedOperationException(); 561 } 562 563 /** 564 * not to be implemented 565 */ 566 public boolean enableDisableTdls(boolean enable, String macAdd, 567 WifiNative.TdlsEventHandler tdlsCallBack) { 568 kilroy(); 569 throw new UnsupportedOperationException(); 570 } 571 572 /** 573 * not to be implemented 574 */ 575 public WifiNative.TdlsStatus getTdlsStatus(String macAdd) { 576 kilroy(); 577 throw new UnsupportedOperationException(); 578 } 579 580 /** 581 * not to be implemented 582 */ 583 public WifiNative.TdlsCapabilities getTdlsCapabilities() { 584 kilroy(); 585 throw new UnsupportedOperationException(); 586 } 587 588 /** 589 * to be implemented 590 */ 591 public boolean setLoggingEventHandler(WifiNative.WifiLoggerEventHandler handler) { 592 kilroy(); 593 throw new UnsupportedOperationException(); 594 } 595 596 /** 597 * Control debug data collection 598 * 599 * @param verboseLevel 0 to 3, inclusive. 0 stops logging. 600 * @param flags Ignored. 601 * @param maxIntervalInSec Maximum interval between reports; ignore if 0. 602 * @param minDataSizeInBytes Minimum data size in buffer for report; ignore if 0. 603 * @param ringName Name of the ring for which data collection is to start. 604 * @return true for success 605 */ 606 public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxIntervalInSec, 607 int minDataSizeInBytes, String ringName) { 608 kilroy(); 609 throw new UnsupportedOperationException(); 610 } 611 612 /** 613 * Pointlessly fail 614 * 615 * @return -1 616 */ 617 public int getSupportedLoggerFeatureSet() { 618 return -1; 619 } 620 621 /** 622 * to be implemented 623 */ 624 public boolean resetLogHandler() { 625 kilroy(); 626 throw new UnsupportedOperationException(); 627 } 628 629 private String mDriverDescription; // Cached value filled by requestChipDebugInfo() 630 631 /** 632 * Vendor-provided wifi driver version string 633 */ 634 public String getDriverVersion() { 635 synchronized (sLock) { 636 if (mDriverDescription == null) requestChipDebugInfo(); 637 return mDriverDescription; 638 } 639 } 640 641 private String mFirmwareDescription; // Cached value filled by requestChipDebugInfo() 642 643 /** 644 * Vendor-provided wifi firmware version string 645 */ 646 public String getFirmwareVersion() { 647 synchronized (sLock) { 648 if (mFirmwareDescription == null) requestChipDebugInfo(); 649 return mFirmwareDescription; 650 } 651 } 652 653 /** 654 * Refreshes our idea of the driver and firmware versions 655 */ 656 private void requestChipDebugInfo() { 657 mDriverDescription = null; 658 mFirmwareDescription = null; 659 try { 660 if (mIWifiChip == null) return; 661 mIWifiChip.requestChipDebugInfo((status, chipDebugInfo) -> { 662 if (status.code != WifiStatusCode.SUCCESS) return; 663 mDriverDescription = chipDebugInfo.driverDescription; 664 mFirmwareDescription = chipDebugInfo.firmwareDescription; 665 }); 666 } catch (RemoteException e) { 667 handleRemoteException(e); 668 return; 669 } 670 Log.e(TAG, "Driver: " + mDriverDescription + " Firmware: " + mFirmwareDescription); 671 } 672 673 /** 674 * API to get the status of all ring buffers supported by driver 675 */ 676 public WifiNative.RingBufferStatus[] getRingBufferStatus() { 677 kilroy(); 678 throw new UnsupportedOperationException(); 679 } 680 681 /** 682 * indicates to driver that all 683 * the data has to be uploaded urgently 684 */ 685 public boolean getRingBufferData(String ringName) { 686 kilroy(); 687 throw new UnsupportedOperationException(); 688 } 689 690 /** 691 * to be implemented via mIWifiChip.requestFirmwareDebugDump 692 */ 693 public byte[] getFwMemoryDump() { 694 kilroy(); 695 throw new UnsupportedOperationException(); 696 } 697 698 /** 699 * Request vendor debug info from the driver 700 */ 701 public byte[] getDriverStateDump() { 702 kilroy(); 703 throw new UnsupportedOperationException(); 704 } 705 706 /** 707 * Start packet fate monitoring 708 * <p> 709 * Once started, monitoring remains active until HAL is unloaded. 710 * 711 * @return true for success 712 */ 713 public boolean startPktFateMonitoring() { 714 kilroy(); 715 throw new UnsupportedOperationException(); 716 } 717 718 /** 719 * Retrieve fates of outbound packets 720 * <p> 721 * Reports the outbound frames for the most recent association (space allowing). 722 * 723 * @param reportBufs 724 * @return true for success 725 */ 726 public boolean getTxPktFates(WifiNative.TxFateReport[] reportBufs) { 727 kilroy(); 728 throw new UnsupportedOperationException(); 729 } 730 731 /** 732 * Retrieve fates of inbound packets 733 * <p> 734 * Reports the inbound frames for the most recent association (space allowing). 735 * 736 * @param reportBufs 737 * @return true for success 738 */ 739 public boolean getRxPktFates(WifiNative.RxFateReport[] reportBufs) { 740 kilroy(); 741 throw new UnsupportedOperationException(); 742 } 743 744 /** 745 * Start sending the specified keep alive packets periodically. 746 * 747 * @return 0 for success, -1 for error 748 */ 749 public int startSendingOffloadedPacket( 750 int slot, KeepalivePacketData keepAlivePacket, int periodInMs) { 751 kilroy(); 752 throw new UnsupportedOperationException(); 753 } 754 755 /** 756 * Stop sending the specified keep alive packets. 757 * 758 * @param slot id - same as startSendingOffloadedPacket call. 759 * @return 0 for success, -1 for error 760 */ 761 public int stopSendingOffloadedPacket(int slot) { 762 kilroy(); 763 throw new UnsupportedOperationException(); 764 } 765 766 /** 767 * Start RSSI monitoring on the currently connected access point. 768 * 769 * @param maxRssi Maximum RSSI threshold. 770 * @param minRssi Minimum RSSI threshold. 771 * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi 772 * @return 0 for success, -1 for failure 773 */ 774 public int startRssiMonitoring(byte maxRssi, byte minRssi, 775 WifiNative.WifiRssiEventHandler rssiEventHandler) { 776 kilroy(); 777 throw new UnsupportedOperationException(); 778 } 779 780 /** 781 * Stop RSSI monitoring 782 * 783 * @return 0 for success, -1 for failure 784 */ 785 public int stopRssiMonitoring() { 786 kilroy(); 787 throw new UnsupportedOperationException(); 788 } 789 790 private WifiDebugHostWakeReasonStats mWifiDebugHostWakeReasonStats; 791 792 /** 793 * Fetch the host wakeup reasons stats from wlan driver. 794 * 795 * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver. 796 */ 797 public WifiWakeReasonAndCounts getWlanWakeReasonCount() { 798 kilroy(); 799 throw new UnsupportedOperationException(); 800 } 801 802 /** 803 * Enable/Disable Neighbour discovery offload functionality in the firmware. 804 */ 805 public boolean configureNeighborDiscoveryOffload(boolean enabled) { 806 kilroy(); 807 throw new UnsupportedOperationException(); 808 } 809 810 // Firmware roaming control. 811 812 /** 813 * Query the firmware roaming capabilities. 814 * 815 * @param capabilities object to be filled in 816 * @return true for success; false for failure 817 */ 818 public boolean getRoamingCapabilities(WifiNative.RoamingCapabilities capabilities) { 819 kilroy(); 820 synchronized (sLock) { 821 kilroy(); 822 try { 823 kilroy(); 824 if (!isHalStarted()) return false; 825 MutableBoolean ok = new MutableBoolean(false); 826 WifiNative.RoamingCapabilities out = capabilities; 827 mIWifiStaIface.getRoamingCapabilities((status, cap) -> { 828 kilroy(); 829 if (status.code != WifiStatusCode.SUCCESS) return; 830 out.maxBlacklistSize = cap.maxBlacklistSize; 831 out.maxWhitelistSize = cap.maxWhitelistSize; 832 ok.value = true; 833 }); 834 return ok.value; 835 } catch (RemoteException e) { 836 kilroy(); 837 handleRemoteException(e); 838 return false; 839 } 840 } 841 } 842 843 /** 844 * Enable/disable firmware roaming. 845 * 846 * @param state the intended roaming state 847 * @return SUCCESS, FAILURE, or BUSY 848 */ 849 public int enableFirmwareRoaming(int state) { 850 kilroy(); 851 synchronized (sLock) { 852 kilroy(); 853 try { 854 kilroy(); 855 if (!isHalStarted()) return WifiStatusCode.ERROR_NOT_STARTED; 856 byte val; 857 switch (state) { 858 case WifiNative.DISABLE_FIRMWARE_ROAMING: 859 val = StaRoamingState.DISABLED; 860 break; 861 case WifiNative.ENABLE_FIRMWARE_ROAMING: 862 val = StaRoamingState.ENABLED; 863 break; 864 default: 865 Log.e(TAG, "enableFirmwareRoaming invalid argument " + state); 866 return WifiStatusCode.ERROR_INVALID_ARGS; 867 } 868 869 kilroy(); 870 WifiStatus status = mIWifiStaIface.setRoamingState(val); 871 Log.d(TAG, "setRoamingState returned " + status.code); 872 return status.code; 873 } catch (RemoteException e) { 874 kilroy(); 875 handleRemoteException(e); 876 return WifiStatusCode.ERROR_UNKNOWN; 877 } 878 } 879 } 880 881 /** 882 * Set firmware roaming configurations. 883 * 884 * @param config new roaming configuration object 885 * @return true for success; false for failure 886 */ 887 public boolean configureRoaming(WifiNative.RoamingConfig config) { 888 kilroy(); 889 synchronized (sLock) { 890 kilroy(); 891 try { 892 kilroy(); 893 if (!isHalStarted()) return false; 894 StaRoamingConfig roamingConfig = new StaRoamingConfig(); 895 896 // parse the blacklist BSSIDs if any 897 if (config.blacklistBssids != null) { 898 kilroy(); 899 for (String bssid : config.blacklistBssids) { 900 String unquotedMacStr = WifiInfo.removeDoubleQuotes(bssid); 901 byte[] mac = new byte[6]; 902 parseUnquotedMacStrToByteArray(unquotedMacStr, mac); 903 roamingConfig.bssidBlacklist.add(mac); 904 } 905 } 906 907 // parse the whitelist SSIDs if any 908 if (config.whitelistSsids != null) { 909 kilroy(); 910 for (String ssidStr : config.whitelistSsids) { 911 String unquotedSsidStr = WifiInfo.removeDoubleQuotes(ssidStr); 912 913 int len = unquotedSsidStr.length(); 914 if (len > 32) { 915 Log.e(TAG, "configureRoaming: skip invalid SSID " + unquotedSsidStr); 916 continue; 917 } 918 byte[] ssid = new byte[len]; 919 for (int i = 0; i < len; i++) { 920 ssid[i] = (byte) unquotedSsidStr.charAt(i); 921 } 922 roamingConfig.ssidWhitelist.add(ssid); 923 } 924 } 925 926 kilroy(); 927 WifiStatus status = mIWifiStaIface.configureRoaming(roamingConfig); 928 if (status.code != WifiStatusCode.SUCCESS) { 929 kilroy(); 930 noteHidlError(status, "configureRoaming"); 931 return false; 932 } 933 } catch (RemoteException e) { 934 kilroy(); 935 handleRemoteException(e); 936 return false; 937 } 938 kilroy(); 939 return true; 940 } 941 } 942 943 /** 944 * Helper function that parses unquoted MAC address string to a byte array 945 * 946 * @param macWithColons mac address string without double quotes 947 * @param mac an array of 6 bytes to receive the parsed mac address 948 */ 949 @VisibleForTesting 950 void parseUnquotedMacStrToByteArray(String macWithColons, byte[] mac) { 951 String[] macAddrStr = macWithColons.split(":"); 952 for (int i = 0; i < 6; i++) { 953 Integer hexVal = Integer.parseInt(macAddrStr[i], 16); 954 mac[i] = hexVal.byteValue(); 955 } 956 } 957 958 StackTraceElement[] mTrace; 959 960 private void kilroy() { 961 Thread cur = Thread.currentThread(); 962 mTrace = cur.getStackTrace(); 963 StackTraceElement s = mTrace[3]; 964 String name = s.getMethodName(); 965 if (name.contains("lambda$")) { 966 // Try to find a friendlier method name 967 String myFile = s.getFileName(); 968 if (myFile != null) { 969 for (int i = 4; i < mTrace.length; i++) { 970 if (myFile.equals(mTrace[i].getFileName())) { 971 name = mTrace[i].getMethodName(); 972 break; 973 } 974 } 975 } 976 } 977 Log.e(TAG, "th " + cur.getId() + " line " + s.getLineNumber() + " " + name); 978 } 979 980 /** 981 * Hal Device Manager callbacks. 982 */ 983 public class HalDeviceManagerStatusListener implements HalDeviceManager.ManagerStatusListener { 984 @Override 985 public void onStatusChanged() { 986 boolean isReady = mHalDeviceManager.isReady(); 987 boolean isStarted = mHalDeviceManager.isStarted(); 988 989 Log.i(TAG, "Device Manager onStatusChanged. isReady(): " + isReady 990 + ", isStarted(): " + isStarted); 991 // Reset all our cached handles. 992 if (!isReady || !isStarted) { 993 kilroy(); 994 mIWifiChip = null; 995 mIWifiStaIface = null; 996 mIWifiApIface = null; 997 mIWifiRttController = null; 998 mDriverDescription = null; 999 mFirmwareDescription = null; 1000 } 1001 } 1002 } 1003} 1004