WifiVendorHal.java revision 542b204c2120a9c91324ccc86c6695012ac02ab7
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.IWifiChipEventCallback; 22import android.hardware.wifi.V1_0.IWifiIface; 23import android.hardware.wifi.V1_0.IWifiRttController; 24import android.hardware.wifi.V1_0.IWifiStaIface; 25import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback; 26import android.hardware.wifi.V1_0.IfaceType; 27import android.hardware.wifi.V1_0.StaRoamingConfig; 28import android.hardware.wifi.V1_0.StaRoamingState; 29import android.hardware.wifi.V1_0.StaScanData; 30import android.hardware.wifi.V1_0.StaScanResult; 31import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats; 32import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType; 33import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags; 34import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; 35import android.hardware.wifi.V1_0.WifiDebugRxPacketFate; 36import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport; 37import android.hardware.wifi.V1_0.WifiDebugTxPacketFate; 38import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport; 39import android.hardware.wifi.V1_0.WifiStatus; 40import android.hardware.wifi.V1_0.WifiStatusCode; 41import android.net.apf.ApfCapabilities; 42import android.net.wifi.RttManager; 43import android.net.wifi.RttManager.ResponderConfig; 44import android.net.wifi.WifiInfo; 45import android.net.wifi.WifiLinkLayerStats; 46import android.net.wifi.WifiManager; 47import android.net.wifi.WifiScanner; 48import android.net.wifi.WifiWakeReasonAndCounts; 49import android.os.HandlerThread; 50import android.os.RemoteException; 51import android.util.Log; 52import android.util.MutableBoolean; 53import android.util.MutableInt; 54 55import com.android.internal.annotations.VisibleForTesting; 56import com.android.internal.util.ArrayUtils; 57import com.android.server.connectivity.KeepalivePacketData; 58import com.android.server.wifi.util.BitMask; 59import com.android.server.wifi.util.NativeUtil; 60 61import java.util.ArrayList; 62import java.util.Set; 63 64/** 65 * Vendor HAL via HIDL 66 */ 67public class WifiVendorHal { 68 69 private static final String TAG = "WifiVendorHal"; 70 71 // Vendor HAL HIDL interface objects. 72 private IWifiChip mIWifiChip; 73 private IWifiStaIface mIWifiStaIface; 74 private IWifiApIface mIWifiApIface; 75 private IWifiRttController mIWifiRttController; 76 private final HalDeviceManager mHalDeviceManager; 77 private final HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks; 78 private final HandlerThread mWifiStateMachineHandlerThread; 79 private final IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback; 80 private final IWifiChipEventCallback mIWifiChipEventCallback; 81 82 public WifiVendorHal(HalDeviceManager halDeviceManager, 83 HandlerThread wifiStateMachineHandlerThread) { 84 mHalDeviceManager = halDeviceManager; 85 mWifiStateMachineHandlerThread = wifiStateMachineHandlerThread; 86 mHalDeviceManagerStatusCallbacks = new HalDeviceManagerStatusListener(); 87 mIWifiStaIfaceEventCallback = new StaIfaceEventCallback(); 88 mIWifiChipEventCallback = new ChipEventCallback(); 89 } 90 91 // TODO(mplass): figure out where we need locking in hidl world. b/33383725 92 public static final Object sLock = new Object(); 93 94 private void handleRemoteException(RemoteException e) { 95 kilroy(); 96 Log.e(TAG, "RemoteException in HIDL call " + e); 97 } 98 99 private void noteHidlError(WifiStatus status, String culprit) { 100 kilroy(); 101 Log.e(TAG, "Error in " + culprit + " code: " + status.code 102 + " (" + status.description + ")"); 103 } 104 105 /** 106 * Initialize the Hal device manager and register for status callbacks. 107 * @return 108 */ 109 public boolean initialize() { 110 mHalDeviceManager.initialize(); 111 mHalDeviceManager.registerStatusListener( 112 mHalDeviceManagerStatusCallbacks, mWifiStateMachineHandlerThread.getLooper()); 113 return true; 114 } 115 116 /** 117 * Bring up the HIDL Vendor HAL and configure for AP (Access Point) mode 118 * @return true for success 119 */ 120 public boolean startVendorHalAp() { 121 return startVendorHal(AP_MODE); 122 } 123 124 /** 125 * Bring up the HIDL Vendor HAL and configure for STA (Station) mode 126 * @return true for success 127 */ 128 public boolean startVendorHalSta() { 129 return startVendorHal(STA_MODE); 130 } 131 132 133 public static final boolean STA_MODE = true; 134 public static final boolean AP_MODE = false; 135 136 /** 137 * Bring up the HIDL Vendor HAL and configure for STA mode or AP mode. 138 * 139 * @param isStaMode true to start HAL in STA mode, false to start in AP mode. 140 */ 141 public boolean startVendorHal(boolean isStaMode) { 142 if (!mHalDeviceManager.start()) { 143 Log.e(TAG, "Failed to start the vendor HAL"); 144 return false; 145 } 146 IWifiIface iface; 147 if (isStaMode) { 148 mIWifiStaIface = mHalDeviceManager.createStaIface(null, null); 149 if (mIWifiStaIface == null) { 150 Log.e(TAG, "Failed to create STA Iface. Vendor Hal start failed"); 151 mHalDeviceManager.stop(); 152 return false; 153 } 154 iface = (IWifiIface) mIWifiStaIface; 155 if (!registerStaIfaceCallback()) { 156 Log.e(TAG, "Failed to register sta iface callback"); 157 mHalDeviceManager.stop(); 158 return false; 159 } 160 mIWifiRttController = mHalDeviceManager.createRttController(iface); 161 if (mIWifiRttController == null) { 162 Log.e(TAG, "Failed to create RTT controller. Vendor Hal start failed"); 163 stopVendorHal(); 164 return false; 165 } 166 enableLinkLayerStats(); 167 } else { 168 mIWifiApIface = mHalDeviceManager.createApIface(null, null); 169 if (mIWifiApIface == null) { 170 Log.e(TAG, "Failed to create AP Iface. Vendor Hal start failed"); 171 stopVendorHal(); 172 return false; 173 } 174 iface = (IWifiIface) mIWifiApIface; 175 } 176 mIWifiChip = mHalDeviceManager.getChip(iface); 177 if (mIWifiChip == null) { 178 Log.e(TAG, "Failed to get the chip created for the Iface. Vendor Hal start failed"); 179 stopVendorHal(); 180 return false; 181 } 182 if (!registerChipCallback()) { 183 Log.e(TAG, "Failed to register chip callback"); 184 mHalDeviceManager.stop(); 185 return false; 186 } 187 Log.i(TAG, "Vendor Hal started successfully"); 188 return true; 189 } 190 191 /** 192 * Registers the sta iface callback. 193 */ 194 private boolean registerStaIfaceCallback() { 195 synchronized (sLock) { 196 if (mIWifiStaIface == null || mIWifiStaIfaceEventCallback == null) return false; 197 try { 198 kilroy(); 199 WifiStatus status = 200 mIWifiStaIface.registerEventCallback(mIWifiStaIfaceEventCallback); 201 return (status.code == WifiStatusCode.SUCCESS); 202 } catch (RemoteException e) { 203 kilroy(); 204 handleRemoteException(e); 205 return false; 206 } 207 } 208 } 209 210 /** 211 * Registers the sta iface callback. 212 */ 213 private boolean registerChipCallback() { 214 synchronized (sLock) { 215 if (mIWifiChip == null || mIWifiChipEventCallback == null) return false; 216 try { 217 kilroy(); 218 WifiStatus status = mIWifiChip.registerEventCallback(mIWifiChipEventCallback); 219 return (status.code == WifiStatusCode.SUCCESS); 220 } catch (RemoteException e) { 221 kilroy(); 222 handleRemoteException(e); 223 return false; 224 } 225 } 226 } 227 228 /** 229 * Stops the HAL 230 */ 231 public void stopVendorHal() { 232 mHalDeviceManager.stop(); 233 Log.i(TAG, "Vendor Hal stopped"); 234 } 235 236 /** 237 * Tests whether the HAL is running or not 238 */ 239 public boolean isHalStarted() { 240 return (mIWifiStaIface != null || mIWifiApIface != null); 241 } 242 243 /** 244 * Gets the scan capabilities 245 * 246 * @param capabilities object to be filled in 247 * @return true for success. false for failure 248 */ 249 public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) { 250 kilroy(); 251 throw new UnsupportedOperationException(); 252 } 253 254 /** 255 * to be implemented 256 */ 257 public boolean startScan(WifiNative.ScanSettings settings, 258 WifiNative.ScanEventHandler eventHandler) { 259 kilroy(); 260 throw new UnsupportedOperationException(); 261 } 262 263 /** 264 * to be implemented 265 */ 266 public void stopScan() { 267 kilroy(); 268 throw new UnsupportedOperationException(); 269 } 270 271 /** 272 * to be implemented 273 */ 274 public void pauseScan() { 275 kilroy(); 276 throw new UnsupportedOperationException(); 277 } 278 279 /** 280 * to be implemented 281 */ 282 public void restartScan() { 283 kilroy(); 284 throw new UnsupportedOperationException(); 285 } 286 287 /** 288 * to be implemented 289 */ 290 public WifiScanner.ScanData[] getScanResults(boolean flush) { 291 kilroy(); 292 throw new UnsupportedOperationException(); 293 } 294 295 /** 296 * Get the link layer statistics 297 * 298 * Note - we always enable link layer stats on a STA interface. 299 * 300 * @return the statistics, or null if unable to do so 301 */ 302 public WifiLinkLayerStats getWifiLinkLayerStats() { 303 kilroy(); 304 synchronized (sLock) { 305 try { 306 if (mIWifiStaIface == null) return null; 307 kilroy(); 308 WifiLinkLayerStats out = new WifiLinkLayerStats(); 309 MutableBoolean ok = new MutableBoolean(false); 310 kilroy(); 311 mIWifiStaIface.getLinkLayerStats((status, stats) -> { 312 kilroy(); 313 if (status.code != WifiStatusCode.SUCCESS) return; 314 out.status = 0; // TODO 315 out.SSID = null; // TODO 316 out.BSSID = null; // TODO 317 out.beacon_rx = stats.iface.beaconRx; 318 out.rssi_mgmt = stats.iface.avgRssiMgmt; 319 /* WME Best Effort Access Category */ 320 out.rxmpdu_be = stats.iface.wmeBePktStats.rxMpdu; 321 out.txmpdu_be = stats.iface.wmeBePktStats.txMpdu; 322 out.lostmpdu_be = stats.iface.wmeBePktStats.lostMpdu; 323 out.retries_be = stats.iface.wmeBePktStats.retries; 324 /* WME Background Access Category */ 325 out.rxmpdu_bk = stats.iface.wmeBkPktStats.rxMpdu; 326 out.txmpdu_bk = stats.iface.wmeBkPktStats.txMpdu; 327 out.lostmpdu_bk = stats.iface.wmeBkPktStats.lostMpdu; 328 out.retries_bk = stats.iface.wmeBkPktStats.retries; 329 /* WME Video Access Category */ 330 out.rxmpdu_vi = stats.iface.wmeViPktStats.rxMpdu; 331 out.txmpdu_vi = stats.iface.wmeViPktStats.txMpdu; 332 out.lostmpdu_vi = stats.iface.wmeViPktStats.lostMpdu; 333 out.retries_vi = stats.iface.wmeViPktStats.retries; 334 /* WME Voice Access Category */ 335 out.rxmpdu_vo = stats.iface.wmeVoPktStats.rxMpdu; 336 out.txmpdu_vo = stats.iface.wmeVoPktStats.txMpdu; 337 out.lostmpdu_vo = stats.iface.wmeVoPktStats.lostMpdu; 338 out.retries_vo = stats.iface.wmeVoPktStats.retries; 339 out.on_time = stats.radio.onTimeInMs; 340 out.tx_time = stats.radio.txTimeInMs; 341 out.tx_time_per_level = new int[stats.radio.txTimeInMsPerLevel.size()]; 342 for (int i = 0; i < out.tx_time_per_level.length; i++) { 343 out.tx_time_per_level[i] = stats.radio.txTimeInMsPerLevel.get(i); 344 } 345 out.rx_time = stats.radio.rxTimeInMs; 346 out.on_time_scan = stats.radio.onTimeInMsForScan; 347 kilroy(); 348 ok.value = true; 349 } 350 ); 351 return ok.value ? out : null; 352 } catch (RemoteException e) { 353 kilroy(); 354 handleRemoteException(e); 355 return null; 356 } 357 } 358 } 359 360 @VisibleForTesting 361 boolean mLinkLayerStatsDebug = false; // Passed to Hal 362 363 /** 364 * Enables the linkLayerStats in the Hal. 365 * 366 * This is called unconditionally whenever we create a STA interface. 367 * 368 */ 369 private void enableLinkLayerStats() { 370 synchronized (sLock) { 371 try { 372 kilroy(); 373 WifiStatus status; 374 status = mIWifiStaIface.enableLinkLayerStatsCollection(mLinkLayerStatsDebug); 375 if (status.code != WifiStatusCode.SUCCESS) { 376 kilroy(); 377 Log.e(TAG, "unable to enable link layer stats collection"); 378 } 379 } catch (RemoteException e) { 380 kilroy(); 381 handleRemoteException(e); 382 } 383 } 384 } 385 386 /** 387 * Translation table used by getSupportedFeatureSet for translating IWifiStaIface caps 388 */ 389 private static final int[][] sFeatureCapabilityTranslation = { 390 {WifiManager.WIFI_FEATURE_INFRA_5G, 391 IWifiStaIface.StaIfaceCapabilityMask.STA_5G 392 }, 393 {WifiManager.WIFI_FEATURE_PASSPOINT, 394 IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT 395 }, 396 {WifiManager.WIFI_FEATURE_SCANNER, 397 IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN, 398 }, 399 {WifiManager.WIFI_FEATURE_PNO, 400 IWifiStaIface.StaIfaceCapabilityMask.PNO 401 }, 402 {WifiManager.WIFI_FEATURE_TDLS, 403 IWifiStaIface.StaIfaceCapabilityMask.TDLS 404 }, 405 {WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL, 406 IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL 407 }, 408 {WifiManager.WIFI_FEATURE_LINK_LAYER_STATS, 409 IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS 410 }, 411 {WifiManager.WIFI_FEATURE_RSSI_MONITOR, 412 IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR 413 }, 414 {WifiManager.WIFI_FEATURE_MKEEP_ALIVE, 415 IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE 416 }, 417 {WifiManager.WIFI_FEATURE_CONFIG_NDO, 418 IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD 419 }, 420 {WifiManager.WIFI_FEATURE_CONTROL_ROAMING, 421 IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING 422 }, 423 {WifiManager.WIFI_FEATURE_IE_WHITELIST, 424 IWifiStaIface.StaIfaceCapabilityMask.PROBE_IE_WHITELIST 425 }, 426 {WifiManager.WIFI_FEATURE_SCAN_RAND, 427 IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND 428 }, 429 }; 430 431 /** 432 * Feature bit mask translation for STAs 433 * 434 * @param capabilities bitmask defined IWifiStaIface.StaIfaceCapabilityMask 435 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 436 */ 437 @VisibleForTesting 438 int wifiFeatureMaskFromStaCapabilities(int capabilities) { 439 int features = 0; 440 for (int i = 0; i < sFeatureCapabilityTranslation.length; i++) { 441 if ((capabilities & sFeatureCapabilityTranslation[i][1]) != 0) { 442 features |= sFeatureCapabilityTranslation[i][0]; 443 } 444 } 445 return features; 446 } 447 448 /** 449 * Get the supported features 450 * <p> 451 * Note that not all the WifiManager.WIFI_FEATURE_* bits are supplied through 452 * this call. //TODO(b/34900537) fix this 453 * 454 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 455 */ 456 public int getSupportedFeatureSet() { 457 int featureSet = 0; 458 try { 459 final MutableInt feat = new MutableInt(0); 460 synchronized (sLock) { 461 if (mIWifiStaIface != null) { 462 mIWifiStaIface.getCapabilities((status, capabilities) -> { 463 if (status.code != WifiStatusCode.SUCCESS) return; 464 feat.value = wifiFeatureMaskFromStaCapabilities(capabilities); 465 }); 466 } 467 } 468 featureSet = feat.value; 469 } catch (RemoteException e) { 470 handleRemoteException(e); 471 return 0; 472 } 473 474 Set<Integer> supportedIfaceTypes = mHalDeviceManager.getSupportedIfaceTypes(); 475 if (supportedIfaceTypes.contains(IfaceType.STA)) { 476 featureSet |= WifiManager.WIFI_FEATURE_INFRA; 477 } 478 if (supportedIfaceTypes.contains(IfaceType.AP)) { 479 featureSet |= WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT; 480 } 481 if (supportedIfaceTypes.contains(IfaceType.P2P)) { 482 featureSet |= WifiManager.WIFI_FEATURE_P2P; 483 } 484 if (supportedIfaceTypes.contains(IfaceType.NAN)) { 485 featureSet |= WifiManager.WIFI_FEATURE_AWARE; 486 } 487 488 return featureSet; 489 } 490 491 /* RTT related commands/events */ 492 493 /** 494 * Starts a new rtt request 495 * 496 * @param params 497 * @param handler 498 * @return success indication 499 */ 500 public boolean requestRtt(RttManager.RttParams[] params, WifiNative.RttEventHandler handler) { 501 kilroy(); 502 throw new UnsupportedOperationException(); 503 } 504 505 /** 506 * Cancels an outstanding rtt request 507 * 508 * @param params 509 * @return true if there was an outstanding request and it was successfully cancelled 510 */ 511 public boolean cancelRtt(RttManager.RttParams[] params) { 512 kilroy(); 513 throw new UnsupportedOperationException(); 514 } 515 516 /** 517 * Enables RTT responder role on the device. 518 * 519 * @return {@link ResponderConfig} if the responder role is successfully enabled, 520 * {@code null} otherwise. 521 */ 522 @Nullable 523 public ResponderConfig enableRttResponder(int timeoutSeconds) { 524 kilroy(); 525 throw new UnsupportedOperationException(); 526 } 527 528 /** 529 * Disables RTT responder role. 530 * 531 * @return {@code true} if responder role is successfully disabled, 532 * {@code false} otherwise. 533 */ 534 public boolean disableRttResponder() { 535 kilroy(); 536 throw new UnsupportedOperationException(); 537 } 538 539 /** 540 * Set the MAC OUI during scanning. 541 * 542 * An OUI {Organizationally Unique Identifier} is a 24-bit number that 543 * uniquely identifies a vendor or manufacturer. 544 * 545 * @param oui 546 * @return true for success 547 */ 548 public boolean setScanningMacOui(byte[] oui) { 549 kilroy(); 550 if (oui == null) return false; 551 kilroy(); 552 if (oui.length != 3) return false; 553 kilroy(); 554 synchronized (sLock) { 555 try { 556 if (mIWifiStaIface == null) return false; 557 WifiStatus status = mIWifiStaIface.setScanningMacOui(oui); 558 if (status.code != WifiStatusCode.SUCCESS) return false; 559 kilroy(); 560 return true; 561 } catch (RemoteException e) { 562 handleRemoteException(e); 563 return false; 564 } 565 } 566 } 567 568 /** 569 * not supported 570 */ 571 public int[] getChannelsForBand(int band) { 572 kilroy(); 573 throw new UnsupportedOperationException(); 574 } 575 576 /** 577 * not supported 578 */ 579 public boolean isGetChannelsForBandSupported() { 580 kilroy(); 581 throw new UnsupportedOperationException(); 582 } 583 584 /** 585 * Set DFS - actually, this is always on. 586 * 587 * @param dfsOn 588 * @return success indication 589 */ 590 public boolean setDfsFlag(boolean dfsOn) { 591 kilroy(); 592 throw new UnsupportedOperationException(); 593 } 594 595 /** 596 * RTT (Round Trip Time) measurement capabilities of the device. 597 */ 598 public RttManager.RttCapabilities getRttCapabilities() { 599 kilroy(); 600 throw new UnsupportedOperationException(); 601 } 602 603 /** 604 * Get the APF (Android Packet Filter) capabilities of the device 605 */ 606 public ApfCapabilities getApfCapabilities() { 607 class AnswerBox { 608 public ApfCapabilities value = sNoApfCapabilities; 609 } 610 synchronized (sLock) { 611 try { 612 if (mIWifiStaIface == null) return sNoApfCapabilities; 613 AnswerBox box = new AnswerBox(); 614 mIWifiStaIface.getApfPacketFilterCapabilities((status, capabilities) -> { 615 if (status.code != WifiStatusCode.SUCCESS) return; 616 box.value = new ApfCapabilities( 617 /* apfVersionSupported */ capabilities.version, 618 /* maximumApfProgramSize */ capabilities.maxLength, 619 /* apfPacketFormat */ android.system.OsConstants.ARPHRD_ETHER); 620 }); 621 return box.value; 622 } catch (RemoteException e) { 623 handleRemoteException(e); 624 return sNoApfCapabilities; 625 } 626 } 627 } 628 629 private static final ApfCapabilities sNoApfCapabilities = new ApfCapabilities(0, 0, 0); 630 631 /** 632 * Installs an APF program on this iface, replacing any existing program. 633 * 634 * @param filter is the android packet filter program 635 * @return true for success 636 */ 637 public boolean installPacketFilter(byte[] filter) { 638 kilroy(); 639 int cmdId = 0; //TODO(b/34901818) We only aspire to support one program at a time 640 if (filter == null) return false; 641 // Copy the program before taking the lock. 642 ArrayList<Byte> program = new ArrayList<>(filter.length); 643 for (byte b : filter) { 644 program.add(b); 645 } 646 synchronized (sLock) { 647 try { 648 if (mIWifiStaIface == null) return false; 649 WifiStatus status = mIWifiStaIface.installApfPacketFilter(cmdId, program); 650 if (status.code != WifiStatusCode.SUCCESS) return false; 651 kilroy(); 652 return true; 653 } catch (RemoteException e) { 654 handleRemoteException(e); 655 return false; 656 } 657 } 658 } 659 660 /** 661 * Set country code for this AP iface. 662 * 663 * @param countryCode - two-letter country code (as ISO 3166) 664 * @return true for success 665 */ 666 public boolean setCountryCodeHal(String countryCode) { 667 kilroy(); 668 if (countryCode == null) return false; 669 if (countryCode.length() != 2) return false; 670 byte[] code; 671 try { 672 code = NativeUtil.stringToByteArray(countryCode); 673 } catch (IllegalArgumentException e) { 674 kilroy(); 675 return false; 676 } 677 synchronized (sLock) { 678 try { 679 if (mIWifiApIface == null) return false; 680 kilroy(); 681 WifiStatus status = mIWifiApIface.setCountryCode(code); 682 if (status.code != WifiStatusCode.SUCCESS) return false; 683 kilroy(); 684 return true; 685 } catch (RemoteException e) { 686 handleRemoteException(e); 687 return false; 688 } 689 } 690 } 691 692 /** 693 * to be implemented TODO(b/34901821) 694 */ 695 public boolean setLoggingEventHandler(WifiNative.WifiLoggerEventHandler handler) { 696 kilroy(); 697 throw new UnsupportedOperationException(); 698 } 699 700 /** 701 * Control debug data collection 702 * 703 * @param verboseLevel 0 to 3, inclusive. 0 stops logging. 704 * @param flags Ignored. 705 * @param maxIntervalInSec Maximum interval between reports; ignore if 0. 706 * @param minDataSizeInBytes Minimum data size in buffer for report; ignore if 0. 707 * @param ringName Name of the ring for which data collection is to start. 708 * @return true for success 709 */ 710 public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxIntervalInSec, 711 int minDataSizeInBytes, String ringName) { 712 kilroy(); 713 synchronized (sLock) { 714 try { 715 if (mIWifiChip == null) return false; 716 kilroy(); 717 // note - flags are not used 718 WifiStatus status = mIWifiChip.startLoggingToDebugRingBuffer( 719 ringName, 720 verboseLevel, 721 maxIntervalInSec, 722 minDataSizeInBytes 723 ); 724 return status.code == WifiStatusCode.SUCCESS; 725 } catch (RemoteException e) { 726 kilroy(); 727 handleRemoteException(e); 728 return false; 729 } 730 } 731 } 732 733 /** 734 * Pointlessly fail 735 * 736 * @return -1 737 */ 738 public int getSupportedLoggerFeatureSet() { 739 return -1; 740 } 741 742 /** 743 * to be implemented TODO(b/34901821) 744 */ 745 public boolean resetLogHandler() { 746 kilroy(); 747 throw new UnsupportedOperationException(); 748 } 749 750 private String mDriverDescription; // Cached value filled by requestChipDebugInfo() 751 752 /** 753 * Vendor-provided wifi driver version string 754 */ 755 public String getDriverVersion() { 756 synchronized (sLock) { 757 if (mDriverDescription == null) requestChipDebugInfo(); 758 return mDriverDescription; 759 } 760 } 761 762 private String mFirmwareDescription; // Cached value filled by requestChipDebugInfo() 763 764 /** 765 * Vendor-provided wifi firmware version string 766 */ 767 public String getFirmwareVersion() { 768 synchronized (sLock) { 769 if (mFirmwareDescription == null) requestChipDebugInfo(); 770 return mFirmwareDescription; 771 } 772 } 773 774 /** 775 * Refreshes our idea of the driver and firmware versions 776 */ 777 private void requestChipDebugInfo() { 778 mDriverDescription = null; 779 mFirmwareDescription = null; 780 try { 781 if (mIWifiChip == null) return; 782 mIWifiChip.requestChipDebugInfo((status, chipDebugInfo) -> { 783 if (status.code != WifiStatusCode.SUCCESS) return; 784 mDriverDescription = chipDebugInfo.driverDescription; 785 mFirmwareDescription = chipDebugInfo.firmwareDescription; 786 }); 787 } catch (RemoteException e) { 788 handleRemoteException(e); 789 return; 790 } 791 Log.e(TAG, "Driver: " + mDriverDescription + " Firmware: " + mFirmwareDescription); 792 } 793 794 /** 795 * Creates RingBufferStatus from the Hal version 796 */ 797 private static WifiNative.RingBufferStatus ringBufferStatus(WifiDebugRingBufferStatus h) { 798 WifiNative.RingBufferStatus ans = new WifiNative.RingBufferStatus(); 799 ans.name = h.ringName; 800 ans.flag = frameworkRingBufferFlagsFromHal(h.flags); 801 ans.ringBufferId = h.ringId; 802 ans.ringBufferByteSize = h.sizeInBytes; 803 ans.verboseLevel = h.verboseLevel; 804 // Remaining fields are unavailable 805 // writtenBytes; 806 // readBytes; 807 // writtenRecords; 808 return ans; 809 } 810 811 /** 812 * Translates a hal wifiDebugRingBufferFlag to the WifiNative version 813 */ 814 private static int frameworkRingBufferFlagsFromHal(int wifiDebugRingBufferFlag) { 815 BitMask checkoff = new BitMask(wifiDebugRingBufferFlag); 816 int flags = 0; 817 if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES)) { 818 flags |= WifiNative.RingBufferStatus.HAS_BINARY_ENTRIES; 819 } 820 if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES)) { 821 flags |= WifiNative.RingBufferStatus.HAS_ASCII_ENTRIES; 822 } 823 if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES)) { 824 flags |= WifiNative.RingBufferStatus.HAS_PER_PACKET_ENTRIES; 825 } 826 if (checkoff.value != 0) { 827 throw new IllegalArgumentException("Unknown WifiDebugRingBufferFlag " + checkoff.value); 828 } 829 return flags; 830 } 831 832 /** 833 * Creates array of RingBufferStatus from the Hal version 834 */ 835 private static WifiNative.RingBufferStatus[] makeRingBufferStatusArray( 836 ArrayList<WifiDebugRingBufferStatus> ringBuffers) { 837 WifiNative.RingBufferStatus[] ans = new WifiNative.RingBufferStatus[ringBuffers.size()]; 838 int i = 0; 839 for (WifiDebugRingBufferStatus b : ringBuffers) { 840 ans[i++] = ringBufferStatus(b); 841 } 842 return ans; 843 } 844 845 /** 846 * API to get the status of all ring buffers supported by driver 847 */ 848 public WifiNative.RingBufferStatus[] getRingBufferStatus() { 849 kilroy(); 850 class AnswerBox { 851 public WifiNative.RingBufferStatus[] value = null; 852 } 853 AnswerBox ans = new AnswerBox(); 854 synchronized (sLock) { 855 if (mIWifiChip == null) return null; 856 try { 857 kilroy(); 858 mIWifiChip.getDebugRingBuffersStatus((status, ringBuffers) -> { 859 kilroy(); 860 if (status.code != WifiStatusCode.SUCCESS) return; 861 ans.value = makeRingBufferStatusArray(ringBuffers); 862 }); 863 } catch (RemoteException e) { 864 kilroy(); 865 handleRemoteException(e); 866 return null; 867 } 868 } 869 return ans.value; 870 } 871 872 /** 873 * indicates to driver that all 874 * the data has to be uploaded urgently 875 */ 876 public boolean getRingBufferData(String ringName) { 877 kilroy(); 878 synchronized (sLock) { 879 try { 880 if (mIWifiChip == null) return false; 881 kilroy(); 882 WifiStatus status = mIWifiChip.forceDumpToDebugRingBuffer(ringName); 883 return status.code == WifiStatusCode.SUCCESS; 884 } catch (RemoteException e) { 885 handleRemoteException(e); 886 return false; 887 } 888 } 889 } 890 891 /** 892 * Request vendor debug info from the firmware 893 */ 894 public byte[] getFwMemoryDump() { 895 kilroy(); 896 class AnswerBox { 897 public byte[] value; 898 } 899 AnswerBox ans = new AnswerBox(); 900 synchronized (sLock) { 901 if (mIWifiChip == null) return (null); 902 try { 903 kilroy(); 904 mIWifiChip.requestFirmwareDebugDump((status, blob) -> { 905 kilroy(); 906 if (status.code != WifiStatusCode.SUCCESS) return; 907 kilroy(); 908 ans.value = NativeUtil.byteArrayFromArrayList(blob); 909 }); 910 } catch (RemoteException e) { 911 kilroy(); 912 handleRemoteException(e); 913 return null; 914 } 915 } 916 return ans.value; 917 } 918 919 /** 920 * Request vendor debug info from the driver 921 */ 922 public byte[] getDriverStateDump() { 923 kilroy(); 924 class AnswerBox { 925 public byte[] value; 926 } 927 AnswerBox ans = new AnswerBox(); 928 synchronized (sLock) { 929 if (mIWifiChip == null) return (null); 930 try { 931 kilroy(); 932 mIWifiChip.requestDriverDebugDump((status, blob) -> { 933 kilroy(); 934 if (status.code != WifiStatusCode.SUCCESS) return; 935 kilroy(); 936 ans.value = NativeUtil.byteArrayFromArrayList(blob); 937 }); 938 } catch (RemoteException e) { 939 kilroy(); 940 handleRemoteException(e); 941 return null; 942 } 943 } 944 return ans.value; 945 } 946 947 /** 948 * Start packet fate monitoring 949 * 950 * Once started, monitoring remains active until HAL is unloaded. 951 * 952 * @return true for success 953 */ 954 public boolean startPktFateMonitoring() { 955 kilroy(); 956 synchronized (sLock) { 957 if (mIWifiStaIface == null) return false; 958 try { 959 kilroy(); 960 WifiStatus status = mIWifiStaIface.startDebugPacketFateMonitoring(); 961 return status.code == WifiStatusCode.SUCCESS; 962 } catch (RemoteException e) { 963 kilroy(); 964 handleRemoteException(e); 965 return false; 966 } 967 } 968 } 969 970 private byte halToFrameworkPktFateFrameType(int type) { 971 switch (type) { 972 case WifiDebugPacketFateFrameType.UNKNOWN: 973 return WifiLoggerHal.FRAME_TYPE_UNKNOWN; 974 case WifiDebugPacketFateFrameType.ETHERNET_II: 975 return WifiLoggerHal.FRAME_TYPE_ETHERNET_II; 976 case WifiDebugPacketFateFrameType.MGMT_80211: 977 return WifiLoggerHal.FRAME_TYPE_80211_MGMT; 978 default: 979 throw new IllegalArgumentException("bad " + type); 980 } 981 } 982 983 private byte halToFrameworkRxPktFate(int type) { 984 switch (type) { 985 case WifiDebugRxPacketFate.SUCCESS: 986 return WifiLoggerHal.RX_PKT_FATE_SUCCESS; 987 case WifiDebugRxPacketFate.FW_QUEUED: 988 return WifiLoggerHal.RX_PKT_FATE_FW_QUEUED; 989 case WifiDebugRxPacketFate.FW_DROP_FILTER: 990 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER; 991 case WifiDebugRxPacketFate.FW_DROP_INVALID: 992 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID; 993 case WifiDebugRxPacketFate.FW_DROP_NOBUFS: 994 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS; 995 case WifiDebugRxPacketFate.FW_DROP_OTHER: 996 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER; 997 case WifiDebugRxPacketFate.DRV_QUEUED: 998 return WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED; 999 case WifiDebugRxPacketFate.DRV_DROP_FILTER: 1000 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER; 1001 case WifiDebugRxPacketFate.DRV_DROP_INVALID: 1002 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID; 1003 case WifiDebugRxPacketFate.DRV_DROP_NOBUFS: 1004 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS; 1005 case WifiDebugRxPacketFate.DRV_DROP_OTHER: 1006 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER; 1007 default: 1008 throw new IllegalArgumentException("bad " + type); 1009 } 1010 } 1011 1012 private byte halToFrameworkTxPktFate(int type) { 1013 switch (type) { 1014 case WifiDebugTxPacketFate.ACKED: 1015 return WifiLoggerHal.TX_PKT_FATE_ACKED; 1016 case WifiDebugTxPacketFate.SENT: 1017 return WifiLoggerHal.TX_PKT_FATE_SENT; 1018 case WifiDebugTxPacketFate.FW_QUEUED: 1019 return WifiLoggerHal.TX_PKT_FATE_FW_QUEUED; 1020 case WifiDebugTxPacketFate.FW_DROP_INVALID: 1021 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID; 1022 case WifiDebugTxPacketFate.FW_DROP_NOBUFS: 1023 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS; 1024 case WifiDebugTxPacketFate.FW_DROP_OTHER: 1025 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER; 1026 case WifiDebugTxPacketFate.DRV_QUEUED: 1027 return WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED; 1028 case WifiDebugTxPacketFate.DRV_DROP_INVALID: 1029 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID; 1030 case WifiDebugTxPacketFate.DRV_DROP_NOBUFS: 1031 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS; 1032 case WifiDebugTxPacketFate.DRV_DROP_OTHER: 1033 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER; 1034 default: 1035 throw new IllegalArgumentException("bad " + type); 1036 } 1037 } 1038 1039 /** 1040 * Retrieve fates of outbound packets 1041 * 1042 * Reports the outbound frames for the most recent association (space allowing). 1043 * 1044 * @param reportBufs 1045 * @return true for success 1046 */ 1047 public boolean getTxPktFates(WifiNative.TxFateReport[] reportBufs) { 1048 kilroy(); 1049 if (ArrayUtils.isEmpty(reportBufs)) return false; 1050 synchronized (sLock) { 1051 if (mIWifiStaIface == null) return false; 1052 try { 1053 kilroy(); 1054 MutableBoolean ok = new MutableBoolean(false); 1055 mIWifiStaIface.getDebugTxPacketFates((status, fates) -> { 1056 kilroy(); 1057 if (status.code != WifiStatusCode.SUCCESS) return; 1058 int i = 0; 1059 for (WifiDebugTxPacketFateReport fate : fates) { 1060 kilroy(); 1061 if (i >= reportBufs.length) break; 1062 byte code = halToFrameworkTxPktFate(fate.fate); 1063 long us = fate.frameInfo.driverTimestampUsec; 1064 byte type = 1065 halToFrameworkPktFateFrameType(fate.frameInfo.frameType); 1066 byte[] frame = 1067 NativeUtil.byteArrayFromArrayList( 1068 fate.frameInfo.frameContent); 1069 reportBufs[i++] = 1070 new WifiNative.TxFateReport(code, us, type, frame); 1071 } 1072 ok.value = true; 1073 } 1074 ); 1075 return ok.value; 1076 } catch (RemoteException e) { 1077 kilroy(); 1078 handleRemoteException(e); 1079 return false; 1080 } 1081 } 1082 } 1083 1084 /** 1085 * Retrieve fates of inbound packets 1086 * 1087 * Reports the inbound frames for the most recent association (space allowing). 1088 * 1089 * @param reportBufs 1090 * @return true for success 1091 */ 1092 public boolean getRxPktFates(WifiNative.RxFateReport[] reportBufs) { 1093 kilroy(); 1094 if (ArrayUtils.isEmpty(reportBufs)) return false; 1095 synchronized (sLock) { 1096 if (mIWifiStaIface == null) return false; 1097 try { 1098 kilroy(); 1099 MutableBoolean ok = new MutableBoolean(false); 1100 mIWifiStaIface.getDebugRxPacketFates((status, fates) -> { 1101 kilroy(); 1102 if (status.code != WifiStatusCode.SUCCESS) return; 1103 int i = 0; 1104 for (WifiDebugRxPacketFateReport fate : fates) { 1105 kilroy(); 1106 if (i >= reportBufs.length) break; 1107 byte code = halToFrameworkRxPktFate(fate.fate); 1108 long us = fate.frameInfo.driverTimestampUsec; 1109 byte type = 1110 halToFrameworkPktFateFrameType(fate.frameInfo.frameType); 1111 byte[] frame = 1112 NativeUtil.byteArrayFromArrayList( 1113 fate.frameInfo.frameContent); 1114 reportBufs[i++] = 1115 new WifiNative.RxFateReport(code, us, type, frame); 1116 } 1117 ok.value = true; 1118 } 1119 ); 1120 return ok.value; 1121 } catch (RemoteException e) { 1122 kilroy(); 1123 handleRemoteException(e); 1124 return false; 1125 } 1126 } 1127 } 1128 1129 /** 1130 * Start sending the specified keep alive packets periodically. 1131 * @param slot 1132 * @param srcMac 1133 * @param keepAlivePacket 1134 * @param periodInMs 1135 * @return 0 for success, -1 for error 1136 */ 1137 public int startSendingOffloadedPacket( 1138 int slot, byte[] srcMac, KeepalivePacketData keepAlivePacket, int periodInMs) { 1139 Log.d(TAG, "startSendingOffloadedPacket slot=" + slot + " periodInMs=" + periodInMs); 1140 1141 ArrayList<Byte> data = NativeUtil.byteArrayToArrayList(keepAlivePacket.data); 1142 short protocol = (short) (keepAlivePacket.protocol); 1143 1144 synchronized (sLock) { 1145 if (mIWifiStaIface == null) return -1; 1146 try { 1147 WifiStatus status = mIWifiStaIface.startSendingKeepAlivePackets( 1148 slot, 1149 data, 1150 protocol, 1151 srcMac, 1152 keepAlivePacket.dstMac, 1153 periodInMs); 1154 if (status.code != WifiStatusCode.SUCCESS) return -1; 1155 return 0; 1156 } catch (RemoteException e) { 1157 kilroy(); 1158 handleRemoteException(e); 1159 return -1; 1160 } 1161 } 1162 } 1163 1164 /** 1165 * Stop sending the specified keep alive packets. 1166 * 1167 * @param slot id - same as startSendingOffloadedPacket call. 1168 * @return 0 for success, -1 for error 1169 */ 1170 public int stopSendingOffloadedPacket(int slot) { 1171 Log.d(TAG, "stopSendingOffloadedPacket " + slot); 1172 1173 synchronized (sLock) { 1174 if (mIWifiStaIface == null) return -1; 1175 try { 1176 WifiStatus wifiStatus = mIWifiStaIface.stopSendingKeepAlivePackets(slot); 1177 if (wifiStatus.code != WifiStatusCode.SUCCESS) return -1; 1178 kilroy(); 1179 return 0; 1180 } catch (RemoteException e) { 1181 handleRemoteException(e); 1182 return -1; 1183 } 1184 } 1185 } 1186 1187 /** 1188 * Start RSSI monitoring on the currently connected access point. 1189 * 1190 * @param maxRssi Maximum RSSI threshold. 1191 * @param minRssi Minimum RSSI threshold. 1192 * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi 1193 * @return 0 for success, -1 for failure 1194 */ 1195 public int startRssiMonitoring(byte maxRssi, byte minRssi, 1196 WifiNative.WifiRssiEventHandler rssiEventHandler) { 1197 kilroy(); 1198 throw new UnsupportedOperationException(); 1199 } 1200 1201 /** 1202 * Stop RSSI monitoring 1203 * 1204 * @return 0 for success, -1 for failure 1205 */ 1206 public int stopRssiMonitoring() { 1207 kilroy(); 1208 throw new UnsupportedOperationException(); 1209 } 1210 1211 //TODO - belongs in NativeUtil 1212 private static int[] intsFromArrayList(ArrayList<Integer> a) { 1213 if (a == null) return null; 1214 int[] b = new int[a.size()]; 1215 int i = 0; 1216 for (Integer e : a) b[i++] = e; 1217 return b; 1218 } 1219 1220 /** 1221 * Translates from Hal version of wake reason stats to the framework version of same 1222 * 1223 * @param h - Hal version of wake reason stats 1224 * @return framework version of same 1225 */ 1226 private static WifiWakeReasonAndCounts halToFrameworkWakeReasons( 1227 WifiDebugHostWakeReasonStats h) { 1228 if (h == null) return null; 1229 WifiWakeReasonAndCounts ans = new WifiWakeReasonAndCounts(); 1230 ans.totalCmdEventWake = h.totalCmdEventWakeCnt; 1231 ans.totalDriverFwLocalWake = h.totalDriverFwLocalWakeCnt; 1232 ans.totalRxDataWake = h.totalRxPacketWakeCnt; 1233 ans.rxUnicast = h.rxPktWakeDetails.rxUnicastCnt; 1234 ans.rxMulticast = h.rxPktWakeDetails.rxMulticastCnt; 1235 ans.rxBroadcast = h.rxPktWakeDetails.rxBroadcastCnt; 1236 ans.icmp = h.rxIcmpPkWakeDetails.icmpPkt; 1237 ans.icmp6 = h.rxIcmpPkWakeDetails.icmp6Pkt; 1238 ans.icmp6Ra = h.rxIcmpPkWakeDetails.icmp6Ra; 1239 ans.icmp6Na = h.rxIcmpPkWakeDetails.icmp6Na; 1240 ans.icmp6Ns = h.rxIcmpPkWakeDetails.icmp6Ns; 1241 ans.ipv4RxMulticast = h.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt; 1242 ans.ipv6Multicast = h.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt; 1243 ans.otherRxMulticast = h.rxMulticastPkWakeDetails.otherRxMulticastAddrCnt; 1244 ans.cmdEventWakeCntArray = intsFromArrayList(h.cmdEventWakeCntPerType); 1245 ans.driverFWLocalWakeCntArray = intsFromArrayList(h.driverFwLocalWakeCntPerType); 1246 return ans; 1247 } 1248 1249 /** 1250 * Fetch the host wakeup reasons stats from wlan driver. 1251 * 1252 * @return the |WifiWakeReasonAndCounts| from the wlan driver, or null on failure. 1253 */ 1254 public WifiWakeReasonAndCounts getWlanWakeReasonCount() { 1255 kilroy(); 1256 class AnswerBox { 1257 public WifiDebugHostWakeReasonStats value = null; 1258 } 1259 AnswerBox ans = new AnswerBox(); 1260 synchronized (sLock) { 1261 if (mIWifiChip == null) return null; 1262 try { 1263 kilroy(); 1264 mIWifiChip.getDebugHostWakeReasonStats((status, stats) -> { 1265 kilroy(); 1266 if (status.code == WifiStatusCode.SUCCESS) { 1267 ans.value = stats; 1268 } 1269 }); 1270 kilroy(); 1271 return halToFrameworkWakeReasons(ans.value); 1272 } catch (RemoteException e) { 1273 kilroy(); 1274 handleRemoteException(e); 1275 return null; 1276 } 1277 } 1278 } 1279 1280 /** 1281 * Enable/Disable Neighbour discovery offload functionality in the firmware. 1282 * 1283 * @param enabled true to enable, false to disable. 1284 */ 1285 public boolean configureNeighborDiscoveryOffload(boolean enabled) { 1286 kilroy(); 1287 synchronized (sLock) { 1288 if (mIWifiStaIface == null) return false; 1289 kilroy(); 1290 try { 1291 kilroy(); 1292 WifiStatus wifiStatus = mIWifiStaIface.enableNdOffload(enabled); 1293 if (wifiStatus.code != WifiStatusCode.SUCCESS) { 1294 kilroy(); 1295 noteHidlError(wifiStatus, "configureNeighborDiscoveryOffload"); 1296 return false; 1297 } 1298 } catch (RemoteException e) { 1299 kilroy(); 1300 handleRemoteException(e); 1301 return false; 1302 } 1303 } 1304 return true; 1305 } 1306 1307 // Firmware roaming control. 1308 1309 /** 1310 * Query the firmware roaming capabilities. 1311 * 1312 * @param capabilities object to be filled in 1313 * @return true for success; false for failure 1314 */ 1315 public boolean getRoamingCapabilities(WifiNative.RoamingCapabilities capabilities) { 1316 kilroy(); 1317 synchronized (sLock) { 1318 kilroy(); 1319 try { 1320 kilroy(); 1321 if (!isHalStarted()) return false; 1322 MutableBoolean ok = new MutableBoolean(false); 1323 WifiNative.RoamingCapabilities out = capabilities; 1324 mIWifiStaIface.getRoamingCapabilities((status, cap) -> { 1325 kilroy(); 1326 if (status.code != WifiStatusCode.SUCCESS) return; 1327 out.maxBlacklistSize = cap.maxBlacklistSize; 1328 out.maxWhitelistSize = cap.maxWhitelistSize; 1329 ok.value = true; 1330 }); 1331 return ok.value; 1332 } catch (RemoteException e) { 1333 kilroy(); 1334 handleRemoteException(e); 1335 return false; 1336 } 1337 } 1338 } 1339 1340 /** 1341 * Enable/disable firmware roaming. 1342 * 1343 * @param state the intended roaming state 1344 * @return SUCCESS, FAILURE, or BUSY 1345 */ 1346 public int enableFirmwareRoaming(int state) { 1347 kilroy(); 1348 synchronized (sLock) { 1349 if (mIWifiStaIface == null) return WifiStatusCode.ERROR_NOT_STARTED; 1350 kilroy(); 1351 try { 1352 kilroy(); 1353 byte val; 1354 switch (state) { 1355 case WifiNative.DISABLE_FIRMWARE_ROAMING: 1356 val = StaRoamingState.DISABLED; 1357 break; 1358 case WifiNative.ENABLE_FIRMWARE_ROAMING: 1359 val = StaRoamingState.ENABLED; 1360 break; 1361 default: 1362 Log.e(TAG, "enableFirmwareRoaming invalid argument " + state); 1363 return WifiStatusCode.ERROR_INVALID_ARGS; 1364 } 1365 1366 kilroy(); 1367 WifiStatus status = mIWifiStaIface.setRoamingState(val); 1368 Log.d(TAG, "setRoamingState returned " + status.code); 1369 return status.code; 1370 } catch (RemoteException e) { 1371 kilroy(); 1372 handleRemoteException(e); 1373 return WifiStatusCode.ERROR_UNKNOWN; 1374 } 1375 } 1376 } 1377 1378 /** 1379 * Set firmware roaming configurations. 1380 * 1381 * @param config new roaming configuration object 1382 * @return true for success; false for failure 1383 */ 1384 public boolean configureRoaming(WifiNative.RoamingConfig config) { 1385 kilroy(); 1386 synchronized (sLock) { 1387 if (mIWifiStaIface == null) return false; 1388 kilroy(); 1389 try { 1390 kilroy(); 1391 StaRoamingConfig roamingConfig = new StaRoamingConfig(); 1392 1393 // parse the blacklist BSSIDs if any 1394 if (config.blacklistBssids != null) { 1395 kilroy(); 1396 for (String bssid : config.blacklistBssids) { 1397 byte[] mac = NativeUtil.macAddressToByteArray(bssid); 1398 roamingConfig.bssidBlacklist.add(mac); 1399 } 1400 } 1401 1402 // parse the whitelist SSIDs if any 1403 if (config.whitelistSsids != null) { 1404 kilroy(); 1405 for (String ssidStr : config.whitelistSsids) { 1406 String unquotedSsidStr = WifiInfo.removeDoubleQuotes(ssidStr); 1407 1408 int len = unquotedSsidStr.length(); 1409 if (len > 32) { 1410 Log.e(TAG, "configureRoaming: skip invalid SSID " + unquotedSsidStr); 1411 continue; 1412 } 1413 byte[] ssid = new byte[len]; 1414 for (int i = 0; i < len; i++) { 1415 ssid[i] = (byte) unquotedSsidStr.charAt(i); 1416 } 1417 roamingConfig.ssidWhitelist.add(ssid); 1418 } 1419 } 1420 1421 kilroy(); 1422 WifiStatus status = mIWifiStaIface.configureRoaming(roamingConfig); 1423 if (status.code != WifiStatusCode.SUCCESS) { 1424 kilroy(); 1425 noteHidlError(status, "configureRoaming"); 1426 return false; 1427 } 1428 } catch (RemoteException e) { 1429 kilroy(); 1430 handleRemoteException(e); 1431 return false; 1432 } 1433 kilroy(); 1434 return true; 1435 } 1436 } 1437 1438 StackTraceElement[] mTrace; 1439 1440 private void kilroy() { 1441 Thread cur = Thread.currentThread(); 1442 mTrace = cur.getStackTrace(); 1443 StackTraceElement s = mTrace[3]; 1444 String name = s.getMethodName(); 1445 if (name.contains("lambda$")) { 1446 // Try to find a friendlier method name 1447 String myFile = s.getFileName(); 1448 if (myFile != null) { 1449 for (int i = 4; i < mTrace.length; i++) { 1450 if (myFile.equals(mTrace[i].getFileName())) { 1451 name = mTrace[i].getMethodName(); 1452 break; 1453 } 1454 } 1455 } 1456 } 1457 Log.e(TAG, "th " + cur.getId() + " line " + s.getLineNumber() + " " + name); 1458 } 1459 1460 /** 1461 * Callback for events on the STA interface. 1462 */ 1463 private class StaIfaceEventCallback extends IWifiStaIfaceEventCallback.Stub { 1464 @Override 1465 public void onBackgroundScanFailure(int cmdId) { 1466 kilroy(); 1467 Log.d(TAG, "onBackgroundScanFailure " + cmdId); 1468 } 1469 1470 @Override 1471 public void onBackgroundFullScanResult(int cmdId, StaScanResult result) { 1472 kilroy(); 1473 Log.d(TAG, "onBackgroundFullScanResult " + cmdId); 1474 } 1475 1476 @Override 1477 public void onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas) { 1478 kilroy(); 1479 Log.d(TAG, "onBackgroundScanResults " + cmdId); 1480 } 1481 1482 @Override 1483 public void onRssiThresholdBreached(int cmdId, byte[/* 6 */] currBssid, int currRssi) { 1484 kilroy(); 1485 Log.d(TAG, "onRssiThresholdBreached " + cmdId + "currRssi " + currRssi); 1486 } 1487 } 1488 1489 /** 1490 * Callback for events on the STA interface. 1491 */ 1492 private class ChipEventCallback extends IWifiChipEventCallback.Stub { 1493 @Override 1494 public void onChipReconfigured(int modeId) { 1495 kilroy(); 1496 Log.d(TAG, "onChipReconfigured " + modeId); 1497 } 1498 1499 @Override 1500 public void onChipReconfigureFailure(WifiStatus status) { 1501 kilroy(); 1502 Log.d(TAG, "onChipReconfigureFailure " + status); 1503 } 1504 1505 public void onIfaceAdded(int type, String name) { 1506 kilroy(); 1507 Log.d(TAG, "onIfaceAdded " + type + ", name: " + name); 1508 } 1509 1510 @Override 1511 public void onIfaceRemoved(int type, String name) { 1512 kilroy(); 1513 Log.d(TAG, "onIfaceRemoved " + type + ", name: " + name); 1514 } 1515 1516 @Override 1517 public void onDebugRingBufferDataAvailable( 1518 WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { 1519 kilroy(); 1520 Log.d(TAG, "onDebugRingBufferDataAvailable " + status); 1521 } 1522 1523 @Override 1524 public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { 1525 kilroy(); 1526 Log.d(TAG, "onDebugErrorAlert " + errorCode); 1527 } 1528 } 1529 1530 /** 1531 * Hal Device Manager callbacks. 1532 */ 1533 public class HalDeviceManagerStatusListener implements HalDeviceManager.ManagerStatusListener { 1534 @Override 1535 public void onStatusChanged() { 1536 boolean isReady = mHalDeviceManager.isReady(); 1537 boolean isStarted = mHalDeviceManager.isStarted(); 1538 1539 Log.i(TAG, "Device Manager onStatusChanged. isReady(): " + isReady 1540 + ", isStarted(): " + isStarted); 1541 // Reset all our cached handles. 1542 if (!isReady || !isStarted) { 1543 kilroy(); 1544 mIWifiChip = null; 1545 mIWifiStaIface = null; 1546 mIWifiApIface = null; 1547 mIWifiRttController = null; 1548 mDriverDescription = null; 1549 mFirmwareDescription = null; 1550 } 1551 } 1552 } 1553} 1554