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