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