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