WifiVendorHal.java revision b4659e143a1a0b27e4f4ca82e8428863b8c41324
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.WifiScanner; 35import android.net.wifi.WifiWakeReasonAndCounts; 36import android.os.HandlerThread; 37import android.os.RemoteException; 38import android.util.Log; 39import android.util.MutableBoolean; 40 41import com.android.internal.annotations.VisibleForTesting; 42import com.android.server.connectivity.KeepalivePacketData; 43 44/** 45 * Vendor HAL via HIDL 46 */ 47public class WifiVendorHal { 48 49 private static final String TAG = "WifiVendorHal"; 50 51 // Vendor HAL HIDL interface objects. 52 private IWifiChip mIWifiChip; 53 private IWifiStaIface mIWifiStaIface; 54 private IWifiApIface mIWifiApIface; 55 private IWifiRttController mIWifiRttController; 56 private final HalDeviceManager mHalDeviceManager; 57 private final HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks; 58 private final HandlerThread mWifiStateMachineHandlerThread; 59 60 public WifiVendorHal(HalDeviceManager halDeviceManager, 61 HandlerThread wifiStateMachineHandlerThread) { 62 mHalDeviceManager = halDeviceManager; 63 mWifiStateMachineHandlerThread = wifiStateMachineHandlerThread; 64 mHalDeviceManagerStatusCallbacks = new HalDeviceManagerStatusListener(); 65 } 66 67 // TODO(mplass): figure out where we need locking in hidl world. b/33383725 68 public static final Object sLock = new Object(); 69 70 private void handleRemoteException(RemoteException e) { 71 kilroy(); 72 Log.e(TAG, "RemoteException in HIDL call " + e); 73 } 74 75 private void noteHidlError(WifiStatus status, String culprit) { 76 kilroy(); 77 Log.e(TAG, "Error in " + culprit + " code: " + status.code 78 + " (" + status.description + ")"); 79 } 80 81 /** 82 * Initialize the Hal device manager and register for status callbacks. 83 * @return 84 */ 85 public boolean initialize() { 86 mHalDeviceManager.initialize(); 87 mHalDeviceManager.registerStatusListener( 88 mHalDeviceManagerStatusCallbacks, mWifiStateMachineHandlerThread.getLooper()); 89 return true; 90 } 91 92 /** 93 * Bring up the HIDL Vendor HAL and configure for STA mode or AP mode. 94 * 95 * @param isStaMode true to start HAL in STA mode, false to start in AP mode. 96 */ 97 public boolean startVendorHal(boolean isStaMode) { 98 if (!mHalDeviceManager.start()) { 99 Log.e(TAG, "Failed to start the vendor HAL"); 100 return false; 101 } 102 if (isStaMode) { 103 mIWifiStaIface = mHalDeviceManager.createStaIface(null, null); 104 if (mIWifiStaIface == null) { 105 Log.e(TAG, "Failed to create STA Iface"); 106 return false; 107 } 108 } else { 109 mIWifiApIface = mHalDeviceManager.createApIface(null, null); 110 if (mIWifiApIface == null) { 111 Log.e(TAG, "Failed to create AP Iface"); 112 return false; 113 } 114 } 115 IWifiIface iface = (IWifiIface) (mIWifiStaIface != null ? mIWifiStaIface : mIWifiApIface); 116 mIWifiChip = mHalDeviceManager.getChip(iface); 117 if (mIWifiStaIface == null) { 118 Log.e(TAG, "Failed to get the chip created for the Iface"); 119 return false; 120 } 121 return true; 122 } 123 124 /** 125 * Stops the HAL 126 */ 127 public void stopVendorHal() { 128 mHalDeviceManager.stop(); 129 } 130 131 /** 132 * Tests whether the HAL is running or not 133 */ 134 public boolean isHalStarted() { 135 return (mIWifiStaIface != null || mIWifiApIface != null); 136 } 137 138 /** 139 * Gets the scan capabilities 140 * 141 * @param capabilities object to be filled in 142 * @return true for success. false for failure 143 */ 144 public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) { 145 kilroy(); 146 throw new UnsupportedOperationException(); 147 } 148 149 /** 150 * to be implemented 151 */ 152 public boolean startScan(WifiNative.ScanSettings settings, 153 WifiNative.ScanEventHandler eventHandler) { 154 kilroy(); 155 throw new UnsupportedOperationException(); 156 } 157 158 /** 159 * to be implemented 160 */ 161 public void stopScan() { 162 kilroy(); 163 throw new UnsupportedOperationException(); 164 } 165 166 /** 167 * to be implemented 168 */ 169 public void pauseScan() { 170 kilroy(); 171 throw new UnsupportedOperationException(); 172 } 173 174 /** 175 * to be implemented 176 */ 177 public void restartScan() { 178 kilroy(); 179 throw new UnsupportedOperationException(); 180 } 181 182 /** 183 * to be implemented 184 */ 185 public WifiScanner.ScanData[] getScanResults(boolean flush) { 186 kilroy(); 187 throw new UnsupportedOperationException(); 188 } 189 190 /** 191 * Get the link layer statistics 192 * 193 * @param iface is the name of the wifi interface (checked for null, otherwise ignored) 194 * @return the statistics, or null if unable to do so 195 */ 196 public WifiLinkLayerStats getWifiLinkLayerStats(String iface) { 197 kilroy(); 198 throw new UnsupportedOperationException(); 199 } 200 201 /** 202 * Enable link layer stats collection 203 * 204 * @param iface is the name of the wifi interface (checked for null, otherwise ignored) 205 * @param enable must be 1 206 */ 207 public void setWifiLinkLayerStats(String iface, int enable) { 208 kilroy(); 209 throw new UnsupportedOperationException(); 210 } 211 212 /** 213 * Get the supported features 214 * 215 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 216 */ 217 public int getSupportedFeatureSet() { 218 kilroy(); 219 throw new UnsupportedOperationException(); 220 } 221 222 /* RTT related commands/events */ 223 224 /** 225 * Starts a new rtt request 226 * 227 * @param params 228 * @param handler 229 * @return success indication 230 */ 231 public boolean requestRtt(RttManager.RttParams[] params, WifiNative.RttEventHandler handler) { 232 kilroy(); 233 throw new UnsupportedOperationException(); 234 } 235 236 /** 237 * Cancels an outstanding rtt request 238 * 239 * @param params 240 * @return true if there was an outstanding request and it was successfully cancelled 241 */ 242 public boolean cancelRtt(RttManager.RttParams[] params) { 243 kilroy(); 244 throw new UnsupportedOperationException(); 245 } 246 247 /** 248 * Enables RTT responder role on the device. 249 * 250 * @return {@link ResponderConfig} if the responder role is successfully enabled, 251 * {@code null} otherwise. 252 */ 253 @Nullable 254 public ResponderConfig enableRttResponder(int timeoutSeconds) { 255 kilroy(); 256 throw new UnsupportedOperationException(); 257 } 258 259 /** 260 * Disables RTT responder role. 261 * 262 * @return {@code true} if responder role is successfully disabled, 263 * {@code false} otherwise. 264 */ 265 public boolean disableRttResponder() { 266 kilroy(); 267 throw new UnsupportedOperationException(); 268 } 269 270 /** 271 * not supported 272 */ 273 public boolean setScanningMacOui(byte[] oui) { 274 kilroy(); 275 throw new UnsupportedOperationException(); 276 } 277 278 /** 279 * not supported 280 */ 281 public int[] getChannelsForBand(int band) { 282 kilroy(); 283 throw new UnsupportedOperationException(); 284 } 285 286 /** 287 * not supported 288 */ 289 public boolean isGetChannelsForBandSupported() { 290 kilroy(); 291 throw new UnsupportedOperationException(); 292 } 293 294 /** 295 * Set DFS - actually, this is always on. 296 * 297 * @param dfsOn 298 * @return success indication 299 */ 300 public boolean setDfsFlag(boolean dfsOn) { 301 kilroy(); 302 throw new UnsupportedOperationException(); 303 } 304 305 /** 306 * RTT (Round Trip Time) measurement capabilities of the device. 307 */ 308 public RttManager.RttCapabilities getRttCapabilities() { 309 kilroy(); 310 throw new UnsupportedOperationException(); 311 } 312 313 /** 314 * Get the APF (Android Packet Filter) capabilities of the device 315 */ 316 public ApfCapabilities getApfCapabilities() { 317 kilroy(); 318 throw new UnsupportedOperationException(); 319 } 320 321 private static final ApfCapabilities sNoApfCapabilities = new ApfCapabilities(0, 0, 0); 322 323 /** 324 * Installs an APF program on this iface, replacing an existing 325 * program if present. 326 */ 327 public boolean installPacketFilter(byte[] filter) { 328 kilroy(); 329 throw new UnsupportedOperationException(); 330 } 331 332 333 /** 334 * to be implemented 335 */ 336 public boolean setCountryCodeHal(String countryCode) { 337 kilroy(); 338 throw new UnsupportedOperationException(); 339 } 340 341 /** 342 * not to be implemented 343 */ 344 public boolean enableDisableTdls(boolean enable, String macAdd, 345 WifiNative.TdlsEventHandler tdlsCallBack) { 346 kilroy(); 347 throw new UnsupportedOperationException(); 348 } 349 350 /** 351 * not to be implemented 352 */ 353 public WifiNative.TdlsStatus getTdlsStatus(String macAdd) { 354 kilroy(); 355 throw new UnsupportedOperationException(); 356 } 357 358 /** 359 * not to be implemented 360 */ 361 public WifiNative.TdlsCapabilities getTdlsCapabilities() { 362 kilroy(); 363 throw new UnsupportedOperationException(); 364 } 365 366 /** 367 * to be implemented 368 */ 369 public boolean setLoggingEventHandler(WifiNative.WifiLoggerEventHandler handler) { 370 kilroy(); 371 throw new UnsupportedOperationException(); 372 } 373 374 /** 375 * Control debug data collection 376 * 377 * @param verboseLevel 0 to 3, inclusive. 0 stops logging. 378 * @param flags Ignored. 379 * @param maxIntervalInSec Maximum interval between reports; ignore if 0. 380 * @param minDataSizeInBytes Minimum data size in buffer for report; ignore if 0. 381 * @param ringName Name of the ring for which data collection is to start. 382 * @return true for success 383 */ 384 public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxIntervalInSec, 385 int minDataSizeInBytes, String ringName) { 386 kilroy(); 387 throw new UnsupportedOperationException(); 388 } 389 390 /** 391 * Pointlessly fail 392 * 393 * @return -1 394 */ 395 public int getSupportedLoggerFeatureSet() { 396 return -1; 397 } 398 399 /** 400 * to be implemented 401 */ 402 public boolean resetLogHandler() { 403 kilroy(); 404 throw new UnsupportedOperationException(); 405 } 406 407 private String mDriverDescription; 408 409 /** 410 * Vendor-provided wifi driver version string 411 */ 412 public String getDriverVersion() { 413 kilroy(); 414 throw new UnsupportedOperationException(); 415 } 416 417 private String mFirmwareDescription; 418 419 /** 420 * Vendor-provided wifi firmware version string 421 */ 422 public String getFirmwareVersion() { 423 kilroy(); 424 throw new UnsupportedOperationException(); 425 } 426 427 /** 428 * API to get the status of all ring buffers supported by driver 429 */ 430 public WifiNative.RingBufferStatus[] getRingBufferStatus() { 431 kilroy(); 432 throw new UnsupportedOperationException(); 433 } 434 435 /** 436 * indicates to driver that all 437 * the data has to be uploaded urgently 438 */ 439 public boolean getRingBufferData(String ringName) { 440 kilroy(); 441 throw new UnsupportedOperationException(); 442 } 443 444 /** 445 * to be implemented via mIWifiChip.requestFirmwareDebugDump 446 */ 447 public byte[] getFwMemoryDump() { 448 kilroy(); 449 throw new UnsupportedOperationException(); 450 } 451 452 /** 453 * Request vendor debug info from the driver 454 */ 455 public byte[] getDriverStateDump() { 456 kilroy(); 457 throw new UnsupportedOperationException(); 458 } 459 460 /** 461 * Start packet fate monitoring 462 * <p> 463 * Once started, monitoring remains active until HAL is unloaded. 464 * 465 * @return true for success 466 */ 467 public boolean startPktFateMonitoring() { 468 kilroy(); 469 throw new UnsupportedOperationException(); 470 } 471 472 /** 473 * Retrieve fates of outbound packets 474 * <p> 475 * Reports the outbound frames for the most recent association (space allowing). 476 * 477 * @param reportBufs 478 * @return true for success 479 */ 480 public boolean getTxPktFates(WifiNative.TxFateReport[] reportBufs) { 481 kilroy(); 482 throw new UnsupportedOperationException(); 483 } 484 485 /** 486 * Retrieve fates of inbound packets 487 * <p> 488 * Reports the inbound frames for the most recent association (space allowing). 489 * 490 * @param reportBufs 491 * @return true for success 492 */ 493 public boolean getRxPktFates(WifiNative.RxFateReport[] reportBufs) { 494 kilroy(); 495 throw new UnsupportedOperationException(); 496 } 497 498 /** 499 * Start sending the specified keep alive packets periodically. 500 * 501 * @return 0 for success, -1 for error 502 */ 503 public int startSendingOffloadedPacket( 504 int slot, KeepalivePacketData keepAlivePacket, int periodInMs) { 505 kilroy(); 506 throw new UnsupportedOperationException(); 507 } 508 509 /** 510 * Stop sending the specified keep alive packets. 511 * 512 * @param slot id - same as startSendingOffloadedPacket call. 513 * @return 0 for success, -1 for error 514 */ 515 public int stopSendingOffloadedPacket(int slot) { 516 kilroy(); 517 throw new UnsupportedOperationException(); 518 } 519 520 /** 521 * Start RSSI monitoring on the currently connected access point. 522 * 523 * @param maxRssi Maximum RSSI threshold. 524 * @param minRssi Minimum RSSI threshold. 525 * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi 526 * @return 0 for success, -1 for failure 527 */ 528 public int startRssiMonitoring(byte maxRssi, byte minRssi, 529 WifiNative.WifiRssiEventHandler rssiEventHandler) { 530 kilroy(); 531 throw new UnsupportedOperationException(); 532 } 533 534 /** 535 * Stop RSSI monitoring 536 * 537 * @return 0 for success, -1 for failure 538 */ 539 public int stopRssiMonitoring() { 540 kilroy(); 541 throw new UnsupportedOperationException(); 542 } 543 544 private WifiDebugHostWakeReasonStats mWifiDebugHostWakeReasonStats; 545 546 /** 547 * Fetch the host wakeup reasons stats from wlan driver. 548 * 549 * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver. 550 */ 551 public WifiWakeReasonAndCounts getWlanWakeReasonCount() { 552 kilroy(); 553 throw new UnsupportedOperationException(); 554 } 555 556 /** 557 * Enable/Disable Neighbour discovery offload functionality in the firmware. 558 */ 559 public boolean configureNeighborDiscoveryOffload(boolean enabled) { 560 kilroy(); 561 throw new UnsupportedOperationException(); 562 } 563 564 // Firmware roaming control. 565 566 /** 567 * Query the firmware roaming capabilities. 568 * 569 * @param capabilities object to be filled in 570 * @return true for success; false for failure 571 */ 572 public boolean getRoamingCapabilities(WifiNative.RoamingCapabilities capabilities) { 573 kilroy(); 574 synchronized (sLock) { 575 kilroy(); 576 try { 577 kilroy(); 578 if (!isHalStarted()) return false; 579 MutableBoolean ok = new MutableBoolean(false); 580 WifiNative.RoamingCapabilities out = capabilities; 581 mIWifiStaIface.getRoamingCapabilities((status, cap) -> { 582 kilroy(); 583 if (status.code != WifiStatusCode.SUCCESS) return; 584 out.maxBlacklistSize = cap.maxBlacklistSize; 585 out.maxWhitelistSize = cap.maxWhitelistSize; 586 ok.value = true; 587 }); 588 return ok.value; 589 } catch (RemoteException e) { 590 kilroy(); 591 handleRemoteException(e); 592 return false; 593 } 594 } 595 } 596 597 /** 598 * Enable/disable firmware roaming. 599 * 600 * @param state the intended roaming state 601 * @return SUCCESS, FAILURE, or BUSY 602 */ 603 public int enableFirmwareRoaming(int state) { 604 kilroy(); 605 synchronized (sLock) { 606 kilroy(); 607 try { 608 kilroy(); 609 if (!isHalStarted()) return WifiStatusCode.ERROR_NOT_STARTED; 610 byte val; 611 switch (state) { 612 case WifiNative.DISABLE_FIRMWARE_ROAMING: 613 val = StaRoamingState.DISABLED; 614 break; 615 case WifiNative.ENABLE_FIRMWARE_ROAMING: 616 val = StaRoamingState.ENABLED; 617 break; 618 default: 619 Log.e(TAG, "enableFirmwareRoaming invalid argument " + state); 620 return WifiStatusCode.ERROR_INVALID_ARGS; 621 } 622 623 kilroy(); 624 WifiStatus status = mIWifiStaIface.setRoamingState(val); 625 Log.d(TAG, "setRoamingState returned " + status.code); 626 return status.code; 627 } catch (RemoteException e) { 628 kilroy(); 629 handleRemoteException(e); 630 return WifiStatusCode.ERROR_UNKNOWN; 631 } 632 } 633 } 634 635 /** 636 * Set firmware roaming configurations. 637 * 638 * @param config new roaming configuration object 639 * @return true for success; false for failure 640 */ 641 public boolean configureRoaming(WifiNative.RoamingConfig config) { 642 kilroy(); 643 synchronized (sLock) { 644 kilroy(); 645 try { 646 kilroy(); 647 if (!isHalStarted()) return false; 648 StaRoamingConfig roamingConfig = new StaRoamingConfig(); 649 650 // parse the blacklist BSSIDs if any 651 if (config.blacklistBssids != null) { 652 kilroy(); 653 for (String bssid : config.blacklistBssids) { 654 String unquotedMacStr = WifiInfo.removeDoubleQuotes(bssid); 655 byte[] mac = new byte[6]; 656 parseUnquotedMacStrToByteArray(unquotedMacStr, mac); 657 roamingConfig.bssidBlacklist.add(mac); 658 } 659 } 660 661 // parse the whitelist SSIDs if any 662 if (config.whitelistSsids != null) { 663 kilroy(); 664 for (String ssidStr : config.whitelistSsids) { 665 String unquotedSsidStr = WifiInfo.removeDoubleQuotes(ssidStr); 666 667 int len = unquotedSsidStr.length(); 668 if (len > 32) { 669 Log.e(TAG, "configureRoaming: skip invalid SSID " + unquotedSsidStr); 670 continue; 671 } 672 byte[] ssid = new byte[len]; 673 for (int i = 0; i < len; i++) { 674 ssid[i] = (byte) unquotedSsidStr.charAt(i); 675 } 676 roamingConfig.ssidWhitelist.add(ssid); 677 } 678 } 679 680 kilroy(); 681 WifiStatus status = mIWifiStaIface.configureRoaming(roamingConfig); 682 if (status.code != WifiStatusCode.SUCCESS) { 683 kilroy(); 684 noteHidlError(status, "configureRoaming"); 685 return false; 686 } 687 } catch (RemoteException e) { 688 kilroy(); 689 handleRemoteException(e); 690 return false; 691 } 692 kilroy(); 693 return true; 694 } 695 } 696 697 /** 698 * Helper function that parses unquoted MAC address string to a byte array 699 * 700 * @param macWithColons mac address string without double quotes 701 * @param mac an array of 6 bytes to receive the parsed mac address 702 */ 703 @VisibleForTesting 704 void parseUnquotedMacStrToByteArray(String macWithColons, byte[] mac) { 705 String[] macAddrStr = macWithColons.split(":"); 706 for (int i = 0; i < 6; i++) { 707 Integer hexVal = Integer.parseInt(macAddrStr[i], 16); 708 mac[i] = hexVal.byteValue(); 709 } 710 } 711 712 StackTraceElement[] mTrace; 713 714 private void kilroy() { 715 Thread cur = Thread.currentThread(); 716 mTrace = cur.getStackTrace(); 717 StackTraceElement s = mTrace[3]; 718 String name = s.getMethodName(); 719 if (name.contains("lambda$")) { 720 // Try to find a friendlier method name 721 String myFile = s.getFileName(); 722 if (myFile != null) { 723 for (int i = 4; i < mTrace.length; i++) { 724 if (myFile.equals(mTrace[i].getFileName())) { 725 name = mTrace[i].getMethodName(); 726 break; 727 } 728 } 729 } 730 } 731 Log.e(TAG, "th " + cur.getId() + " line " + s.getLineNumber() + " " + name); 732 } 733 734 /** 735 * Hal Device Manager callbacks. 736 */ 737 public class HalDeviceManagerStatusListener implements HalDeviceManager.ManagerStatusListener { 738 @Override 739 public void onStatusChanged() { 740 Log.i(TAG, "Device Manager onStatusChanged. isReady(): " + mHalDeviceManager.isReady() 741 + "isStarted(): " + mHalDeviceManager.isStarted()); 742 // Reset all our cached handles. 743 if (!mHalDeviceManager.isReady() || !mHalDeviceManager.isStarted()) { 744 mIWifiChip = null; 745 mIWifiStaIface = null; 746 mIWifiApIface = null; 747 mIWifiRttController = null; 748 mDriverDescription = null; 749 mFirmwareDescription = null; 750 } 751 } 752 } 753} 754