WifiVendorHal.java revision 699cb92ca94c3fbd883472937ab3b071cafadf77
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.hardware.wifi.V1_0.IWifiApIface; 19import android.hardware.wifi.V1_0.IWifiChip; 20import android.hardware.wifi.V1_0.IWifiChipEventCallback; 21import android.hardware.wifi.V1_0.IWifiIface; 22import android.hardware.wifi.V1_0.IWifiRttController; 23import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback; 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.RttBw; 28import android.hardware.wifi.V1_0.RttConfig; 29import android.hardware.wifi.V1_0.RttPeerType; 30import android.hardware.wifi.V1_0.RttPreamble; 31import android.hardware.wifi.V1_0.RttResponder; 32import android.hardware.wifi.V1_0.RttResult; 33import android.hardware.wifi.V1_0.RttType; 34import android.hardware.wifi.V1_0.StaBackgroundScanBucketEventReportSchemeMask; 35import android.hardware.wifi.V1_0.StaBackgroundScanBucketParameters; 36import android.hardware.wifi.V1_0.StaBackgroundScanParameters; 37import android.hardware.wifi.V1_0.StaLinkLayerStats; 38import android.hardware.wifi.V1_0.StaRoamingConfig; 39import android.hardware.wifi.V1_0.StaRoamingState; 40import android.hardware.wifi.V1_0.StaScanData; 41import android.hardware.wifi.V1_0.StaScanDataFlagMask; 42import android.hardware.wifi.V1_0.StaScanResult; 43import android.hardware.wifi.V1_0.WifiBand; 44import android.hardware.wifi.V1_0.WifiChannelWidthInMhz; 45import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats; 46import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType; 47import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags; 48import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; 49import android.hardware.wifi.V1_0.WifiDebugRxPacketFate; 50import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport; 51import android.hardware.wifi.V1_0.WifiDebugTxPacketFate; 52import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport; 53import android.hardware.wifi.V1_0.WifiInformationElement; 54import android.hardware.wifi.V1_0.WifiStatus; 55import android.hardware.wifi.V1_0.WifiStatusCode; 56import android.net.apf.ApfCapabilities; 57import android.net.wifi.RttManager; 58import android.net.wifi.RttManager.ResponderConfig; 59import android.net.wifi.ScanResult; 60import android.net.wifi.WifiInfo; 61import android.net.wifi.WifiLinkLayerStats; 62import android.net.wifi.WifiManager; 63import android.net.wifi.WifiScanner; 64import android.net.wifi.WifiSsid; 65import android.net.wifi.WifiWakeReasonAndCounts; 66import android.os.HandlerThread; 67import android.os.RemoteException; 68import android.util.MutableBoolean; 69import android.util.MutableInt; 70 71import com.android.internal.annotations.VisibleForTesting; 72import com.android.internal.util.ArrayUtils; 73import com.android.server.connectivity.KeepalivePacketData; 74import com.android.server.wifi.util.BitMask; 75import com.android.server.wifi.util.NativeUtil; 76 77import java.util.ArrayList; 78import java.util.Set; 79 80/** 81 * Vendor HAL via HIDL 82 */ 83public class WifiVendorHal { 84 85 private static final WifiLog sNoLog = new FakeWifiLog(); 86 87 /** 88 * Chatty logging should use mVerboseLog 89 */ 90 @VisibleForTesting 91 WifiLog mVerboseLog = sNoLog; 92 93 /** 94 * Errors should use mLog 95 */ 96 @VisibleForTesting 97 WifiLog mLog = new LogcatLog("WifiVendorHal"); 98 99 /** 100 * Enables or disables verbose logging 101 * 102 * @param verbose - with the obvious interpretation 103 */ 104 public void enableVerboseLogging(boolean verbose) { 105 synchronized (sLock) { 106 if (verbose) { 107 mVerboseLog = mLog; 108 enter("verbose=true").flush(); 109 } else { 110 enter("verbose=false").flush(); 111 mVerboseLog = sNoLog; 112 } 113 } 114 } 115 116 /** 117 * Checks for a successful status result. 118 * 119 * Failures are logged to mLog. 120 * 121 * @param status is the WifiStatus generated by a hal call 122 * @return true for success, false for failure 123 */ 124 private boolean ok(WifiStatus status) { 125 if (status.code == WifiStatusCode.SUCCESS) return true; 126 127 Thread cur = Thread.currentThread(); 128 StackTraceElement[] trace = cur.getStackTrace(); 129 130 mLog.err("% failed %") 131 .c(niceMethodName(trace, 3)) 132 .c(status.toString()) 133 .flush(); 134 135 return false; 136 } 137 138 /** 139 * Logs if the argument is false. 140 * 141 * Always returns its argument. 142 */ 143 private boolean boolResult(boolean result) { 144 if (mVerboseLog == sNoLog) return result; 145 // Currently only seen if verbose logging is on 146 147 Thread cur = Thread.currentThread(); 148 StackTraceElement[] trace = cur.getStackTrace(); 149 150 mVerboseLog.err("% returns %") 151 .c(niceMethodName(trace, 3)) 152 .c(result) 153 .flush(); 154 155 return result; 156 } 157 158 /** 159 * Logs at method entry 160 * 161 * @param format string with % placeholders 162 * @return LogMessage formatter (remember to .flush()) 163 */ 164 private WifiLog.LogMessage enter(String format) { 165 if (mVerboseLog == sNoLog) return sNoLog.info(format); 166 Thread cur = Thread.currentThread(); 167 StackTraceElement[] trace = cur.getStackTrace(); 168 return mVerboseLog.trace("% " + format).c(trace[3].getMethodName()); 169 } 170 171 /** 172 * Gets the method name and line number from a stack trace. 173 * 174 * Attempts to skip frames created by lambdas to get a human-sensible name. 175 * 176 * @param trace, fo example obtained by Thread.currentThread().getStackTrace() 177 * @param start frame number to log, typically 3 178 * @return string cotaining the method name and line number 179 */ 180 private static String niceMethodName(StackTraceElement[] trace, int start) { 181 if (start >= trace.length) return ""; 182 StackTraceElement s = trace[start]; 183 String name = s.getMethodName(); 184 if (name.contains("lambda$")) { 185 // Try to find a friendlier method name 186 String myFile = s.getFileName(); 187 if (myFile != null) { 188 for (int i = start + 1; i < trace.length; i++) { 189 if (myFile.equals(trace[i].getFileName())) { 190 name = trace[i].getMethodName(); 191 break; 192 } 193 } 194 } 195 } 196 return (name + "(l." + s.getLineNumber() + ")"); 197 } 198 199 // Vendor HAL HIDL interface objects. 200 private IWifiChip mIWifiChip; 201 private IWifiStaIface mIWifiStaIface; 202 private IWifiApIface mIWifiApIface; 203 private IWifiRttController mIWifiRttController; 204 private final HalDeviceManager mHalDeviceManager; 205 private final HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks; 206 private final HandlerThread mWifiStateMachineHandlerThread; 207 private final IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback; 208 private final IWifiChipEventCallback mIWifiChipEventCallback; 209 210 public WifiVendorHal(HalDeviceManager halDeviceManager, 211 HandlerThread wifiStateMachineHandlerThread) { 212 mHalDeviceManager = halDeviceManager; 213 mWifiStateMachineHandlerThread = wifiStateMachineHandlerThread; 214 mHalDeviceManagerStatusCallbacks = new HalDeviceManagerStatusListener(); 215 mIWifiStaIfaceEventCallback = new StaIfaceEventCallback(); 216 mIWifiChipEventCallback = new ChipEventCallback(); 217 } 218 219 // TODO(mplass): figure out where we need locking in hidl world. b/33383725 220 public static final Object sLock = new Object(); 221 222 private void handleRemoteException(RemoteException e) { 223 String methodName = niceMethodName(Thread.currentThread().getStackTrace(), 3); 224 mLog.err("% RemoteException in HIDL call %").c(methodName).c(e.toString()).flush(); 225 } 226 227 /** 228 * Initialize the Hal device manager and register for status callbacks. 229 * 230 * @return 231 */ 232 public boolean initialize() { 233 mHalDeviceManager.initialize(); 234 mHalDeviceManager.registerStatusListener( 235 mHalDeviceManagerStatusCallbacks, mWifiStateMachineHandlerThread.getLooper()); 236 return true; 237 } 238 239 /** 240 * Bring up the HIDL Vendor HAL and configure for AP (Access Point) mode 241 * 242 * @return true for success 243 */ 244 public boolean startVendorHalAp() { 245 return startVendorHal(AP_MODE); 246 } 247 248 /** 249 * Bring up the HIDL Vendor HAL and configure for STA (Station) mode 250 * 251 * @return true for success 252 */ 253 public boolean startVendorHalSta() { 254 return startVendorHal(STA_MODE); 255 } 256 257 public static final boolean STA_MODE = true; 258 public static final boolean AP_MODE = false; 259 260 /** 261 * Bring up the HIDL Vendor HAL and configure for STA mode or AP mode. 262 * 263 * @param isStaMode true to start HAL in STA mode, false to start in AP mode. 264 */ 265 public boolean startVendorHal(boolean isStaMode) { 266 if (!mHalDeviceManager.start()) { 267 mLog.e("Failed to start the vendor HAL"); 268 return false; 269 } 270 IWifiIface iface; 271 if (isStaMode) { 272 mIWifiStaIface = mHalDeviceManager.createStaIface(null, null); 273 if (mIWifiStaIface == null) { 274 mLog.e("Failed to create STA Iface. Vendor Hal start failed"); 275 mHalDeviceManager.stop(); 276 return false; 277 } 278 iface = (IWifiIface) mIWifiStaIface; 279 if (!registerStaIfaceCallback()) { 280 mLog.e("Failed to register sta iface callback"); 281 mHalDeviceManager.stop(); 282 return false; 283 } 284 mIWifiRttController = mHalDeviceManager.createRttController(iface); 285 if (mIWifiRttController == null) { 286 mLog.e("Failed to create RTT controller. Vendor Hal start failed"); 287 stopVendorHal(); 288 return false; 289 } 290 enableLinkLayerStats(); 291 } else { 292 mIWifiApIface = mHalDeviceManager.createApIface(null, null); 293 if (mIWifiApIface == null) { 294 mLog.e("Failed to create AP Iface. Vendor Hal start failed"); 295 stopVendorHal(); 296 return false; 297 } 298 iface = (IWifiIface) mIWifiApIface; 299 } 300 mIWifiChip = mHalDeviceManager.getChip(iface); 301 if (mIWifiChip == null) { 302 mLog.e("Failed to get the chip created for the Iface. Vendor Hal start failed"); 303 stopVendorHal(); 304 return false; 305 } 306 if (!registerChipCallback()) { 307 mLog.e("Failed to register chip callback"); 308 mHalDeviceManager.stop(); 309 return false; 310 } 311 mLog.i("Vendor Hal started successfully"); 312 return true; 313 } 314 315 /** 316 * Registers the sta iface callback. 317 */ 318 private boolean registerStaIfaceCallback() { 319 synchronized (sLock) { 320 if (mIWifiStaIface == null) return boolResult(false); 321 if (mIWifiStaIfaceEventCallback == null) return boolResult(false); 322 try { 323 WifiStatus status = 324 mIWifiStaIface.registerEventCallback(mIWifiStaIfaceEventCallback); 325 return ok(status); 326 } catch (RemoteException e) { 327 handleRemoteException(e); 328 return false; 329 } 330 } 331 } 332 333 /** 334 * Registers the sta iface callback. 335 */ 336 private boolean registerChipCallback() { 337 synchronized (sLock) { 338 if (mIWifiChip == null) return boolResult(false); 339 if (mIWifiChipEventCallback == null) return boolResult(false); 340 try { 341 WifiStatus status = mIWifiChip.registerEventCallback(mIWifiChipEventCallback); 342 return ok(status); 343 } catch (RemoteException e) { 344 handleRemoteException(e); 345 return false; 346 } 347 } 348 } 349 350 /** 351 * Stops the HAL 352 */ 353 public void stopVendorHal() { 354 mHalDeviceManager.stop(); 355 mLog.i("Vendor Hal stopped"); 356 } 357 358 /** 359 * Tests whether the HAL is running or not 360 */ 361 public boolean isHalStarted() { 362 // For external use only. Methods in this class should test for null directly. 363 return (mIWifiStaIface != null || mIWifiApIface != null); 364 } 365 366 /** 367 * Gets the scan capabilities 368 * 369 * @param capabilities object to be filled in 370 * @return true for success. false for failure 371 */ 372 public boolean getScanCapabilities(WifiNative.ScanCapabilities capabilities) { 373 synchronized (sLock) { 374 if (mIWifiStaIface == null) return boolResult(false); 375 try { 376 MutableBoolean ans = new MutableBoolean(false); 377 WifiNative.ScanCapabilities out = capabilities; 378 mIWifiStaIface.getBackgroundScanCapabilities((status, cap) -> { 379 if (!ok(status)) return; 380 mVerboseLog.info("scan capabilities %").c(cap.toString()).flush(); 381 out.max_scan_cache_size = cap.maxCacheSize; 382 out.max_ap_cache_per_scan = cap.maxApCachePerScan; 383 out.max_scan_buckets = cap.maxBuckets; 384 out.max_rssi_sample_size = 0; 385 out.max_scan_reporting_threshold = cap.maxReportingThreshold; 386 out.max_hotlist_bssids = 0; 387 out.max_significant_wifi_change_aps = 0; 388 out.max_bssid_history_entries = 0; 389 out.max_number_epno_networks = 0; 390 out.max_number_epno_networks_by_ssid = 0; 391 out.max_number_of_white_listed_ssid = 0; 392 ans.value = true; 393 } 394 ); 395 return ans.value; 396 } catch (RemoteException e) { 397 handleRemoteException(e); 398 return false; 399 } 400 } 401 } 402 403 /** 404 * Holds the current background scan state, to implement pause and restart 405 */ 406 @VisibleForTesting 407 class CurrentBackgroundScan { 408 public int cmdId; 409 public StaBackgroundScanParameters param; 410 public WifiNative.ScanEventHandler eventHandler = null; 411 public boolean paused = false; 412 public WifiScanner.ScanData[] latestScanResults = null; 413 414 CurrentBackgroundScan(int id, WifiNative.ScanSettings settings) { 415 cmdId = id; 416 param = new StaBackgroundScanParameters(); 417 param.basePeriodInMs = settings.base_period_ms; 418 param.maxApPerScan = settings.max_ap_per_scan; 419 param.reportThresholdPercent = settings.report_threshold_percent; 420 param.reportThresholdNumScans = settings.report_threshold_num_scans; 421 if (settings.buckets != null) { 422 for (WifiNative.BucketSettings bs : settings.buckets) { 423 param.buckets.add(makeStaBackgroundScanBucketParametersFromBucketSettings(bs)); 424 } 425 } 426 } 427 } 428 429 /** 430 * Makes the Hal flavor of WifiNative.BucketSettings 431 * 432 * @param bs WifiNative.BucketSettings 433 * @return Hal flavor of bs 434 * @throws IllegalArgumentException if band value is not recognized 435 */ 436 private StaBackgroundScanBucketParameters 437 makeStaBackgroundScanBucketParametersFromBucketSettings(WifiNative.BucketSettings bs) { 438 StaBackgroundScanBucketParameters pa = new StaBackgroundScanBucketParameters(); 439 pa.bucketIdx = bs.bucket; 440 pa.band = makeWifiBandFromFrameworkBand(bs.band); 441 if (bs.channels != null) { 442 for (WifiNative.ChannelSettings cs : bs.channels) { 443 pa.frequencies.add(cs.frequency); 444 } 445 } 446 pa.periodInMs = bs.period_ms; 447 pa.eventReportScheme = makeReportSchemeFromBucketSettingsReportEvents(bs.report_events); 448 pa.exponentialMaxPeriodInMs = bs.max_period_ms; 449 // Although HAL API allows configurable base value for the truncated 450 // exponential back off scan. Native API and above support only 451 // truncated binary exponential back off scan. 452 // Hard code value of base to 2 here. 453 pa.exponentialBase = 2; 454 pa.exponentialStepCount = bs.step_count; 455 return pa; 456 } 457 458 /** 459 * Makes the Hal flavor of WifiScanner's band indication 460 * 461 * @param frameworkBand one of WifiScanner.WIFI_BAND_* 462 * @return A WifiBand value 463 * @throws IllegalArgumentException if frameworkBand is not recognized 464 */ 465 private int makeWifiBandFromFrameworkBand(int frameworkBand) { 466 switch (frameworkBand) { 467 case WifiScanner.WIFI_BAND_UNSPECIFIED: 468 return WifiBand.BAND_UNSPECIFIED; 469 case WifiScanner.WIFI_BAND_24_GHZ: 470 return WifiBand.BAND_24GHZ; 471 case WifiScanner.WIFI_BAND_5_GHZ: 472 return WifiBand.BAND_5GHZ; 473 case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: 474 return WifiBand.BAND_5GHZ_DFS; 475 case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: 476 return WifiBand.BAND_5GHZ_WITH_DFS; 477 case WifiScanner.WIFI_BAND_BOTH: 478 return WifiBand.BAND_24GHZ_5GHZ; 479 case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: 480 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS; 481 default: 482 throw new IllegalArgumentException("bad band " + frameworkBand); 483 } 484 } 485 486 /** 487 * Makes the Hal flavor of WifiScanner's report event mask 488 * 489 * @param reportUnderscoreEvents is logical OR of WifiScanner.REPORT_EVENT_* values 490 * @return Corresponding StaBackgroundScanBucketEventReportSchemeMask value 491 * @throws IllegalArgumentException if a mask bit is not recognized 492 */ 493 private int makeReportSchemeFromBucketSettingsReportEvents(int reportUnderscoreEvents) { 494 int ans = 0; 495 BitMask in = new BitMask(reportUnderscoreEvents); 496 if (in.testAndClear(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)) { 497 ans |= StaBackgroundScanBucketEventReportSchemeMask.EACH_SCAN; 498 } 499 if (in.testAndClear(WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)) { 500 ans |= StaBackgroundScanBucketEventReportSchemeMask.FULL_RESULTS; 501 } 502 if (in.testAndClear(WifiScanner.REPORT_EVENT_NO_BATCH)) { 503 ans |= StaBackgroundScanBucketEventReportSchemeMask.NO_BATCH; 504 } 505 if (in.value != 0) throw new IllegalArgumentException("bad " + reportUnderscoreEvents); 506 return ans; 507 } 508 509 private int mLastScanCmdId; // For assigning cmdIds to scans 510 511 @VisibleForTesting 512 CurrentBackgroundScan mScan = null; 513 514 /** 515 * Starts a background scan 516 * <p> 517 * Any ongoing scan will be stopped first 518 * 519 * @param settings to control the scan 520 * @param eventHandler to call with the results 521 * @return true for success 522 */ 523 public boolean startScan(WifiNative.ScanSettings settings, 524 WifiNative.ScanEventHandler eventHandler) { 525 WifiStatus status; 526 if (eventHandler == null) return boolResult(false); 527 synchronized (sLock) { 528 if (mIWifiStaIface == null) return boolResult(false); 529 try { 530 if (mScan != null && !mScan.paused) { 531 ok(mIWifiStaIface.stopBackgroundScan(mScan.cmdId)); 532 mScan = null; 533 } 534 mLastScanCmdId = (mLastScanCmdId % 9) + 1; // cycle through non-zero single digits 535 CurrentBackgroundScan scan = new CurrentBackgroundScan(mLastScanCmdId, settings); 536 status = mIWifiStaIface.startBackgroundScan(scan.cmdId, scan.param); 537 if (!ok(status)) return false; 538 scan.eventHandler = eventHandler; 539 mScan = scan; 540 return true; 541 } catch (RemoteException e) { 542 handleRemoteException(e); 543 return false; 544 } 545 } 546 } 547 548 549 /** 550 * Stops any ongoing backgound scan 551 */ 552 public void stopScan() { 553 WifiStatus status; 554 synchronized (sLock) { 555 if (mIWifiStaIface == null) return; 556 try { 557 if (mScan != null) { 558 ok(mIWifiStaIface.stopBackgroundScan(mScan.cmdId)); 559 mScan = null; 560 } 561 } catch (RemoteException e) { 562 handleRemoteException(e); 563 } 564 } 565 } 566 567 /** 568 * Pauses an ongoing backgound scan 569 */ 570 public void pauseScan() { 571 WifiStatus status; 572 synchronized (sLock) { 573 try { 574 if (mIWifiStaIface == null) return; 575 if (mScan != null && !mScan.paused) { 576 status = mIWifiStaIface.stopBackgroundScan(mScan.cmdId); 577 if (!ok(status)) return; 578 mScan.paused = true; 579 } 580 } catch (RemoteException e) { 581 handleRemoteException(e); 582 } 583 } 584 } 585 586 /** 587 * Restarts a paused scan 588 */ 589 public void restartScan() { 590 WifiStatus status; 591 synchronized (sLock) { 592 if (mIWifiStaIface == null) return; 593 try { 594 if (mScan != null && mScan.paused) { 595 status = mIWifiStaIface.startBackgroundScan(mScan.cmdId, mScan.param); 596 if (!ok(status)) return; 597 mScan.paused = false; 598 } 599 } catch (RemoteException e) { 600 handleRemoteException(e); 601 } 602 } 603 } 604 605 /** 606 * Gets the latest scan results received from the HIDL interface callback. 607 * TODO(b/35754840): This hop to fetch scan results after callback is unnecessary. Refactor 608 * WifiScanner to use the scan results from the callback. 609 */ 610 public WifiScanner.ScanData[] getScanResults() { 611 synchronized (sLock) { 612 if (mIWifiStaIface == null) return null; 613 if (mScan == null) return null; 614 return mScan.latestScanResults; 615 } 616 } 617 618 /** 619 * Get the link layer statistics 620 * 621 * Note - we always enable link layer stats on a STA interface. 622 * 623 * @return the statistics, or null if unable to do so 624 */ 625 public WifiLinkLayerStats getWifiLinkLayerStats() { 626 class AnswerBox { 627 public StaLinkLayerStats value = null; 628 } 629 AnswerBox answer = new AnswerBox(); 630 synchronized (sLock) { 631 try { 632 if (mIWifiStaIface == null) return null; 633 mIWifiStaIface.getLinkLayerStats((status, stats) -> { 634 if (!ok(status)) return; 635 answer.value = stats; 636 }); 637 } catch (RemoteException e) { 638 handleRemoteException(e); 639 return null; 640 } 641 } 642 WifiLinkLayerStats stats = frameworkFromHalLinkLayerStats(answer.value); 643 return stats; 644 } 645 646 /** 647 * Makes the framework version of link layer stats from the hal version. 648 */ 649 @VisibleForTesting 650 static WifiLinkLayerStats frameworkFromHalLinkLayerStats(StaLinkLayerStats stats) { 651 if (stats == null) return null; 652 WifiLinkLayerStats out = new WifiLinkLayerStats(); 653 // unpopulated: out.status, out.SSID, out.BSSID 654 out.beacon_rx = stats.iface.beaconRx; 655 out.rssi_mgmt = stats.iface.avgRssiMgmt; 656 // Statistics are broken out by Wireless Multimedia Extensions categories 657 // WME Best Effort Access Category 658 out.rxmpdu_be = stats.iface.wmeBePktStats.rxMpdu; 659 out.txmpdu_be = stats.iface.wmeBePktStats.txMpdu; 660 out.lostmpdu_be = stats.iface.wmeBePktStats.lostMpdu; 661 out.retries_be = stats.iface.wmeBePktStats.retries; 662 // WME Background Access Category 663 out.rxmpdu_bk = stats.iface.wmeBkPktStats.rxMpdu; 664 out.txmpdu_bk = stats.iface.wmeBkPktStats.txMpdu; 665 out.lostmpdu_bk = stats.iface.wmeBkPktStats.lostMpdu; 666 out.retries_bk = stats.iface.wmeBkPktStats.retries; 667 // WME Video Access Category 668 out.rxmpdu_vi = stats.iface.wmeViPktStats.rxMpdu; 669 out.txmpdu_vi = stats.iface.wmeViPktStats.txMpdu; 670 out.lostmpdu_vi = stats.iface.wmeViPktStats.lostMpdu; 671 out.retries_vi = stats.iface.wmeViPktStats.retries; 672 // WME Voice Access Category 673 out.rxmpdu_vo = stats.iface.wmeVoPktStats.rxMpdu; 674 out.txmpdu_vo = stats.iface.wmeVoPktStats.txMpdu; 675 out.lostmpdu_vo = stats.iface.wmeVoPktStats.lostMpdu; 676 out.retries_vo = stats.iface.wmeVoPktStats.retries; 677 out.on_time = stats.radio.onTimeInMs; 678 out.tx_time = stats.radio.txTimeInMs; 679 out.tx_time_per_level = new int[stats.radio.txTimeInMsPerLevel.size()]; 680 for (int i = 0; i < out.tx_time_per_level.length; i++) { 681 out.tx_time_per_level[i] = stats.radio.txTimeInMsPerLevel.get(i); 682 } 683 out.rx_time = stats.radio.rxTimeInMs; 684 out.on_time_scan = stats.radio.onTimeInMsForScan; 685 // unused: stats.timeStampInMs; 686 return out; 687 } 688 689 @VisibleForTesting 690 boolean mLinkLayerStatsDebug = false; // Passed to Hal 691 692 /** 693 * Enables the linkLayerStats in the Hal. 694 * 695 * This is called unconditionally whenever we create a STA interface. 696 */ 697 private void enableLinkLayerStats() { 698 synchronized (sLock) { 699 try { 700 WifiStatus status; 701 status = mIWifiStaIface.enableLinkLayerStatsCollection(mLinkLayerStatsDebug); 702 if (!ok(status)) { 703 mLog.e("unable to enable link layer stats collection"); 704 } 705 } catch (RemoteException e) { 706 handleRemoteException(e); 707 } 708 } 709 } 710 711 /** 712 * Translation table used by getSupportedFeatureSet for translating IWifiStaIface caps 713 */ 714 private static final int[][] sFeatureCapabilityTranslation = { 715 {WifiManager.WIFI_FEATURE_INFRA_5G, 716 IWifiStaIface.StaIfaceCapabilityMask.STA_5G 717 }, 718 {WifiManager.WIFI_FEATURE_PASSPOINT, 719 IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT 720 }, 721 {WifiManager.WIFI_FEATURE_SCANNER, 722 IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN, 723 }, 724 {WifiManager.WIFI_FEATURE_PNO, 725 IWifiStaIface.StaIfaceCapabilityMask.PNO 726 }, 727 {WifiManager.WIFI_FEATURE_TDLS, 728 IWifiStaIface.StaIfaceCapabilityMask.TDLS 729 }, 730 {WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL, 731 IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL 732 }, 733 {WifiManager.WIFI_FEATURE_LINK_LAYER_STATS, 734 IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS 735 }, 736 {WifiManager.WIFI_FEATURE_RSSI_MONITOR, 737 IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR 738 }, 739 {WifiManager.WIFI_FEATURE_MKEEP_ALIVE, 740 IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE 741 }, 742 {WifiManager.WIFI_FEATURE_CONFIG_NDO, 743 IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD 744 }, 745 {WifiManager.WIFI_FEATURE_CONTROL_ROAMING, 746 IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING 747 }, 748 {WifiManager.WIFI_FEATURE_IE_WHITELIST, 749 IWifiStaIface.StaIfaceCapabilityMask.PROBE_IE_WHITELIST 750 }, 751 {WifiManager.WIFI_FEATURE_SCAN_RAND, 752 IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND 753 }, 754 }; 755 756 /** 757 * Feature bit mask translation for STAs 758 * 759 * @param capabilities bitmask defined IWifiStaIface.StaIfaceCapabilityMask 760 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 761 */ 762 @VisibleForTesting 763 int wifiFeatureMaskFromStaCapabilities(int capabilities) { 764 int features = 0; 765 for (int i = 0; i < sFeatureCapabilityTranslation.length; i++) { 766 if ((capabilities & sFeatureCapabilityTranslation[i][1]) != 0) { 767 features |= sFeatureCapabilityTranslation[i][0]; 768 } 769 } 770 return features; 771 } 772 773 /** 774 * Get the supported features 775 * <p> 776 * Note that not all the WifiManager.WIFI_FEATURE_* bits are supplied through 777 * this call. //TODO(b/34900537) fix this 778 * 779 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 780 */ 781 public int getSupportedFeatureSet() { 782 int featureSet = 0; 783 try { 784 final MutableInt feat = new MutableInt(0); 785 synchronized (sLock) { 786 if (mIWifiStaIface != null) { 787 mIWifiStaIface.getCapabilities((status, capabilities) -> { 788 if (!ok(status)) return; 789 feat.value = wifiFeatureMaskFromStaCapabilities(capabilities); 790 }); 791 } 792 } 793 featureSet = feat.value; 794 } catch (RemoteException e) { 795 handleRemoteException(e); 796 return 0; 797 } 798 799 Set<Integer> supportedIfaceTypes = mHalDeviceManager.getSupportedIfaceTypes(); 800 if (supportedIfaceTypes.contains(IfaceType.STA)) { 801 featureSet |= WifiManager.WIFI_FEATURE_INFRA; 802 } 803 if (supportedIfaceTypes.contains(IfaceType.AP)) { 804 featureSet |= WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT; 805 } 806 if (supportedIfaceTypes.contains(IfaceType.P2P)) { 807 featureSet |= WifiManager.WIFI_FEATURE_P2P; 808 } 809 if (supportedIfaceTypes.contains(IfaceType.NAN)) { 810 featureSet |= WifiManager.WIFI_FEATURE_AWARE; 811 } 812 813 return featureSet; 814 } 815 816 /* RTT related commands/events */ 817 818 /** 819 * RTT (Round Trip Time) measurement capabilities of the device. 820 */ 821 public RttManager.RttCapabilities getRttCapabilities() { 822 class AnswerBox { 823 public RttManager.RttCapabilities value = null; 824 } 825 synchronized (sLock) { 826 if (mIWifiRttController == null) return null; 827 try { 828 AnswerBox box = new AnswerBox(); 829 mIWifiRttController.getCapabilities((status, capabilities) -> { 830 if (!ok(status)) return; 831 mVerboseLog.info("rtt capabilites %").c(capabilities.toString()).flush(); 832 RttManager.RttCapabilities ans = new RttManager.RttCapabilities(); 833 ans.oneSidedRttSupported = capabilities.rttOneSidedSupported; 834 ans.twoSided11McRttSupported = capabilities.rttFtmSupported; 835 ans.lciSupported = capabilities.lciSupported; 836 ans.lcrSupported = capabilities.lcrSupported; 837 ans.preambleSupported = frameworkPreambleFromHalPreamble( 838 capabilities.preambleSupport); 839 ans.bwSupported = frameworkBwFromHalBw(capabilities.bwSupport); 840 ans.responderSupported = capabilities.responderSupported; 841 ans.secureRttSupported = false; 842 ans.mcVersion = ((int) capabilities.mcVersion) & 0xff; 843 box.value = ans; 844 }); 845 return box.value; 846 } catch (RemoteException e) { 847 handleRemoteException(e); 848 return null; 849 } 850 } 851 } 852 853 private int mRttCmdIdNext = 1; // used to generate new command ids 854 private int mRttCmdId; // id of currently active request 855 private RttEventCallback mRttEventCallback; // currently active RTT callback 856 857 /** 858 * Receives a callback from the Hal and passes it along to our client using RttEventHandler 859 */ 860 private class RttEventCallback extends IWifiRttControllerEventCallback.Stub { 861 WifiNative.RttEventHandler mRttEventHandler; 862 int mRttCmdId; 863 864 RttEventCallback(int cmdId, WifiNative.RttEventHandler rttEventHandler) { 865 mRttCmdId = cmdId; 866 mRttEventHandler = rttEventHandler; 867 } 868 869 @Override 870 public void onResults(int cmdId, java.util.ArrayList<RttResult> results) { 871 WifiNative.RttEventHandler eventHandler; 872 synchronized (sLock) { 873 if (cmdId != mRttCmdId || mRttEventHandler == null) return; 874 eventHandler = mRttEventHandler; 875 } 876 RttManager.RttResult[] rtt = new RttManager.RttResult[results.size()]; 877 for (int i = 0; i < rtt.length; i++) { 878 rtt[i] = frameworkRttResultFromHalRttResult(results.get(i)); 879 } 880 eventHandler.onRttResults(rtt); 881 } 882 } 883 884 /** 885 * Converts a Hal RttResult to a RttManager.RttResult 886 */ 887 @VisibleForTesting 888 static RttManager.RttResult frameworkRttResultFromHalRttResult(RttResult result) { 889 RttManager.RttResult ans = new RttManager.RttResult(); 890 ans.bssid = NativeUtil.macAddressFromByteArray(result.addr); 891 ans.burstNumber = result.burstNum; 892 ans.measurementFrameNumber = result.measurementNumber; 893 ans.successMeasurementFrameNumber = result.successNumber; 894 ans.frameNumberPerBurstPeer = result.numberPerBurstPeer; 895 ans.status = result.status; //TODO(b/34901744) - don't assume identity translation 896 ans.retryAfterDuration = result.retryAfterDuration; 897 ans.measurementType = result.type; 898 ans.rssi = result.rssi; 899 ans.rssiSpread = result.rssiSpread; 900 //TODO(b/35138520) Fix HAL and framework to use the same units 901 ans.txRate = result.txRate.bitRateInKbps; 902 ans.rxRate = result.rxRate.bitRateInKbps; 903 ans.rtt = result.rtt; 904 ans.rttStandardDeviation = result.rttSd; 905 ans.rttSpread = result.rttSpread; 906 //TODO(b/35138520) These divide-by-10s were in the legacy Hal 907 ans.distance = result.distanceInMm / 10; // Convert cm to mm 908 ans.distanceStandardDeviation = result.distanceSdInMm / 10; // Convert cm to mm 909 ans.distanceSpread = result.distanceSpreadInMm / 10; 910 911 ans.ts = result.timeStampInUs; 912 ans.burstDuration = result.burstDurationInMs; 913 ans.negotiatedBurstNum = result.negotiatedBurstNum; 914 ans.LCI = ieFromHal(result.lci); 915 ans.LCR = ieFromHal(result.lcr); 916 ans.secure = false; // Not present in HIDL HAL 917 return ans; 918 } 919 920 /** 921 * Convert a Hal WifiInformationElement to its RttManager equivalent 922 */ 923 @VisibleForTesting 924 static RttManager.WifiInformationElement ieFromHal( 925 android.hardware.wifi.V1_0.WifiInformationElement ie) { 926 if (ie == null) return null; 927 RttManager.WifiInformationElement ans = new RttManager.WifiInformationElement(); 928 ans.id = ie.id; 929 ans.data = NativeUtil.byteArrayFromArrayList(ie.data); 930 return ans; 931 } 932 933 @VisibleForTesting 934 static RttConfig halRttConfigFromFrameworkRttParams(RttManager.RttParams params) { 935 RttConfig rttConfig = new RttConfig(); 936 if (params.bssid != null) { 937 byte[] addr = NativeUtil.macAddressToByteArray(params.bssid); 938 for (int i = 0; i < rttConfig.addr.length; i++) { 939 rttConfig.addr[i] = addr[i]; 940 } 941 } 942 rttConfig.type = halRttTypeFromFrameworkRttType(params.requestType); 943 rttConfig.peer = halPeerFromFrameworkPeer(params.deviceType); 944 rttConfig.channel.width = halChannelWidthFromFrameworkChannelWidth(params.channelWidth); 945 rttConfig.channel.centerFreq = params.frequency; 946 rttConfig.channel.centerFreq0 = params.centerFreq0; 947 rttConfig.channel.centerFreq1 = params.centerFreq1; 948 rttConfig.burstPeriod = params.interval; // In 100ms units, 0 means no specific 949 rttConfig.numBurst = params.numberBurst; 950 rttConfig.numFramesPerBurst = params.numSamplesPerBurst; 951 rttConfig.numRetriesPerRttFrame = params.numRetriesPerMeasurementFrame; 952 rttConfig.numRetriesPerFtmr = params.numRetriesPerFTMR; 953 rttConfig.mustRequestLci = params.LCIRequest; 954 rttConfig.mustRequestLcr = params.LCRRequest; 955 rttConfig.burstDuration = params.burstTimeout; 956 rttConfig.preamble = halPreambleFromFrameworkPreamble(params.preamble); 957 rttConfig.bw = halBwFromFrameworkBw(params.bandwidth); 958 return rttConfig; 959 } 960 961 @VisibleForTesting 962 static int halRttTypeFromFrameworkRttType(int frameworkRttType) { 963 switch (frameworkRttType) { 964 case RttManager.RTT_TYPE_ONE_SIDED: 965 return RttType.ONE_SIDED; 966 case RttManager.RTT_TYPE_TWO_SIDED: 967 return RttType.TWO_SIDED; 968 default: 969 throw new IllegalArgumentException("bad " + frameworkRttType); 970 } 971 } 972 973 @VisibleForTesting 974 static int frameworkRttTypeFromHalRttType(int halType) { 975 switch (halType) { 976 case RttType.ONE_SIDED: 977 return RttManager.RTT_TYPE_ONE_SIDED; 978 case RttType.TWO_SIDED: 979 return RttManager.RTT_TYPE_TWO_SIDED; 980 default: 981 throw new IllegalArgumentException("bad " + halType); 982 } 983 } 984 985 @VisibleForTesting 986 static int halPeerFromFrameworkPeer(int frameworkPeer) { 987 switch (frameworkPeer) { 988 case RttManager.RTT_PEER_TYPE_AP: 989 return RttPeerType.AP; 990 case RttManager.RTT_PEER_TYPE_STA: 991 return RttPeerType.STA; 992 case RttManager.RTT_PEER_P2P_GO: 993 return RttPeerType.P2P_GO; 994 case RttManager.RTT_PEER_P2P_CLIENT: 995 return RttPeerType.P2P_CLIENT; 996 case RttManager.RTT_PEER_NAN: 997 return RttPeerType.NAN; 998 default: 999 throw new IllegalArgumentException("bad " + frameworkPeer); 1000 } 1001 } 1002 1003 @VisibleForTesting 1004 static int frameworkPeerFromHalPeer(int halPeer) { 1005 switch (halPeer) { 1006 case RttPeerType.AP: 1007 return RttManager.RTT_PEER_TYPE_AP; 1008 case RttPeerType.STA: 1009 return RttManager.RTT_PEER_TYPE_STA; 1010 case RttPeerType.P2P_GO: 1011 return RttManager.RTT_PEER_P2P_GO; 1012 case RttPeerType.P2P_CLIENT: 1013 return RttManager.RTT_PEER_P2P_CLIENT; 1014 case RttPeerType.NAN: 1015 return RttManager.RTT_PEER_NAN; 1016 default: 1017 throw new IllegalArgumentException("bad " + halPeer); 1018 1019 } 1020 } 1021 1022 @VisibleForTesting 1023 static int halChannelWidthFromFrameworkChannelWidth(int frameworkChannelWidth) { 1024 switch (frameworkChannelWidth) { 1025 case ScanResult.CHANNEL_WIDTH_20MHZ: 1026 return WifiChannelWidthInMhz.WIDTH_20; 1027 case ScanResult.CHANNEL_WIDTH_40MHZ: 1028 return WifiChannelWidthInMhz.WIDTH_40; 1029 case ScanResult.CHANNEL_WIDTH_80MHZ: 1030 return WifiChannelWidthInMhz.WIDTH_80; 1031 case ScanResult.CHANNEL_WIDTH_160MHZ: 1032 return WifiChannelWidthInMhz.WIDTH_160; 1033 case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 1034 return WifiChannelWidthInMhz.WIDTH_80P80; 1035 default: 1036 throw new IllegalArgumentException("bad " + frameworkChannelWidth); 1037 } 1038 } 1039 1040 @VisibleForTesting 1041 static int frameworkChannelWidthFromHalChannelWidth(int halChannelWidth) { 1042 switch (halChannelWidth) { 1043 case WifiChannelWidthInMhz.WIDTH_20: 1044 return ScanResult.CHANNEL_WIDTH_20MHZ; 1045 case WifiChannelWidthInMhz.WIDTH_40: 1046 return ScanResult.CHANNEL_WIDTH_40MHZ; 1047 case WifiChannelWidthInMhz.WIDTH_80: 1048 return ScanResult.CHANNEL_WIDTH_80MHZ; 1049 case WifiChannelWidthInMhz.WIDTH_160: 1050 return ScanResult.CHANNEL_WIDTH_160MHZ; 1051 case WifiChannelWidthInMhz.WIDTH_80P80: 1052 return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; 1053 default: 1054 throw new IllegalArgumentException("bad " + halChannelWidth); 1055 } 1056 } 1057 1058 @VisibleForTesting 1059 static int halPreambleFromFrameworkPreamble(int rttManagerPreamble) { 1060 BitMask checkoff = new BitMask(rttManagerPreamble); 1061 int flags = 0; 1062 if (checkoff.testAndClear(RttManager.PREAMBLE_LEGACY)) { 1063 flags |= RttPreamble.LEGACY; 1064 } 1065 if (checkoff.testAndClear(RttManager.PREAMBLE_HT)) { 1066 flags |= RttPreamble.HT; 1067 } 1068 if (checkoff.testAndClear(RttManager.PREAMBLE_VHT)) { 1069 flags |= RttPreamble.VHT; 1070 } 1071 if (checkoff.value != 0) { 1072 throw new IllegalArgumentException("bad " + rttManagerPreamble); 1073 } 1074 return flags; 1075 } 1076 1077 @VisibleForTesting 1078 static int frameworkPreambleFromHalPreamble(int halPreamble) { 1079 BitMask checkoff = new BitMask(halPreamble); 1080 int flags = 0; 1081 if (checkoff.testAndClear(RttPreamble.LEGACY)) { 1082 flags |= RttManager.PREAMBLE_LEGACY; 1083 } 1084 if (checkoff.testAndClear(RttPreamble.HT)) { 1085 flags |= RttManager.PREAMBLE_HT; 1086 } 1087 if (checkoff.testAndClear(RttPreamble.VHT)) { 1088 flags |= RttManager.PREAMBLE_VHT; 1089 } 1090 if (checkoff.value != 0) { 1091 throw new IllegalArgumentException("bad " + halPreamble); 1092 } 1093 return flags; 1094 } 1095 1096 @VisibleForTesting 1097 static int halBwFromFrameworkBw(int rttManagerBandwidth) { 1098 BitMask checkoff = new BitMask(rttManagerBandwidth); 1099 int flags = 0; 1100 if (checkoff.testAndClear(RttManager.RTT_BW_5_SUPPORT)) { 1101 flags |= RttBw.BW_5MHZ; 1102 } 1103 if (checkoff.testAndClear(RttManager.RTT_BW_10_SUPPORT)) { 1104 flags |= RttBw.BW_10MHZ; 1105 } 1106 if (checkoff.testAndClear(RttManager.RTT_BW_20_SUPPORT)) { 1107 flags |= RttBw.BW_20MHZ; 1108 } 1109 if (checkoff.testAndClear(RttManager.RTT_BW_40_SUPPORT)) { 1110 flags |= RttBw.BW_40MHZ; 1111 } 1112 if (checkoff.testAndClear(RttManager.RTT_BW_80_SUPPORT)) { 1113 flags |= RttBw.BW_80MHZ; 1114 } 1115 if (checkoff.testAndClear(RttManager.RTT_BW_160_SUPPORT)) { 1116 flags |= RttBw.BW_160MHZ; 1117 } 1118 if (checkoff.value != 0) { 1119 throw new IllegalArgumentException("bad " + rttManagerBandwidth); 1120 } 1121 return flags; 1122 } 1123 1124 @VisibleForTesting 1125 static int frameworkBwFromHalBw(int rttBw) { 1126 BitMask checkoff = new BitMask(rttBw); 1127 int flags = 0; 1128 if (checkoff.testAndClear(RttBw.BW_5MHZ)) { 1129 flags |= RttManager.RTT_BW_5_SUPPORT; 1130 } 1131 if (checkoff.testAndClear(RttBw.BW_10MHZ)) { 1132 flags |= RttManager.RTT_BW_10_SUPPORT; 1133 } 1134 if (checkoff.testAndClear(RttBw.BW_20MHZ)) { 1135 flags |= RttManager.RTT_BW_20_SUPPORT; 1136 } 1137 if (checkoff.testAndClear(RttBw.BW_40MHZ)) { 1138 flags |= RttManager.RTT_BW_40_SUPPORT; 1139 } 1140 if (checkoff.testAndClear(RttBw.BW_80MHZ)) { 1141 flags |= RttManager.RTT_BW_80_SUPPORT; 1142 } 1143 if (checkoff.testAndClear(RttBw.BW_160MHZ)) { 1144 flags |= RttManager.RTT_BW_160_SUPPORT; 1145 } 1146 if (checkoff.value != 0) { 1147 throw new IllegalArgumentException("bad " + rttBw); 1148 } 1149 return flags; 1150 } 1151 1152 @VisibleForTesting 1153 static ArrayList<RttConfig> halRttConfigArrayFromFrameworkRttParamsArray( 1154 RttManager.RttParams[] params) { 1155 final int length = params.length; 1156 ArrayList<RttConfig> config = new ArrayList<RttConfig>(length); 1157 for (int i = 0; i < length; i++) { 1158 config.add(halRttConfigFromFrameworkRttParams(params[i])); 1159 } 1160 return config; 1161 } 1162 1163 /** 1164 * Starts a new rtt request 1165 * 1166 * @param params 1167 * @param handler 1168 * @return success indication 1169 */ 1170 public boolean requestRtt(RttManager.RttParams[] params, WifiNative.RttEventHandler handler) { 1171 ArrayList<RttConfig> rttConfigs = halRttConfigArrayFromFrameworkRttParamsArray(params); 1172 synchronized (sLock) { 1173 if (mIWifiRttController == null) return boolResult(false); 1174 if (mRttCmdId != 0) return boolResult(false); 1175 mRttCmdId = mRttCmdIdNext++; 1176 if (mRttCmdIdNext <= 0) mRttCmdIdNext = 1; 1177 try { 1178 mRttEventCallback = new RttEventCallback(mRttCmdId, handler); 1179 WifiStatus status = mIWifiRttController.rangeRequest(mRttCmdId, rttConfigs); 1180 if (ok(status)) { 1181 status = mIWifiRttController.registerEventCallback(mRttEventCallback); 1182 } 1183 if (ok(status)) return true; 1184 mRttCmdId = 0; 1185 return false; 1186 } catch (RemoteException e) { 1187 handleRemoteException(e); 1188 return false; 1189 } 1190 } 1191 } 1192 1193 /** 1194 * Cancels an outstanding rtt request 1195 * 1196 * @param params 1197 * @return true if there was an outstanding request and it was successfully cancelled 1198 */ 1199 public boolean cancelRtt(RttManager.RttParams[] params) { 1200 ArrayList<RttConfig> rttConfigs = halRttConfigArrayFromFrameworkRttParamsArray(params); 1201 synchronized (sLock) { 1202 if (mIWifiRttController == null) return boolResult(false); 1203 if (mRttCmdId == 0) return boolResult(false); 1204 ArrayList<byte[/* 6 */]> addrs = new ArrayList<byte[]>(rttConfigs.size()); 1205 for (RttConfig x : rttConfigs) addrs.add(x.addr); 1206 try { 1207 WifiStatus status = mIWifiRttController.rangeCancel(mRttCmdId, addrs); 1208 mRttCmdId = 0; 1209 if (!ok(status)) return false; 1210 return true; 1211 } catch (RemoteException e) { 1212 handleRemoteException(e); 1213 return false; 1214 } 1215 } 1216 } 1217 1218 private int mRttResponderCmdId = 0; 1219 1220 /** 1221 * Get RTT responder information e.g. WiFi channel to enable responder on. 1222 * 1223 * @return info Instance of |RttResponder|, or null for error. 1224 */ 1225 private RttResponder getRttResponder() { 1226 class AnswerBox { 1227 public RttResponder value = null; 1228 } 1229 synchronized (sLock) { 1230 if (mIWifiRttController == null) return null; 1231 AnswerBox answer = new AnswerBox(); 1232 try { 1233 mIWifiRttController.getResponderInfo((status, info) -> { 1234 if (!ok(status)) return; 1235 answer.value = info; 1236 }); 1237 return answer.value; 1238 } catch (RemoteException e) { 1239 handleRemoteException(e); 1240 return null; 1241 } 1242 } 1243 } 1244 1245 /** 1246 * Convert Hal RttResponder to a framework ResponderConfig 1247 * 1248 * @param info Instance of |RttResponder| 1249 * @return framework version of same 1250 */ 1251 private ResponderConfig frameworkResponderConfigFromHalRttResponder(RttResponder info) { 1252 ResponderConfig config = new ResponderConfig(); 1253 config.frequency = info.channel.centerFreq; 1254 config.centerFreq0 = info.channel.centerFreq0; 1255 config.centerFreq1 = info.channel.centerFreq1; 1256 config.channelWidth = frameworkChannelWidthFromHalChannelWidth(info.channel.width); 1257 config.preamble = frameworkPreambleFromHalPreamble(info.preamble); 1258 return config; 1259 } 1260 1261 /** 1262 * Enables RTT responder role on the device. 1263 * 1264 * @return {@link ResponderConfig} if the responder role is successfully enabled, 1265 * {@code null} otherwise. 1266 */ 1267 public ResponderConfig enableRttResponder(int timeoutSeconds) { 1268 RttResponder info = getRttResponder(); 1269 synchronized (sLock) { 1270 if (mIWifiRttController == null) return null; 1271 if (mRttResponderCmdId != 0) { 1272 mLog.e("responder mode already enabled - this shouldn't happen"); 1273 return null; 1274 } 1275 ResponderConfig config = null; 1276 int id = mRttCmdIdNext++; 1277 if (mRttCmdIdNext <= 0) mRttCmdIdNext = 1; 1278 try { 1279 WifiStatus status = mIWifiRttController.enableResponder( 1280 /* cmdId */id, 1281 /* WifiChannelInfo channelHint */null, 1282 timeoutSeconds, info); 1283 if (ok(status)) { 1284 mRttResponderCmdId = id; 1285 config = frameworkResponderConfigFromHalRttResponder(info); 1286 mVerboseLog.i("enabling rtt " + mRttResponderCmdId); 1287 } 1288 return config; 1289 } catch (RemoteException e) { 1290 handleRemoteException(e); 1291 return null; 1292 } 1293 } 1294 } 1295 1296 /** 1297 * Disables RTT responder role. 1298 * 1299 * @return {@code true} if responder role is successfully disabled, 1300 * {@code false} otherwise. 1301 */ 1302 public boolean disableRttResponder() { 1303 synchronized (sLock) { 1304 if (mIWifiRttController == null) return boolResult(false); 1305 if (mRttResponderCmdId == 0) return boolResult(false); 1306 try { 1307 WifiStatus status = mIWifiRttController.disableResponder(mRttResponderCmdId); 1308 mRttResponderCmdId = 0; 1309 if (!ok(status)) return false; 1310 return true; 1311 } catch (RemoteException e) { 1312 handleRemoteException(e); 1313 return false; 1314 } 1315 } 1316 } 1317 1318 /** 1319 * Set the MAC OUI during scanning. 1320 * <p> 1321 * An OUI {Organizationally Unique Identifier} is a 24-bit number that 1322 * uniquely identifies a vendor or manufacturer. 1323 * 1324 * @param oui 1325 * @return true for success 1326 */ 1327 public boolean setScanningMacOui(byte[] oui) { 1328 if (oui == null) return boolResult(false); 1329 if (oui.length != 3) return boolResult(false); 1330 synchronized (sLock) { 1331 try { 1332 if (mIWifiStaIface == null) return boolResult(false); 1333 WifiStatus status = mIWifiStaIface.setScanningMacOui(oui); 1334 if (!ok(status)) return false; 1335 return true; 1336 } catch (RemoteException e) { 1337 handleRemoteException(e); 1338 return false; 1339 } 1340 } 1341 } 1342 1343 /** 1344 * Query the list of valid frequencies for the provided band. 1345 * <p> 1346 * The result depends on the on the country code that has been set. 1347 * 1348 * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants. 1349 * @return frequencies vector of valid frequencies (MHz), or null for error. 1350 * @throws IllegalArgumentException if band is not recognized. 1351 */ 1352 public int[] getChannelsForBand(int band) { 1353 enter("%").c(band).flush(); 1354 class AnswerBox { 1355 public int[] value = null; 1356 } 1357 synchronized (sLock) { 1358 try { 1359 AnswerBox box = new AnswerBox(); 1360 int hb = makeWifiBandFromFrameworkBand(band); 1361 if (mIWifiStaIface != null) { 1362 mIWifiStaIface.getValidFrequenciesForBand(hb, (status, frequencies) -> { 1363 if (status.code == WifiStatusCode.ERROR_NOT_SUPPORTED) { 1364 mChannelsForBandSupport = false; 1365 } 1366 if (!ok(status)) return; 1367 mChannelsForBandSupport = true; 1368 box.value = intArrayFromArrayList(frequencies); 1369 }); 1370 } else if (mIWifiApIface != null) { 1371 mIWifiApIface.getValidFrequenciesForBand(hb, (status, frequencies) -> { 1372 if (status.code == WifiStatusCode.ERROR_NOT_SUPPORTED) { 1373 mChannelsForBandSupport = false; 1374 } 1375 if (!ok(status)) return; 1376 mChannelsForBandSupport = true; 1377 box.value = intArrayFromArrayList(frequencies); 1378 }); 1379 } 1380 return box.value; 1381 } catch (RemoteException e) { 1382 handleRemoteException(e); 1383 return null; 1384 } 1385 } 1386 } 1387 1388 private int[] intArrayFromArrayList(ArrayList<Integer> in) { 1389 int[] ans = new int[in.size()]; 1390 int i = 0; 1391 for (Integer e : in) ans[i++] = e; 1392 return ans; 1393 } 1394 1395 /** 1396 * This holder is null until we know whether or not there is frequency-for-band support. 1397 * <p> 1398 * Set as a side-effect of getChannelsForBand. 1399 */ 1400 @VisibleForTesting 1401 Boolean mChannelsForBandSupport = null; 1402 1403 /** 1404 * Indicates whether getChannelsForBand is supported. 1405 * 1406 * @return true if it is. 1407 */ 1408 public boolean isGetChannelsForBandSupported() { 1409 if (mChannelsForBandSupport != null) return mChannelsForBandSupport; 1410 getChannelsForBand(WifiBand.BAND_24GHZ); 1411 if (mChannelsForBandSupport != null) return mChannelsForBandSupport; 1412 return false; 1413 } 1414 1415 /** 1416 * Set DFS - actually, this is always on. 1417 * 1418 * @param dfsOn 1419 * @return success indication 1420 */ 1421 public boolean setDfsFlag(boolean dfsOn) { 1422 return dfsOn; 1423 } 1424 1425 /** 1426 * Get the APF (Android Packet Filter) capabilities of the device 1427 */ 1428 public ApfCapabilities getApfCapabilities() { 1429 class AnswerBox { 1430 public ApfCapabilities value = sNoApfCapabilities; 1431 } 1432 synchronized (sLock) { 1433 try { 1434 if (mIWifiStaIface == null) return sNoApfCapabilities; 1435 AnswerBox box = new AnswerBox(); 1436 mIWifiStaIface.getApfPacketFilterCapabilities((status, capabilities) -> { 1437 if (!ok(status)) return; 1438 box.value = new ApfCapabilities( 1439 /* apfVersionSupported */ capabilities.version, 1440 /* maximumApfProgramSize */ capabilities.maxLength, 1441 /* apfPacketFormat */ android.system.OsConstants.ARPHRD_ETHER); 1442 }); 1443 return box.value; 1444 } catch (RemoteException e) { 1445 handleRemoteException(e); 1446 return sNoApfCapabilities; 1447 } 1448 } 1449 } 1450 1451 private static final ApfCapabilities sNoApfCapabilities = new ApfCapabilities(0, 0, 0); 1452 1453 /** 1454 * Installs an APF program on this iface, replacing any existing program. 1455 * 1456 * @param filter is the android packet filter program 1457 * @return true for success 1458 */ 1459 public boolean installPacketFilter(byte[] filter) { 1460 int cmdId = 0; //TODO(b/34901818) We only aspire to support one program at a time 1461 if (filter == null) return boolResult(false); 1462 // Copy the program before taking the lock. 1463 ArrayList<Byte> program = NativeUtil.byteArrayToArrayList(filter); 1464 enter("filter length %").c(filter.length).flush(); 1465 synchronized (sLock) { 1466 try { 1467 if (mIWifiStaIface == null) return boolResult(false); 1468 WifiStatus status = mIWifiStaIface.installApfPacketFilter(cmdId, program); 1469 if (!ok(status)) return false; 1470 return true; 1471 } catch (RemoteException e) { 1472 handleRemoteException(e); 1473 return false; 1474 } 1475 } 1476 } 1477 1478 /** 1479 * Set country code for this AP iface. 1480 * 1481 * @param countryCode - two-letter country code (as ISO 3166) 1482 * @return true for success 1483 */ 1484 public boolean setCountryCodeHal(String countryCode) { 1485 if (countryCode == null) return boolResult(false); 1486 if (countryCode.length() != 2) return boolResult(false); 1487 byte[] code; 1488 try { 1489 code = NativeUtil.stringToByteArray(countryCode); 1490 } catch (IllegalArgumentException e) { 1491 return boolResult(false); 1492 } 1493 synchronized (sLock) { 1494 try { 1495 if (mIWifiApIface == null) return boolResult(false); 1496 WifiStatus status = mIWifiApIface.setCountryCode(code); 1497 if (!ok(status)) return false; 1498 return true; 1499 } catch (RemoteException e) { 1500 handleRemoteException(e); 1501 return false; 1502 } 1503 } 1504 } 1505 1506 private WifiNative.WifiLoggerEventHandler mVerboseLogEventHandler = null; 1507 1508 /** 1509 * Registers the logger callback and enables alerts. 1510 * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked. 1511 */ 1512 public boolean setLoggingEventHandler(WifiNative.WifiLoggerEventHandler handler) { 1513 if (handler == null) return boolResult(false); 1514 synchronized (sLock) { 1515 if (mIWifiChip == null) return boolResult(false); 1516 if (mVerboseLogEventHandler != null) return boolResult(false); 1517 try { 1518 WifiStatus status = mIWifiChip.enableDebugErrorAlerts(true); 1519 if (!ok(status)) return false; 1520 mVerboseLogEventHandler = handler; 1521 return true; 1522 } catch (RemoteException e) { 1523 handleRemoteException(e); 1524 return false; 1525 } 1526 } 1527 } 1528 1529 /** 1530 * Stops all logging and resets the logger callback. 1531 * This stops both the alerts and ring buffer data collection. 1532 */ 1533 public boolean resetLogHandler() { 1534 synchronized (sLock) { 1535 if (mIWifiChip == null) return boolResult(false); 1536 if (mVerboseLogEventHandler == null) return boolResult(false); 1537 try { 1538 WifiStatus status = mIWifiChip.enableDebugErrorAlerts(false); 1539 if (!ok(status)) return false; 1540 status = mIWifiChip.stopLoggingToDebugRingBuffer(); 1541 if (!ok(status)) return false; 1542 mVerboseLogEventHandler = null; 1543 return true; 1544 } catch (RemoteException e) { 1545 handleRemoteException(e); 1546 return false; 1547 } 1548 } 1549 } 1550 1551 /** 1552 * Control debug data collection 1553 * 1554 * @param verboseLevel 0 to 3, inclusive. 0 stops logging. 1555 * @param flags Ignored. 1556 * @param maxIntervalInSec Maximum interval between reports; ignore if 0. 1557 * @param minDataSizeInBytes Minimum data size in buffer for report; ignore if 0. 1558 * @param ringName Name of the ring for which data collection is to start. 1559 * @return true for success 1560 */ 1561 public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxIntervalInSec, 1562 int minDataSizeInBytes, String ringName) { 1563 enter("verboseLevel=%, flags=%, maxIntervalInSec=%, minDataSizeInBytes=%, ringName=%") 1564 .c(verboseLevel).c(flags).c(maxIntervalInSec).c(minDataSizeInBytes).c(ringName) 1565 .flush(); 1566 synchronized (sLock) { 1567 if (mIWifiChip == null) return boolResult(false); 1568 try { 1569 // note - flags are not used 1570 WifiStatus status = mIWifiChip.startLoggingToDebugRingBuffer( 1571 ringName, 1572 verboseLevel, 1573 maxIntervalInSec, 1574 minDataSizeInBytes 1575 ); 1576 return ok(status); 1577 } catch (RemoteException e) { 1578 handleRemoteException(e); 1579 return false; 1580 } 1581 } 1582 } 1583 1584 /** 1585 * Pointlessly fail 1586 * 1587 * @return -1 1588 */ 1589 public int getSupportedLoggerFeatureSet() { 1590 return -1; 1591 } 1592 1593 private String mDriverDescription; // Cached value filled by requestChipDebugInfo() 1594 1595 /** 1596 * Vendor-provided wifi driver version string 1597 */ 1598 public String getDriverVersion() { 1599 synchronized (sLock) { 1600 if (mDriverDescription == null) requestChipDebugInfo(); 1601 return mDriverDescription; 1602 } 1603 } 1604 1605 private String mFirmwareDescription; // Cached value filled by requestChipDebugInfo() 1606 1607 /** 1608 * Vendor-provided wifi firmware version string 1609 */ 1610 public String getFirmwareVersion() { 1611 synchronized (sLock) { 1612 if (mFirmwareDescription == null) requestChipDebugInfo(); 1613 return mFirmwareDescription; 1614 } 1615 } 1616 1617 /** 1618 * Refreshes our idea of the driver and firmware versions 1619 */ 1620 private void requestChipDebugInfo() { 1621 mDriverDescription = null; 1622 mFirmwareDescription = null; 1623 try { 1624 if (mIWifiChip == null) return; 1625 mIWifiChip.requestChipDebugInfo((status, chipDebugInfo) -> { 1626 if (!ok(status)) return; 1627 mDriverDescription = chipDebugInfo.driverDescription; 1628 mFirmwareDescription = chipDebugInfo.firmwareDescription; 1629 }); 1630 } catch (RemoteException e) { 1631 handleRemoteException(e); 1632 return; 1633 } 1634 mLog.info("Driver: % Firmware: %") 1635 .c(mDriverDescription) 1636 .c(mFirmwareDescription) 1637 .flush(); 1638 } 1639 1640 /** 1641 * Creates RingBufferStatus from the Hal version 1642 */ 1643 private static WifiNative.RingBufferStatus ringBufferStatus(WifiDebugRingBufferStatus h) { 1644 WifiNative.RingBufferStatus ans = new WifiNative.RingBufferStatus(); 1645 ans.name = h.ringName; 1646 ans.flag = frameworkRingBufferFlagsFromHal(h.flags); 1647 ans.ringBufferId = h.ringId; 1648 ans.ringBufferByteSize = h.sizeInBytes; 1649 ans.verboseLevel = h.verboseLevel; 1650 // Remaining fields are unavailable 1651 // writtenBytes; 1652 // readBytes; 1653 // writtenRecords; 1654 return ans; 1655 } 1656 1657 /** 1658 * Translates a hal wifiDebugRingBufferFlag to the WifiNative version 1659 */ 1660 private static int frameworkRingBufferFlagsFromHal(int wifiDebugRingBufferFlag) { 1661 BitMask checkoff = new BitMask(wifiDebugRingBufferFlag); 1662 int flags = 0; 1663 if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES)) { 1664 flags |= WifiNative.RingBufferStatus.HAS_BINARY_ENTRIES; 1665 } 1666 if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES)) { 1667 flags |= WifiNative.RingBufferStatus.HAS_ASCII_ENTRIES; 1668 } 1669 if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES)) { 1670 flags |= WifiNative.RingBufferStatus.HAS_PER_PACKET_ENTRIES; 1671 } 1672 if (checkoff.value != 0) { 1673 throw new IllegalArgumentException("Unknown WifiDebugRingBufferFlag " + checkoff.value); 1674 } 1675 return flags; 1676 } 1677 1678 /** 1679 * Creates array of RingBufferStatus from the Hal version 1680 */ 1681 private static WifiNative.RingBufferStatus[] makeRingBufferStatusArray( 1682 ArrayList<WifiDebugRingBufferStatus> ringBuffers) { 1683 WifiNative.RingBufferStatus[] ans = new WifiNative.RingBufferStatus[ringBuffers.size()]; 1684 int i = 0; 1685 for (WifiDebugRingBufferStatus b : ringBuffers) { 1686 ans[i++] = ringBufferStatus(b); 1687 } 1688 return ans; 1689 } 1690 1691 /** 1692 * API to get the status of all ring buffers supported by driver 1693 */ 1694 public WifiNative.RingBufferStatus[] getRingBufferStatus() { 1695 class AnswerBox { 1696 public WifiNative.RingBufferStatus[] value = null; 1697 } 1698 AnswerBox ans = new AnswerBox(); 1699 synchronized (sLock) { 1700 if (mIWifiChip == null) return null; 1701 try { 1702 mIWifiChip.getDebugRingBuffersStatus((status, ringBuffers) -> { 1703 if (!ok(status)) return; 1704 ans.value = makeRingBufferStatusArray(ringBuffers); 1705 }); 1706 } catch (RemoteException e) { 1707 handleRemoteException(e); 1708 return null; 1709 } 1710 } 1711 return ans.value; 1712 } 1713 1714 /** 1715 * Indicates to driver that all the data has to be uploaded urgently 1716 */ 1717 public boolean getRingBufferData(String ringName) { 1718 enter("ringName %").c(ringName).flush(); 1719 synchronized (sLock) { 1720 if (mIWifiChip == null) return boolResult(false); 1721 try { 1722 WifiStatus status = mIWifiChip.forceDumpToDebugRingBuffer(ringName); 1723 return ok(status); 1724 } catch (RemoteException e) { 1725 handleRemoteException(e); 1726 return false; 1727 } 1728 } 1729 } 1730 1731 /** 1732 * Request vendor debug info from the firmware 1733 */ 1734 public byte[] getFwMemoryDump() { 1735 class AnswerBox { 1736 public byte[] value; 1737 } 1738 AnswerBox ans = new AnswerBox(); 1739 synchronized (sLock) { 1740 if (mIWifiChip == null) return (null); 1741 try { 1742 mIWifiChip.requestFirmwareDebugDump((status, blob) -> { 1743 if (!ok(status)) return; 1744 ans.value = NativeUtil.byteArrayFromArrayList(blob); 1745 }); 1746 } catch (RemoteException e) { 1747 handleRemoteException(e); 1748 return null; 1749 } 1750 } 1751 return ans.value; 1752 } 1753 1754 /** 1755 * Request vendor debug info from the driver 1756 */ 1757 public byte[] getDriverStateDump() { 1758 class AnswerBox { 1759 public byte[] value; 1760 } 1761 AnswerBox ans = new AnswerBox(); 1762 synchronized (sLock) { 1763 if (mIWifiChip == null) return (null); 1764 try { 1765 mIWifiChip.requestDriverDebugDump((status, blob) -> { 1766 if (!ok(status)) return; 1767 ans.value = NativeUtil.byteArrayFromArrayList(blob); 1768 }); 1769 } catch (RemoteException e) { 1770 handleRemoteException(e); 1771 return null; 1772 } 1773 } 1774 return ans.value; 1775 } 1776 1777 /** 1778 * Start packet fate monitoring 1779 * <p> 1780 * Once started, monitoring remains active until HAL is unloaded. 1781 * 1782 * @return true for success 1783 */ 1784 public boolean startPktFateMonitoring() { 1785 synchronized (sLock) { 1786 if (mIWifiStaIface == null) return boolResult(false); 1787 try { 1788 WifiStatus status = mIWifiStaIface.startDebugPacketFateMonitoring(); 1789 return ok(status); 1790 } catch (RemoteException e) { 1791 handleRemoteException(e); 1792 return false; 1793 } 1794 } 1795 } 1796 1797 private byte halToFrameworkPktFateFrameType(int type) { 1798 switch (type) { 1799 case WifiDebugPacketFateFrameType.UNKNOWN: 1800 return WifiLoggerHal.FRAME_TYPE_UNKNOWN; 1801 case WifiDebugPacketFateFrameType.ETHERNET_II: 1802 return WifiLoggerHal.FRAME_TYPE_ETHERNET_II; 1803 case WifiDebugPacketFateFrameType.MGMT_80211: 1804 return WifiLoggerHal.FRAME_TYPE_80211_MGMT; 1805 default: 1806 throw new IllegalArgumentException("bad " + type); 1807 } 1808 } 1809 1810 private byte halToFrameworkRxPktFate(int type) { 1811 switch (type) { 1812 case WifiDebugRxPacketFate.SUCCESS: 1813 return WifiLoggerHal.RX_PKT_FATE_SUCCESS; 1814 case WifiDebugRxPacketFate.FW_QUEUED: 1815 return WifiLoggerHal.RX_PKT_FATE_FW_QUEUED; 1816 case WifiDebugRxPacketFate.FW_DROP_FILTER: 1817 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER; 1818 case WifiDebugRxPacketFate.FW_DROP_INVALID: 1819 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID; 1820 case WifiDebugRxPacketFate.FW_DROP_NOBUFS: 1821 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS; 1822 case WifiDebugRxPacketFate.FW_DROP_OTHER: 1823 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER; 1824 case WifiDebugRxPacketFate.DRV_QUEUED: 1825 return WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED; 1826 case WifiDebugRxPacketFate.DRV_DROP_FILTER: 1827 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER; 1828 case WifiDebugRxPacketFate.DRV_DROP_INVALID: 1829 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID; 1830 case WifiDebugRxPacketFate.DRV_DROP_NOBUFS: 1831 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS; 1832 case WifiDebugRxPacketFate.DRV_DROP_OTHER: 1833 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER; 1834 default: 1835 throw new IllegalArgumentException("bad " + type); 1836 } 1837 } 1838 1839 private byte halToFrameworkTxPktFate(int type) { 1840 switch (type) { 1841 case WifiDebugTxPacketFate.ACKED: 1842 return WifiLoggerHal.TX_PKT_FATE_ACKED; 1843 case WifiDebugTxPacketFate.SENT: 1844 return WifiLoggerHal.TX_PKT_FATE_SENT; 1845 case WifiDebugTxPacketFate.FW_QUEUED: 1846 return WifiLoggerHal.TX_PKT_FATE_FW_QUEUED; 1847 case WifiDebugTxPacketFate.FW_DROP_INVALID: 1848 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID; 1849 case WifiDebugTxPacketFate.FW_DROP_NOBUFS: 1850 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS; 1851 case WifiDebugTxPacketFate.FW_DROP_OTHER: 1852 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER; 1853 case WifiDebugTxPacketFate.DRV_QUEUED: 1854 return WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED; 1855 case WifiDebugTxPacketFate.DRV_DROP_INVALID: 1856 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID; 1857 case WifiDebugTxPacketFate.DRV_DROP_NOBUFS: 1858 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS; 1859 case WifiDebugTxPacketFate.DRV_DROP_OTHER: 1860 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER; 1861 default: 1862 throw new IllegalArgumentException("bad " + type); 1863 } 1864 } 1865 1866 /** 1867 * Retrieve fates of outbound packets 1868 * <p> 1869 * Reports the outbound frames for the most recent association (space allowing). 1870 * 1871 * @param reportBufs 1872 * @return true for success 1873 */ 1874 public boolean getTxPktFates(WifiNative.TxFateReport[] reportBufs) { 1875 if (ArrayUtils.isEmpty(reportBufs)) return boolResult(false); 1876 synchronized (sLock) { 1877 if (mIWifiStaIface == null) return boolResult(false); 1878 try { 1879 MutableBoolean ok = new MutableBoolean(false); 1880 mIWifiStaIface.getDebugTxPacketFates((status, fates) -> { 1881 if (!ok(status)) return; 1882 int i = 0; 1883 for (WifiDebugTxPacketFateReport fate : fates) { 1884 if (i >= reportBufs.length) break; 1885 byte code = halToFrameworkTxPktFate(fate.fate); 1886 long us = fate.frameInfo.driverTimestampUsec; 1887 byte type = 1888 halToFrameworkPktFateFrameType(fate.frameInfo.frameType); 1889 byte[] frame = 1890 NativeUtil.byteArrayFromArrayList( 1891 fate.frameInfo.frameContent); 1892 reportBufs[i++] = 1893 new WifiNative.TxFateReport(code, us, type, frame); 1894 } 1895 ok.value = true; 1896 } 1897 ); 1898 return ok.value; 1899 } catch (RemoteException e) { 1900 handleRemoteException(e); 1901 return false; 1902 } 1903 } 1904 } 1905 1906 /** 1907 * Retrieve fates of inbound packets 1908 * <p> 1909 * Reports the inbound frames for the most recent association (space allowing). 1910 * 1911 * @param reportBufs 1912 * @return true for success 1913 */ 1914 public boolean getRxPktFates(WifiNative.RxFateReport[] reportBufs) { 1915 if (ArrayUtils.isEmpty(reportBufs)) return boolResult(false); 1916 synchronized (sLock) { 1917 if (mIWifiStaIface == null) return boolResult(false); 1918 try { 1919 MutableBoolean ok = new MutableBoolean(false); 1920 mIWifiStaIface.getDebugRxPacketFates((status, fates) -> { 1921 if (!ok(status)) return; 1922 int i = 0; 1923 for (WifiDebugRxPacketFateReport fate : fates) { 1924 if (i >= reportBufs.length) break; 1925 byte code = halToFrameworkRxPktFate(fate.fate); 1926 long us = fate.frameInfo.driverTimestampUsec; 1927 byte type = 1928 halToFrameworkPktFateFrameType(fate.frameInfo.frameType); 1929 byte[] frame = 1930 NativeUtil.byteArrayFromArrayList( 1931 fate.frameInfo.frameContent); 1932 reportBufs[i++] = 1933 new WifiNative.RxFateReport(code, us, type, frame); 1934 } 1935 ok.value = true; 1936 } 1937 ); 1938 return ok.value; 1939 } catch (RemoteException e) { 1940 handleRemoteException(e); 1941 return false; 1942 } 1943 } 1944 } 1945 1946 /** 1947 * Start sending the specified keep alive packets periodically. 1948 * 1949 * @param slot 1950 * @param srcMac 1951 * @param keepAlivePacket 1952 * @param periodInMs 1953 * @return 0 for success, -1 for error 1954 */ 1955 public int startSendingOffloadedPacket( 1956 int slot, byte[] srcMac, KeepalivePacketData keepAlivePacket, int periodInMs) { 1957 enter("slot=% periodInMs=%").c(slot).c(periodInMs).flush(); 1958 1959 ArrayList<Byte> data = NativeUtil.byteArrayToArrayList(keepAlivePacket.data); 1960 short protocol = (short) (keepAlivePacket.protocol); 1961 1962 synchronized (sLock) { 1963 if (mIWifiStaIface == null) return -1; 1964 try { 1965 WifiStatus status = mIWifiStaIface.startSendingKeepAlivePackets( 1966 slot, 1967 data, 1968 protocol, 1969 srcMac, 1970 keepAlivePacket.dstMac, 1971 periodInMs); 1972 if (!ok(status)) return -1; 1973 return 0; 1974 } catch (RemoteException e) { 1975 handleRemoteException(e); 1976 return -1; 1977 } 1978 } 1979 } 1980 1981 /** 1982 * Stop sending the specified keep alive packets. 1983 * 1984 * @param slot id - same as startSendingOffloadedPacket call. 1985 * @return 0 for success, -1 for error 1986 */ 1987 public int stopSendingOffloadedPacket(int slot) { 1988 enter("slot=%").c(slot).flush(); 1989 1990 synchronized (sLock) { 1991 if (mIWifiStaIface == null) return -1; 1992 try { 1993 WifiStatus status = mIWifiStaIface.stopSendingKeepAlivePackets(slot); 1994 if (!ok(status)) return -1; 1995 return 0; 1996 } catch (RemoteException e) { 1997 handleRemoteException(e); 1998 return -1; 1999 } 2000 } 2001 } 2002 2003 /** 2004 * A fixed cmdId for our RssiMonitoring (we only do one at a time) 2005 */ 2006 @VisibleForTesting 2007 static final int sRssiMonCmdId = 7551; 2008 2009 /** 2010 * Our client's handler 2011 */ 2012 private WifiNative.WifiRssiEventHandler mWifiRssiEventHandler; 2013 2014 /** 2015 * Start RSSI monitoring on the currently connected access point. 2016 * 2017 * @param maxRssi Maximum RSSI threshold. 2018 * @param minRssi Minimum RSSI threshold. 2019 * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi 2020 * @return 0 for success, -1 for failure 2021 */ 2022 public int startRssiMonitoring(byte maxRssi, byte minRssi, 2023 WifiNative.WifiRssiEventHandler rssiEventHandler) { 2024 enter("maxRssi=% minRssi=%").c(maxRssi).c(minRssi).flush(); 2025 if (maxRssi <= minRssi) return -1; 2026 if (rssiEventHandler == null) return -1; 2027 synchronized (sLock) { 2028 if (mIWifiStaIface == null) return -1; 2029 try { 2030 mIWifiStaIface.stopRssiMonitoring(sRssiMonCmdId); 2031 WifiStatus status; 2032 status = mIWifiStaIface.startRssiMonitoring(sRssiMonCmdId, maxRssi, minRssi); 2033 if (!ok(status)) return -1; 2034 mWifiRssiEventHandler = rssiEventHandler; 2035 return 0; 2036 } catch (RemoteException e) { 2037 handleRemoteException(e); 2038 return -1; 2039 } 2040 } 2041 } 2042 2043 /** 2044 * Stop RSSI monitoring 2045 * 2046 * @return 0 for success, -1 for failure 2047 */ 2048 public int stopRssiMonitoring() { 2049 synchronized (sLock) { 2050 mWifiRssiEventHandler = null; 2051 if (mIWifiStaIface == null) return -1; 2052 try { 2053 mIWifiStaIface.stopRssiMonitoring(sRssiMonCmdId); 2054 WifiStatus status = mIWifiStaIface.stopRssiMonitoring(sRssiMonCmdId); 2055 if (!ok(status)) return -1; 2056 return 0; 2057 } catch (RemoteException e) { 2058 handleRemoteException(e); 2059 return -1; 2060 } 2061 } 2062 } 2063 2064 //TODO - belongs in NativeUtil 2065 private static int[] intsFromArrayList(ArrayList<Integer> a) { 2066 if (a == null) return null; 2067 int[] b = new int[a.size()]; 2068 int i = 0; 2069 for (Integer e : a) b[i++] = e; 2070 return b; 2071 } 2072 2073 /** 2074 * Translates from Hal version of wake reason stats to the framework version of same 2075 * 2076 * @param h - Hal version of wake reason stats 2077 * @return framework version of same 2078 */ 2079 private static WifiWakeReasonAndCounts halToFrameworkWakeReasons( 2080 WifiDebugHostWakeReasonStats h) { 2081 if (h == null) return null; 2082 WifiWakeReasonAndCounts ans = new WifiWakeReasonAndCounts(); 2083 ans.totalCmdEventWake = h.totalCmdEventWakeCnt; 2084 ans.totalDriverFwLocalWake = h.totalDriverFwLocalWakeCnt; 2085 ans.totalRxDataWake = h.totalRxPacketWakeCnt; 2086 ans.rxUnicast = h.rxPktWakeDetails.rxUnicastCnt; 2087 ans.rxMulticast = h.rxPktWakeDetails.rxMulticastCnt; 2088 ans.rxBroadcast = h.rxPktWakeDetails.rxBroadcastCnt; 2089 ans.icmp = h.rxIcmpPkWakeDetails.icmpPkt; 2090 ans.icmp6 = h.rxIcmpPkWakeDetails.icmp6Pkt; 2091 ans.icmp6Ra = h.rxIcmpPkWakeDetails.icmp6Ra; 2092 ans.icmp6Na = h.rxIcmpPkWakeDetails.icmp6Na; 2093 ans.icmp6Ns = h.rxIcmpPkWakeDetails.icmp6Ns; 2094 ans.ipv4RxMulticast = h.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt; 2095 ans.ipv6Multicast = h.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt; 2096 ans.otherRxMulticast = h.rxMulticastPkWakeDetails.otherRxMulticastAddrCnt; 2097 ans.cmdEventWakeCntArray = intsFromArrayList(h.cmdEventWakeCntPerType); 2098 ans.driverFWLocalWakeCntArray = intsFromArrayList(h.driverFwLocalWakeCntPerType); 2099 return ans; 2100 } 2101 2102 /** 2103 * Fetch the host wakeup reasons stats from wlan driver. 2104 * 2105 * @return the |WifiWakeReasonAndCounts| from the wlan driver, or null on failure. 2106 */ 2107 public WifiWakeReasonAndCounts getWlanWakeReasonCount() { 2108 class AnswerBox { 2109 public WifiDebugHostWakeReasonStats value = null; 2110 } 2111 AnswerBox ans = new AnswerBox(); 2112 synchronized (sLock) { 2113 if (mIWifiChip == null) return null; 2114 try { 2115 mIWifiChip.getDebugHostWakeReasonStats((status, stats) -> { 2116 if (ok(status)) { 2117 ans.value = stats; 2118 } 2119 }); 2120 return halToFrameworkWakeReasons(ans.value); 2121 } catch (RemoteException e) { 2122 handleRemoteException(e); 2123 return null; 2124 } 2125 } 2126 } 2127 2128 /** 2129 * Enable/Disable Neighbour discovery offload functionality in the firmware. 2130 * 2131 * @param enabled true to enable, false to disable. 2132 */ 2133 public boolean configureNeighborDiscoveryOffload(boolean enabled) { 2134 enter("enabled=%").c(enabled).flush(); 2135 synchronized (sLock) { 2136 if (mIWifiStaIface == null) return boolResult(false); 2137 try { 2138 WifiStatus status = mIWifiStaIface.enableNdOffload(enabled); 2139 if (!ok(status)) return false; 2140 } catch (RemoteException e) { 2141 handleRemoteException(e); 2142 return false; 2143 } 2144 } 2145 return true; 2146 } 2147 2148 // Firmware roaming control. 2149 2150 /** 2151 * Query the firmware roaming capabilities. 2152 * 2153 * @param capabilities object to be filled in 2154 * @return true for success; false for failure 2155 */ 2156 public boolean getRoamingCapabilities(WifiNative.RoamingCapabilities capabilities) { 2157 synchronized (sLock) { 2158 try { 2159 if (mIWifiStaIface == null) return boolResult(false); 2160 MutableBoolean ok = new MutableBoolean(false); 2161 WifiNative.RoamingCapabilities out = capabilities; 2162 mIWifiStaIface.getRoamingCapabilities((status, cap) -> { 2163 if (!ok(status)) return; 2164 out.maxBlacklistSize = cap.maxBlacklistSize; 2165 out.maxWhitelistSize = cap.maxWhitelistSize; 2166 ok.value = true; 2167 }); 2168 return ok.value; 2169 } catch (RemoteException e) { 2170 handleRemoteException(e); 2171 return false; 2172 } 2173 } 2174 } 2175 2176 /** 2177 * Enable/disable firmware roaming. 2178 * 2179 * @param state the intended roaming state 2180 * @return SUCCESS, FAILURE, or BUSY 2181 */ 2182 public int enableFirmwareRoaming(int state) { 2183 synchronized (sLock) { 2184 if (mIWifiStaIface == null) return WifiStatusCode.ERROR_NOT_STARTED; 2185 try { 2186 byte val; 2187 switch (state) { 2188 case WifiNative.DISABLE_FIRMWARE_ROAMING: 2189 val = StaRoamingState.DISABLED; 2190 break; 2191 case WifiNative.ENABLE_FIRMWARE_ROAMING: 2192 val = StaRoamingState.ENABLED; 2193 break; 2194 default: 2195 mLog.e("enableFirmwareRoaming invalid argument " + state); 2196 return WifiStatusCode.ERROR_INVALID_ARGS; 2197 } 2198 2199 WifiStatus status = mIWifiStaIface.setRoamingState(val); 2200 mVerboseLog.d("setRoamingState returned " + status.code); 2201 return status.code; 2202 } catch (RemoteException e) { 2203 handleRemoteException(e); 2204 return WifiStatusCode.ERROR_UNKNOWN; 2205 } 2206 } 2207 } 2208 2209 /** 2210 * Set firmware roaming configurations. 2211 * 2212 * @param config new roaming configuration object 2213 * @return true for success; false for failure 2214 */ 2215 public boolean configureRoaming(WifiNative.RoamingConfig config) { 2216 synchronized (sLock) { 2217 if (mIWifiStaIface == null) return boolResult(false); 2218 try { 2219 StaRoamingConfig roamingConfig = new StaRoamingConfig(); 2220 2221 // parse the blacklist BSSIDs if any 2222 if (config.blacklistBssids != null) { 2223 for (String bssid : config.blacklistBssids) { 2224 byte[] mac = NativeUtil.macAddressToByteArray(bssid); 2225 roamingConfig.bssidBlacklist.add(mac); 2226 } 2227 } 2228 2229 // parse the whitelist SSIDs if any 2230 if (config.whitelistSsids != null) { 2231 for (String ssidStr : config.whitelistSsids) { 2232 String unquotedSsidStr = WifiInfo.removeDoubleQuotes(ssidStr); 2233 2234 int len = unquotedSsidStr.length(); 2235 if (len > 32) { 2236 mLog.err("configureRoaming: skip invalid SSID %") 2237 .r(unquotedSsidStr).flush(); 2238 continue; 2239 } 2240 byte[] ssid = new byte[len]; 2241 for (int i = 0; i < len; i++) { 2242 ssid[i] = (byte) unquotedSsidStr.charAt(i); 2243 } 2244 roamingConfig.ssidWhitelist.add(ssid); 2245 } 2246 } 2247 2248 WifiStatus status = mIWifiStaIface.configureRoaming(roamingConfig); 2249 if (!ok(status)) return false; 2250 } catch (RemoteException e) { 2251 handleRemoteException(e); 2252 return false; 2253 } 2254 return true; 2255 } 2256 } 2257 2258 // This creates a blob of IE elements from the array received. 2259 // TODO: This ugly conversion can be removed if we put IE elements in ScanResult. 2260 private static byte[] hidlIeArrayToFrameworkIeBlob(ArrayList<WifiInformationElement> ies) { 2261 if (ies == null || ies.isEmpty()) return new byte[0]; 2262 ArrayList<Byte> ieBlob = new ArrayList<>(); 2263 for (WifiInformationElement ie : ies) { 2264 ieBlob.add(ie.id); 2265 ieBlob.addAll(ie.data); 2266 } 2267 return NativeUtil.byteArrayFromArrayList(ieBlob); 2268 } 2269 2270 // This is only filling up the fields of Scan Result used by Gscan clients. 2271 private static ScanResult hidlToFrameworkScanResult(StaScanResult scanResult) { 2272 if (scanResult == null) return null; 2273 ScanResult frameworkScanResult = new ScanResult(); 2274 frameworkScanResult.SSID = NativeUtil.encodeSsid(scanResult.ssid); 2275 frameworkScanResult.wifiSsid = 2276 WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(scanResult.ssid)); 2277 frameworkScanResult.BSSID = NativeUtil.macAddressFromByteArray(scanResult.bssid); 2278 frameworkScanResult.level = scanResult.rssi; 2279 frameworkScanResult.frequency = scanResult.frequency; 2280 frameworkScanResult.timestamp = scanResult.timeStampInUs; 2281 frameworkScanResult.bytes = hidlIeArrayToFrameworkIeBlob(scanResult.informationElements); 2282 return frameworkScanResult; 2283 } 2284 2285 private static ScanResult[] hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults) { 2286 if (scanResults == null || scanResults.isEmpty()) return new ScanResult[0]; 2287 ScanResult[] frameworkScanResults = new ScanResult[scanResults.size()]; 2288 int i = 0; 2289 for (StaScanResult scanResult : scanResults) { 2290 frameworkScanResults[i++] = hidlToFrameworkScanResult(scanResult); 2291 } 2292 return frameworkScanResults; 2293 } 2294 2295 /** 2296 * This just returns whether the scan was interrupted or not. 2297 */ 2298 private static int hidlToFrameworkScanDataFlags(int flag) { 2299 if (flag == StaScanDataFlagMask.INTERRUPTED) { 2300 return 1; 2301 } else { 2302 return 0; 2303 } 2304 } 2305 2306 private static WifiScanner.ScanData[] hidlToFrameworkScanDatas( 2307 int cmdId, ArrayList<StaScanData> scanDatas) { 2308 if (scanDatas == null || scanDatas.isEmpty()) return new WifiScanner.ScanData[0]; 2309 WifiScanner.ScanData[] frameworkScanDatas = new WifiScanner.ScanData[scanDatas.size()]; 2310 int i = 0; 2311 for (StaScanData scanData : scanDatas) { 2312 int flags = hidlToFrameworkScanDataFlags(scanData.flags); 2313 ScanResult[] frameworkScanResults = hidlToFrameworkScanResults(scanData.results); 2314 frameworkScanDatas[i++] = 2315 new WifiScanner.ScanData(cmdId, flags, scanData.bucketsScanned, false, 2316 frameworkScanResults); 2317 } 2318 return frameworkScanDatas; 2319 } 2320 2321 /** 2322 * Callback for events on the STA interface. 2323 */ 2324 private class StaIfaceEventCallback extends IWifiStaIfaceEventCallback.Stub { 2325 @Override 2326 public void onBackgroundScanFailure(int cmdId) { 2327 mVerboseLog.d("onBackgroundScanFailure " + cmdId); 2328 WifiNative.ScanEventHandler eventHandler; 2329 synchronized (sLock) { 2330 if (mScan == null || cmdId != mScan.cmdId) return; 2331 eventHandler = mScan.eventHandler; 2332 } 2333 eventHandler.onScanStatus(WifiNative.WIFI_SCAN_FAILED); 2334 } 2335 2336 @Override 2337 public void onBackgroundFullScanResult( 2338 int cmdId, int bucketsScanned, StaScanResult result) { 2339 mVerboseLog.d("onBackgroundFullScanResult " + cmdId); 2340 WifiNative.ScanEventHandler eventHandler; 2341 synchronized (sLock) { 2342 if (mScan == null || cmdId != mScan.cmdId) return; 2343 eventHandler = mScan.eventHandler; 2344 } 2345 eventHandler.onFullScanResult(hidlToFrameworkScanResult(result), bucketsScanned); 2346 } 2347 2348 @Override 2349 public void onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas) { 2350 mVerboseLog.d("onBackgroundScanResults " + cmdId); 2351 WifiNative.ScanEventHandler eventHandler; 2352 // WifiScanner currently uses the results callback to fetch the scan results. 2353 // So, simulate that by sending out the notification and then caching the results 2354 // locally. This will then be returned to WifiScanner via getScanResults. 2355 synchronized (sLock) { 2356 if (mScan == null || cmdId != mScan.cmdId) return; 2357 eventHandler = mScan.eventHandler; 2358 mScan.latestScanResults = hidlToFrameworkScanDatas(cmdId, scanDatas); 2359 } 2360 eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); 2361 } 2362 2363 @Override 2364 public void onRssiThresholdBreached(int cmdId, byte[/* 6 */] currBssid, int currRssi) { 2365 mVerboseLog.d("onRssiThresholdBreached " + cmdId + "currRssi " + currRssi); 2366 WifiNative.WifiRssiEventHandler eventHandler; 2367 synchronized (sLock) { 2368 if (mWifiRssiEventHandler == null || cmdId != sRssiMonCmdId) return; 2369 eventHandler = mWifiRssiEventHandler; 2370 } 2371 eventHandler.onRssiThresholdBreached((byte) currRssi); 2372 } 2373 } 2374 2375 /** 2376 * Callback for events on the STA interface. 2377 */ 2378 private class ChipEventCallback extends IWifiChipEventCallback.Stub { 2379 @Override 2380 public void onChipReconfigured(int modeId) { 2381 mVerboseLog.d("onChipReconfigured " + modeId); 2382 } 2383 2384 @Override 2385 public void onChipReconfigureFailure(WifiStatus status) { 2386 mVerboseLog.d("onChipReconfigureFailure " + status); 2387 } 2388 2389 public void onIfaceAdded(int type, String name) { 2390 mVerboseLog.d("onIfaceAdded " + type + ", name: " + name); 2391 } 2392 2393 @Override 2394 public void onIfaceRemoved(int type, String name) { 2395 mVerboseLog.d("onIfaceRemoved " + type + ", name: " + name); 2396 } 2397 2398 @Override 2399 public void onDebugRingBufferDataAvailable( 2400 WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { 2401 //TODO(b/35875078) Reinstate logging when execessive callbacks are fixed 2402 // mVerboseLog.d("onDebugRingBufferDataAvailable " + status); 2403 WifiNative.WifiLoggerEventHandler eventHandler; 2404 synchronized (sLock) { 2405 if (mVerboseLogEventHandler == null || status == null || data == null) return; 2406 eventHandler = mVerboseLogEventHandler; 2407 } 2408 eventHandler.onRingBufferData( 2409 ringBufferStatus(status), NativeUtil.byteArrayFromArrayList(data)); 2410 } 2411 2412 @Override 2413 public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { 2414 mVerboseLog.d("onDebugErrorAlert " + errorCode); 2415 WifiNative.WifiLoggerEventHandler eventHandler; 2416 synchronized (sLock) { 2417 if (mVerboseLogEventHandler == null || debugData == null) return; 2418 eventHandler = mVerboseLogEventHandler; 2419 } 2420 eventHandler.onWifiAlert( 2421 errorCode, NativeUtil.byteArrayFromArrayList(debugData)); 2422 } 2423 } 2424 2425 /** 2426 * Hal Device Manager callbacks. 2427 */ 2428 public class HalDeviceManagerStatusListener implements HalDeviceManager.ManagerStatusListener { 2429 @Override 2430 public void onStatusChanged() { 2431 boolean isReady = mHalDeviceManager.isReady(); 2432 boolean isStarted = mHalDeviceManager.isStarted(); 2433 2434 mVerboseLog.i("Device Manager onStatusChanged. isReady(): " + isReady 2435 + ", isStarted(): " + isStarted); 2436 // Reset all our cached handles. 2437 // TODO(b/33384303) it could be dicey not having this grab the lock 2438 if (!isReady || !isStarted) { 2439 mIWifiChip = null; 2440 mIWifiStaIface = null; 2441 mIWifiApIface = null; 2442 mIWifiRttController = null; 2443 mDriverDescription = null; 2444 mFirmwareDescription = null; 2445 // TODO(b/33384303) likely other things to clear out 2446 } 2447 } 2448 } 2449} 2450