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