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 */ enableVerboseLogging(boolean verbose)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 */ ok(WifiStatus status)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 */ boolResult(boolean result)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 */ enter(String format)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 */ niceMethodName(StackTraceElement[] trace, int start)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 WifiVendorHal(HalDeviceManager halDeviceManager, Looper looper)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 handleRemoteException(RemoteException e)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 */ initialize(WifiNative.VendorHalDeathEventHandler handler)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 */ isVendorHalSupported()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 */ startVendorHalAp()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 */ startVendorHalSta()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 */ startVendorHal(boolean isStaMode)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 */ startFailedTo(String message)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 */ registerStaIfaceCallback()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 */ registerChipCallback()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 */ registerRttEventCallback()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 */ stopVendorHal()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 */ clearState()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 */ isHalStarted()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 */ getBgScanCapabilities(WifiNative.ScanCapabilities capabilities)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 CurrentBackgroundScan(int id, WifiNative.ScanSettings settings)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 makeStaBackgroundScanBucketParametersFromBucketSettings(WifiNative.BucketSettings bs)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 */ makeWifiBandFromFrameworkBand(int frameworkBand)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 */ makeReportSchemeFromBucketSettingsReportEvents(int reportUnderscoreEvents)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 */ startBgScan(WifiNative.ScanSettings settings, WifiNative.ScanEventHandler eventHandler)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 */ stopBgScan()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 */ pauseBgScan()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 */ restartBgScan()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 */ getBgScanResults()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 */ getWifiLinkLayerStats()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 frameworkFromHalLinkLayerStats(StaLinkLayerStats stats)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 */ enableLinkLayerStats()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 IWifiChip caps 782 */ 783 private static final int[][] sChipFeatureCapabilityTranslation = { 784 {WifiManager.WIFI_FEATURE_TX_POWER_LIMIT, 785 android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT 786 }, 787 {WifiManager.WIFI_FEATURE_D2D_RTT, 788 android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT 789 }, 790 {WifiManager.WIFI_FEATURE_D2AP_RTT, 791 android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT 792 } 793 }; 794 795 /** 796 * Feature bit mask translation for Chip 797 * 798 * @param capabilities bitmask defined IWifiChip.ChipCapabilityMask 799 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 800 */ 801 @VisibleForTesting wifiFeatureMaskFromChipCapabilities(int capabilities)802 int wifiFeatureMaskFromChipCapabilities(int capabilities) { 803 int features = 0; 804 for (int i = 0; i < sChipFeatureCapabilityTranslation.length; i++) { 805 if ((capabilities & sChipFeatureCapabilityTranslation[i][1]) != 0) { 806 features |= sChipFeatureCapabilityTranslation[i][0]; 807 } 808 } 809 return features; 810 } 811 812 /** 813 * Translation table used by getSupportedFeatureSet for translating IWifiStaIface caps 814 */ 815 private static final int[][] sStaFeatureCapabilityTranslation = { 816 {WifiManager.WIFI_FEATURE_INFRA_5G, 817 IWifiStaIface.StaIfaceCapabilityMask.STA_5G 818 }, 819 {WifiManager.WIFI_FEATURE_PASSPOINT, 820 IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT 821 }, 822 {WifiManager.WIFI_FEATURE_SCANNER, 823 IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN, 824 }, 825 {WifiManager.WIFI_FEATURE_PNO, 826 IWifiStaIface.StaIfaceCapabilityMask.PNO 827 }, 828 {WifiManager.WIFI_FEATURE_TDLS, 829 IWifiStaIface.StaIfaceCapabilityMask.TDLS 830 }, 831 {WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL, 832 IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL 833 }, 834 {WifiManager.WIFI_FEATURE_LINK_LAYER_STATS, 835 IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS 836 }, 837 {WifiManager.WIFI_FEATURE_RSSI_MONITOR, 838 IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR 839 }, 840 {WifiManager.WIFI_FEATURE_MKEEP_ALIVE, 841 IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE 842 }, 843 {WifiManager.WIFI_FEATURE_CONFIG_NDO, 844 IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD 845 }, 846 {WifiManager.WIFI_FEATURE_CONTROL_ROAMING, 847 IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING 848 }, 849 {WifiManager.WIFI_FEATURE_IE_WHITELIST, 850 IWifiStaIface.StaIfaceCapabilityMask.PROBE_IE_WHITELIST 851 }, 852 {WifiManager.WIFI_FEATURE_SCAN_RAND, 853 IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND 854 }, 855 }; 856 857 /** 858 * Feature bit mask translation for STAs 859 * 860 * @param capabilities bitmask defined IWifiStaIface.StaIfaceCapabilityMask 861 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 862 */ 863 @VisibleForTesting wifiFeatureMaskFromStaCapabilities(int capabilities)864 int wifiFeatureMaskFromStaCapabilities(int capabilities) { 865 int features = 0; 866 for (int i = 0; i < sStaFeatureCapabilityTranslation.length; i++) { 867 if ((capabilities & sStaFeatureCapabilityTranslation[i][1]) != 0) { 868 features |= sStaFeatureCapabilityTranslation[i][0]; 869 } 870 } 871 return features; 872 } 873 874 /** 875 * Get the supported features 876 * 877 * The result may differ depending on the mode (STA or AP) 878 * 879 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 880 */ getSupportedFeatureSet()881 public int getSupportedFeatureSet() { 882 int featureSet = 0; 883 if (!mHalDeviceManager.isStarted()) { 884 return featureSet; // TODO: can't get capabilities with Wi-Fi down 885 } 886 try { 887 final MutableInt feat = new MutableInt(0); 888 synchronized (sLock) { 889 if (mIWifiChip != null) { 890 mIWifiChip.getCapabilities((status, capabilities) -> { 891 if (!ok(status)) return; 892 feat.value = wifiFeatureMaskFromChipCapabilities(capabilities); 893 }); 894 } 895 if (mIWifiStaIface != null) { 896 mIWifiStaIface.getCapabilities((status, capabilities) -> { 897 if (!ok(status)) return; 898 feat.value |= wifiFeatureMaskFromStaCapabilities(capabilities); 899 }); 900 } 901 } 902 featureSet = feat.value; 903 } catch (RemoteException e) { 904 handleRemoteException(e); 905 return 0; 906 } 907 908 Set<Integer> supportedIfaceTypes = mHalDeviceManager.getSupportedIfaceTypes(); 909 if (supportedIfaceTypes.contains(IfaceType.STA)) { 910 featureSet |= WifiManager.WIFI_FEATURE_INFRA; 911 } 912 if (supportedIfaceTypes.contains(IfaceType.AP)) { 913 featureSet |= WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT; 914 } 915 if (supportedIfaceTypes.contains(IfaceType.P2P)) { 916 featureSet |= WifiManager.WIFI_FEATURE_P2P; 917 } 918 if (supportedIfaceTypes.contains(IfaceType.NAN)) { 919 featureSet |= WifiManager.WIFI_FEATURE_AWARE; 920 } 921 922 return featureSet; 923 } 924 925 /* RTT related commands/events */ 926 927 /** 928 * RTT (Round Trip Time) measurement capabilities of the device. 929 */ getRttCapabilities()930 public RttManager.RttCapabilities getRttCapabilities() { 931 class AnswerBox { 932 public RttManager.RttCapabilities value = null; 933 } 934 synchronized (sLock) { 935 if (mIWifiRttController == null) return null; 936 try { 937 AnswerBox box = new AnswerBox(); 938 mIWifiRttController.getCapabilities((status, capabilities) -> { 939 if (!ok(status)) return; 940 mVerboseLog.info("rtt capabilites %").c(capabilities.toString()).flush(); 941 RttManager.RttCapabilities ans = new RttManager.RttCapabilities(); 942 ans.oneSidedRttSupported = capabilities.rttOneSidedSupported; 943 ans.twoSided11McRttSupported = capabilities.rttFtmSupported; 944 ans.lciSupported = capabilities.lciSupported; 945 ans.lcrSupported = capabilities.lcrSupported; 946 ans.preambleSupported = frameworkPreambleFromHalPreamble( 947 capabilities.preambleSupport); 948 ans.bwSupported = frameworkBwFromHalBw(capabilities.bwSupport); 949 ans.responderSupported = capabilities.responderSupported; 950 ans.secureRttSupported = false; 951 ans.mcVersion = ((int) capabilities.mcVersion) & 0xff; 952 box.value = ans; 953 }); 954 return box.value; 955 } catch (RemoteException e) { 956 handleRemoteException(e); 957 return null; 958 } 959 } 960 } 961 962 private int mRttCmdIdNext = 1; // used to generate new command ids 963 private int mRttCmdId; // id of currently active request 964 // Event handler for current active RTT request. 965 private WifiNative.RttEventHandler mRttEventHandler; 966 967 /** 968 * Receives a callback from the Hal and passes it along to our client using RttEventHandler 969 */ 970 private class RttEventCallback extends IWifiRttControllerEventCallback.Stub { 971 972 @Override onResults(int cmdId, java.util.ArrayList<RttResult> results)973 public void onResults(int cmdId, java.util.ArrayList<RttResult> results) { 974 WifiNative.RttEventHandler eventHandler; 975 synchronized (sLock) { 976 if (cmdId != mRttCmdId || mRttEventHandler == null) return; 977 eventHandler = mRttEventHandler; 978 // Reset the command id for RTT operations in WifiVendorHal. 979 WifiVendorHal.this.mRttCmdId = 0; 980 } 981 RttManager.RttResult[] rtt = new RttManager.RttResult[results.size()]; 982 for (int i = 0; i < rtt.length; i++) { 983 rtt[i] = frameworkRttResultFromHalRttResult(results.get(i)); 984 } 985 eventHandler.onRttResults(rtt); 986 } 987 } 988 989 /** 990 * Converts a Hal RttResult to a RttManager.RttResult 991 */ 992 @VisibleForTesting frameworkRttResultFromHalRttResult(RttResult result)993 static RttManager.RttResult frameworkRttResultFromHalRttResult(RttResult result) { 994 RttManager.RttResult ans = new RttManager.RttResult(); 995 ans.bssid = NativeUtil.macAddressFromByteArray(result.addr); 996 ans.burstNumber = result.burstNum; 997 ans.measurementFrameNumber = result.measurementNumber; 998 ans.successMeasurementFrameNumber = result.successNumber; 999 ans.frameNumberPerBurstPeer = result.numberPerBurstPeer; 1000 ans.status = result.status; //TODO(b/35138520) - don't assume identity translation 1001 ans.retryAfterDuration = result.retryAfterDuration; 1002 ans.measurementType = result.type; 1003 ans.rssi = result.rssi; 1004 ans.rssiSpread = result.rssiSpread; 1005 //TODO(b/35138520) Fix HAL and framework to use the same units 1006 ans.txRate = result.txRate.bitRateInKbps; 1007 ans.rxRate = result.rxRate.bitRateInKbps; 1008 ans.rtt = result.rtt; 1009 ans.rttStandardDeviation = result.rttSd; 1010 ans.rttSpread = result.rttSpread; 1011 //TODO(b/35138520) These divide-by-10s were in the legacy Hal 1012 ans.distance = result.distanceInMm / 10; // Convert cm to mm 1013 ans.distanceStandardDeviation = result.distanceSdInMm / 10; // Convert cm to mm 1014 ans.distanceSpread = result.distanceSpreadInMm / 10; 1015 1016 ans.ts = result.timeStampInUs; 1017 ans.burstDuration = result.burstDurationInMs; 1018 ans.negotiatedBurstNum = result.negotiatedBurstNum; 1019 ans.LCI = ieFromHal(result.lci); 1020 ans.LCR = ieFromHal(result.lcr); 1021 ans.secure = false; // Not present in HIDL HAL 1022 return ans; 1023 } 1024 1025 /** 1026 * Convert a Hal WifiInformationElement to its RttManager equivalent 1027 */ 1028 @VisibleForTesting ieFromHal( android.hardware.wifi.V1_0.WifiInformationElement ie)1029 static RttManager.WifiInformationElement ieFromHal( 1030 android.hardware.wifi.V1_0.WifiInformationElement ie) { 1031 if (ie == null) return null; 1032 RttManager.WifiInformationElement ans = new RttManager.WifiInformationElement(); 1033 ans.id = ie.id; 1034 ans.data = NativeUtil.byteArrayFromArrayList(ie.data); 1035 return ans; 1036 } 1037 1038 @VisibleForTesting halRttConfigFromFrameworkRttParams(RttManager.RttParams params)1039 static RttConfig halRttConfigFromFrameworkRttParams(RttManager.RttParams params) { 1040 RttConfig rttConfig = new RttConfig(); 1041 if (params.bssid != null) { 1042 byte[] addr = NativeUtil.macAddressToByteArray(params.bssid); 1043 for (int i = 0; i < rttConfig.addr.length; i++) { 1044 rttConfig.addr[i] = addr[i]; 1045 } 1046 } 1047 rttConfig.type = halRttTypeFromFrameworkRttType(params.requestType); 1048 rttConfig.peer = halPeerFromFrameworkPeer(params.deviceType); 1049 rttConfig.channel.width = halChannelWidthFromFrameworkChannelWidth(params.channelWidth); 1050 rttConfig.channel.centerFreq = params.frequency; 1051 rttConfig.channel.centerFreq0 = params.centerFreq0; 1052 rttConfig.channel.centerFreq1 = params.centerFreq1; 1053 rttConfig.burstPeriod = params.interval; // In 100ms units, 0 means no specific 1054 rttConfig.numBurst = params.numberBurst; 1055 rttConfig.numFramesPerBurst = params.numSamplesPerBurst; 1056 rttConfig.numRetriesPerRttFrame = params.numRetriesPerMeasurementFrame; 1057 rttConfig.numRetriesPerFtmr = params.numRetriesPerFTMR; 1058 rttConfig.mustRequestLci = params.LCIRequest; 1059 rttConfig.mustRequestLcr = params.LCRRequest; 1060 rttConfig.burstDuration = params.burstTimeout; 1061 rttConfig.preamble = halPreambleFromFrameworkPreamble(params.preamble); 1062 rttConfig.bw = halBwFromFrameworkBw(params.bandwidth); 1063 return rttConfig; 1064 } 1065 1066 @VisibleForTesting halRttTypeFromFrameworkRttType(int frameworkRttType)1067 static int halRttTypeFromFrameworkRttType(int frameworkRttType) { 1068 switch (frameworkRttType) { 1069 case RttManager.RTT_TYPE_ONE_SIDED: 1070 return RttType.ONE_SIDED; 1071 case RttManager.RTT_TYPE_TWO_SIDED: 1072 return RttType.TWO_SIDED; 1073 default: 1074 throw new IllegalArgumentException("bad " + frameworkRttType); 1075 } 1076 } 1077 1078 @VisibleForTesting frameworkRttTypeFromHalRttType(int halType)1079 static int frameworkRttTypeFromHalRttType(int halType) { 1080 switch (halType) { 1081 case RttType.ONE_SIDED: 1082 return RttManager.RTT_TYPE_ONE_SIDED; 1083 case RttType.TWO_SIDED: 1084 return RttManager.RTT_TYPE_TWO_SIDED; 1085 default: 1086 throw new IllegalArgumentException("bad " + halType); 1087 } 1088 } 1089 1090 @VisibleForTesting halPeerFromFrameworkPeer(int frameworkPeer)1091 static int halPeerFromFrameworkPeer(int frameworkPeer) { 1092 switch (frameworkPeer) { 1093 case RttManager.RTT_PEER_TYPE_AP: 1094 return RttPeerType.AP; 1095 case RttManager.RTT_PEER_TYPE_STA: 1096 return RttPeerType.STA; 1097 case RttManager.RTT_PEER_P2P_GO: 1098 return RttPeerType.P2P_GO; 1099 case RttManager.RTT_PEER_P2P_CLIENT: 1100 return RttPeerType.P2P_CLIENT; 1101 case RttManager.RTT_PEER_NAN: 1102 return RttPeerType.NAN; 1103 default: 1104 throw new IllegalArgumentException("bad " + frameworkPeer); 1105 } 1106 } 1107 1108 @VisibleForTesting frameworkPeerFromHalPeer(int halPeer)1109 static int frameworkPeerFromHalPeer(int halPeer) { 1110 switch (halPeer) { 1111 case RttPeerType.AP: 1112 return RttManager.RTT_PEER_TYPE_AP; 1113 case RttPeerType.STA: 1114 return RttManager.RTT_PEER_TYPE_STA; 1115 case RttPeerType.P2P_GO: 1116 return RttManager.RTT_PEER_P2P_GO; 1117 case RttPeerType.P2P_CLIENT: 1118 return RttManager.RTT_PEER_P2P_CLIENT; 1119 case RttPeerType.NAN: 1120 return RttManager.RTT_PEER_NAN; 1121 default: 1122 throw new IllegalArgumentException("bad " + halPeer); 1123 1124 } 1125 } 1126 1127 @VisibleForTesting halChannelWidthFromFrameworkChannelWidth(int frameworkChannelWidth)1128 static int halChannelWidthFromFrameworkChannelWidth(int frameworkChannelWidth) { 1129 switch (frameworkChannelWidth) { 1130 case ScanResult.CHANNEL_WIDTH_20MHZ: 1131 return WifiChannelWidthInMhz.WIDTH_20; 1132 case ScanResult.CHANNEL_WIDTH_40MHZ: 1133 return WifiChannelWidthInMhz.WIDTH_40; 1134 case ScanResult.CHANNEL_WIDTH_80MHZ: 1135 return WifiChannelWidthInMhz.WIDTH_80; 1136 case ScanResult.CHANNEL_WIDTH_160MHZ: 1137 return WifiChannelWidthInMhz.WIDTH_160; 1138 case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 1139 return WifiChannelWidthInMhz.WIDTH_80P80; 1140 default: 1141 throw new IllegalArgumentException("bad " + frameworkChannelWidth); 1142 } 1143 } 1144 1145 @VisibleForTesting frameworkChannelWidthFromHalChannelWidth(int halChannelWidth)1146 static int frameworkChannelWidthFromHalChannelWidth(int halChannelWidth) { 1147 switch (halChannelWidth) { 1148 case WifiChannelWidthInMhz.WIDTH_20: 1149 return ScanResult.CHANNEL_WIDTH_20MHZ; 1150 case WifiChannelWidthInMhz.WIDTH_40: 1151 return ScanResult.CHANNEL_WIDTH_40MHZ; 1152 case WifiChannelWidthInMhz.WIDTH_80: 1153 return ScanResult.CHANNEL_WIDTH_80MHZ; 1154 case WifiChannelWidthInMhz.WIDTH_160: 1155 return ScanResult.CHANNEL_WIDTH_160MHZ; 1156 case WifiChannelWidthInMhz.WIDTH_80P80: 1157 return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; 1158 default: 1159 throw new IllegalArgumentException("bad " + halChannelWidth); 1160 } 1161 } 1162 1163 @VisibleForTesting halPreambleFromFrameworkPreamble(int rttManagerPreamble)1164 static int halPreambleFromFrameworkPreamble(int rttManagerPreamble) { 1165 BitMask checkoff = new BitMask(rttManagerPreamble); 1166 int flags = 0; 1167 if (checkoff.testAndClear(RttManager.PREAMBLE_LEGACY)) { 1168 flags |= RttPreamble.LEGACY; 1169 } 1170 if (checkoff.testAndClear(RttManager.PREAMBLE_HT)) { 1171 flags |= RttPreamble.HT; 1172 } 1173 if (checkoff.testAndClear(RttManager.PREAMBLE_VHT)) { 1174 flags |= RttPreamble.VHT; 1175 } 1176 if (checkoff.value != 0) { 1177 throw new IllegalArgumentException("bad " + rttManagerPreamble); 1178 } 1179 return flags; 1180 } 1181 1182 @VisibleForTesting frameworkPreambleFromHalPreamble(int halPreamble)1183 static int frameworkPreambleFromHalPreamble(int halPreamble) { 1184 BitMask checkoff = new BitMask(halPreamble); 1185 int flags = 0; 1186 if (checkoff.testAndClear(RttPreamble.LEGACY)) { 1187 flags |= RttManager.PREAMBLE_LEGACY; 1188 } 1189 if (checkoff.testAndClear(RttPreamble.HT)) { 1190 flags |= RttManager.PREAMBLE_HT; 1191 } 1192 if (checkoff.testAndClear(RttPreamble.VHT)) { 1193 flags |= RttManager.PREAMBLE_VHT; 1194 } 1195 if (checkoff.value != 0) { 1196 throw new IllegalArgumentException("bad " + halPreamble); 1197 } 1198 return flags; 1199 } 1200 1201 @VisibleForTesting halBwFromFrameworkBw(int rttManagerBandwidth)1202 static int halBwFromFrameworkBw(int rttManagerBandwidth) { 1203 BitMask checkoff = new BitMask(rttManagerBandwidth); 1204 int flags = 0; 1205 if (checkoff.testAndClear(RttManager.RTT_BW_5_SUPPORT)) { 1206 flags |= RttBw.BW_5MHZ; 1207 } 1208 if (checkoff.testAndClear(RttManager.RTT_BW_10_SUPPORT)) { 1209 flags |= RttBw.BW_10MHZ; 1210 } 1211 if (checkoff.testAndClear(RttManager.RTT_BW_20_SUPPORT)) { 1212 flags |= RttBw.BW_20MHZ; 1213 } 1214 if (checkoff.testAndClear(RttManager.RTT_BW_40_SUPPORT)) { 1215 flags |= RttBw.BW_40MHZ; 1216 } 1217 if (checkoff.testAndClear(RttManager.RTT_BW_80_SUPPORT)) { 1218 flags |= RttBw.BW_80MHZ; 1219 } 1220 if (checkoff.testAndClear(RttManager.RTT_BW_160_SUPPORT)) { 1221 flags |= RttBw.BW_160MHZ; 1222 } 1223 if (checkoff.value != 0) { 1224 throw new IllegalArgumentException("bad " + rttManagerBandwidth); 1225 } 1226 return flags; 1227 } 1228 1229 @VisibleForTesting frameworkBwFromHalBw(int rttBw)1230 static int frameworkBwFromHalBw(int rttBw) { 1231 BitMask checkoff = new BitMask(rttBw); 1232 int flags = 0; 1233 if (checkoff.testAndClear(RttBw.BW_5MHZ)) { 1234 flags |= RttManager.RTT_BW_5_SUPPORT; 1235 } 1236 if (checkoff.testAndClear(RttBw.BW_10MHZ)) { 1237 flags |= RttManager.RTT_BW_10_SUPPORT; 1238 } 1239 if (checkoff.testAndClear(RttBw.BW_20MHZ)) { 1240 flags |= RttManager.RTT_BW_20_SUPPORT; 1241 } 1242 if (checkoff.testAndClear(RttBw.BW_40MHZ)) { 1243 flags |= RttManager.RTT_BW_40_SUPPORT; 1244 } 1245 if (checkoff.testAndClear(RttBw.BW_80MHZ)) { 1246 flags |= RttManager.RTT_BW_80_SUPPORT; 1247 } 1248 if (checkoff.testAndClear(RttBw.BW_160MHZ)) { 1249 flags |= RttManager.RTT_BW_160_SUPPORT; 1250 } 1251 if (checkoff.value != 0) { 1252 throw new IllegalArgumentException("bad " + rttBw); 1253 } 1254 return flags; 1255 } 1256 1257 @VisibleForTesting halRttConfigArrayFromFrameworkRttParamsArray( RttManager.RttParams[] params)1258 static ArrayList<RttConfig> halRttConfigArrayFromFrameworkRttParamsArray( 1259 RttManager.RttParams[] params) { 1260 final int length = params.length; 1261 ArrayList<RttConfig> configs = new ArrayList<RttConfig>(length); 1262 for (int i = 0; i < length; i++) { 1263 RttConfig config = halRttConfigFromFrameworkRttParams(params[i]); 1264 if (config != null) { 1265 configs.add(config); 1266 } 1267 } 1268 return configs; 1269 } 1270 1271 /** 1272 * Starts a new rtt request 1273 * 1274 * @param params 1275 * @param handler 1276 * @return success indication 1277 */ requestRtt(RttManager.RttParams[] params, WifiNative.RttEventHandler handler)1278 public boolean requestRtt(RttManager.RttParams[] params, WifiNative.RttEventHandler handler) { 1279 ArrayList<RttConfig> rttConfigs; 1280 try { 1281 rttConfigs = halRttConfigArrayFromFrameworkRttParamsArray(params); 1282 } catch (IllegalArgumentException e) { 1283 mLog.err("Illegal argument for RTT request").c(e.toString()).flush(); 1284 return false; 1285 } 1286 synchronized (sLock) { 1287 if (mIWifiRttController == null) return boolResult(false); 1288 if (mRttCmdId != 0) return boolResult(false); 1289 mRttCmdId = mRttCmdIdNext++; 1290 mRttEventHandler = handler; 1291 if (mRttCmdIdNext <= 0) mRttCmdIdNext = 1; 1292 try { 1293 WifiStatus status = mIWifiRttController.rangeRequest(mRttCmdId, rttConfigs); 1294 if (ok(status)) return true; 1295 mRttCmdId = 0; 1296 return false; 1297 } catch (RemoteException e) { 1298 handleRemoteException(e); 1299 return false; 1300 } 1301 } 1302 } 1303 1304 /** 1305 * Cancels an outstanding rtt request 1306 * 1307 * @param params 1308 * @return true if there was an outstanding request and it was successfully cancelled 1309 */ cancelRtt(RttManager.RttParams[] params)1310 public boolean cancelRtt(RttManager.RttParams[] params) { 1311 ArrayList<RttConfig> rttConfigs = halRttConfigArrayFromFrameworkRttParamsArray(params); 1312 synchronized (sLock) { 1313 if (mIWifiRttController == null) return boolResult(false); 1314 if (mRttCmdId == 0) return boolResult(false); 1315 ArrayList<byte[/* 6 */]> addrs = new ArrayList<byte[]>(rttConfigs.size()); 1316 for (RttConfig x : rttConfigs) addrs.add(x.addr); 1317 try { 1318 WifiStatus status = mIWifiRttController.rangeCancel(mRttCmdId, addrs); 1319 mRttCmdId = 0; 1320 if (!ok(status)) return false; 1321 return true; 1322 } catch (RemoteException e) { 1323 handleRemoteException(e); 1324 return false; 1325 } 1326 } 1327 } 1328 1329 private int mRttResponderCmdId = 0; 1330 1331 /** 1332 * Get RTT responder information e.g. WiFi channel to enable responder on. 1333 * 1334 * @return info Instance of |RttResponder|, or null for error. 1335 */ getRttResponder()1336 private RttResponder getRttResponder() { 1337 class AnswerBox { 1338 public RttResponder value = null; 1339 } 1340 synchronized (sLock) { 1341 if (mIWifiRttController == null) return null; 1342 AnswerBox answer = new AnswerBox(); 1343 try { 1344 mIWifiRttController.getResponderInfo((status, info) -> { 1345 if (!ok(status)) return; 1346 answer.value = info; 1347 }); 1348 return answer.value; 1349 } catch (RemoteException e) { 1350 handleRemoteException(e); 1351 return null; 1352 } 1353 } 1354 } 1355 1356 /** 1357 * Convert Hal RttResponder to a framework ResponderConfig 1358 * 1359 * @param info Instance of |RttResponder| 1360 * @return framework version of same 1361 */ frameworkResponderConfigFromHalRttResponder(RttResponder info)1362 private ResponderConfig frameworkResponderConfigFromHalRttResponder(RttResponder info) { 1363 ResponderConfig config = new ResponderConfig(); 1364 config.frequency = info.channel.centerFreq; 1365 config.centerFreq0 = info.channel.centerFreq0; 1366 config.centerFreq1 = info.channel.centerFreq1; 1367 config.channelWidth = frameworkChannelWidthFromHalChannelWidth(info.channel.width); 1368 config.preamble = frameworkPreambleFromHalPreamble(info.preamble); 1369 return config; 1370 } 1371 1372 /** 1373 * Enables RTT responder role on the device. 1374 * 1375 * @return {@link ResponderConfig} if the responder role is successfully enabled, 1376 * {@code null} otherwise. 1377 */ enableRttResponder(int timeoutSeconds)1378 public ResponderConfig enableRttResponder(int timeoutSeconds) { 1379 RttResponder info = getRttResponder(); 1380 synchronized (sLock) { 1381 if (mIWifiRttController == null) return null; 1382 if (mRttResponderCmdId != 0) { 1383 mLog.e("responder mode already enabled - this shouldn't happen"); 1384 return null; 1385 } 1386 ResponderConfig config = null; 1387 int id = mRttCmdIdNext++; 1388 if (mRttCmdIdNext <= 0) mRttCmdIdNext = 1; 1389 try { 1390 WifiStatus status = mIWifiRttController.enableResponder( 1391 /* cmdId */id, 1392 /* WifiChannelInfo channelHint */null, 1393 timeoutSeconds, info); 1394 if (ok(status)) { 1395 mRttResponderCmdId = id; 1396 config = frameworkResponderConfigFromHalRttResponder(info); 1397 mVerboseLog.i("enabling rtt " + mRttResponderCmdId); 1398 } 1399 return config; 1400 } catch (RemoteException e) { 1401 handleRemoteException(e); 1402 return null; 1403 } 1404 } 1405 } 1406 1407 /** 1408 * Disables RTT responder role. 1409 * 1410 * @return {@code true} if responder role is successfully disabled, 1411 * {@code false} otherwise. 1412 */ disableRttResponder()1413 public boolean disableRttResponder() { 1414 synchronized (sLock) { 1415 if (mIWifiRttController == null) return boolResult(false); 1416 if (mRttResponderCmdId == 0) return boolResult(false); 1417 try { 1418 WifiStatus status = mIWifiRttController.disableResponder(mRttResponderCmdId); 1419 mRttResponderCmdId = 0; 1420 if (!ok(status)) return false; 1421 return true; 1422 } catch (RemoteException e) { 1423 handleRemoteException(e); 1424 return false; 1425 } 1426 } 1427 } 1428 1429 /** 1430 * Set the MAC OUI during scanning. 1431 * <p> 1432 * An OUI {Organizationally Unique Identifier} is a 24-bit number that 1433 * uniquely identifies a vendor or manufacturer. 1434 * 1435 * @param oui 1436 * @return true for success 1437 */ setScanningMacOui(byte[] oui)1438 public boolean setScanningMacOui(byte[] oui) { 1439 if (oui == null) return boolResult(false); 1440 if (oui.length != 3) return boolResult(false); 1441 synchronized (sLock) { 1442 try { 1443 if (mIWifiStaIface == null) return boolResult(false); 1444 WifiStatus status = mIWifiStaIface.setScanningMacOui(oui); 1445 if (!ok(status)) return false; 1446 return true; 1447 } catch (RemoteException e) { 1448 handleRemoteException(e); 1449 return false; 1450 } 1451 } 1452 } 1453 1454 /** 1455 * Query the list of valid frequencies for the provided band. 1456 * <p> 1457 * The result depends on the on the country code that has been set. 1458 * 1459 * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants. 1460 * @return frequencies vector of valid frequencies (MHz), or null for error. 1461 * @throws IllegalArgumentException if band is not recognized. 1462 */ getChannelsForBand(int band)1463 public int[] getChannelsForBand(int band) { 1464 enter("%").c(band).flush(); 1465 class AnswerBox { 1466 public int[] value = null; 1467 } 1468 synchronized (sLock) { 1469 try { 1470 AnswerBox box = new AnswerBox(); 1471 int hb = makeWifiBandFromFrameworkBand(band); 1472 if (mIWifiStaIface != null) { 1473 mIWifiStaIface.getValidFrequenciesForBand(hb, (status, frequencies) -> { 1474 if (status.code == WifiStatusCode.ERROR_NOT_SUPPORTED) { 1475 mChannelsForBandSupport = false; 1476 } 1477 if (!ok(status)) return; 1478 mChannelsForBandSupport = true; 1479 box.value = intArrayFromArrayList(frequencies); 1480 }); 1481 } else if (mIWifiApIface != null) { 1482 mIWifiApIface.getValidFrequenciesForBand(hb, (status, frequencies) -> { 1483 if (status.code == WifiStatusCode.ERROR_NOT_SUPPORTED) { 1484 mChannelsForBandSupport = false; 1485 } 1486 if (!ok(status)) return; 1487 mChannelsForBandSupport = true; 1488 box.value = intArrayFromArrayList(frequencies); 1489 }); 1490 } 1491 return box.value; 1492 } catch (RemoteException e) { 1493 handleRemoteException(e); 1494 return null; 1495 } 1496 } 1497 } 1498 intArrayFromArrayList(ArrayList<Integer> in)1499 private int[] intArrayFromArrayList(ArrayList<Integer> in) { 1500 int[] ans = new int[in.size()]; 1501 int i = 0; 1502 for (Integer e : in) ans[i++] = e; 1503 return ans; 1504 } 1505 1506 /** 1507 * This holder is null until we know whether or not there is frequency-for-band support. 1508 * <p> 1509 * Set as a side-effect of getChannelsForBand. 1510 */ 1511 @VisibleForTesting 1512 Boolean mChannelsForBandSupport = null; 1513 1514 /** 1515 * Indicates whether getChannelsForBand is supported. 1516 * 1517 * @return true if it is. 1518 */ isGetChannelsForBandSupported()1519 public boolean isGetChannelsForBandSupported() { 1520 if (mChannelsForBandSupport != null) return mChannelsForBandSupport; 1521 getChannelsForBand(WifiBand.BAND_24GHZ); 1522 if (mChannelsForBandSupport != null) return mChannelsForBandSupport; 1523 return false; 1524 } 1525 1526 /** 1527 * Get the APF (Android Packet Filter) capabilities of the device 1528 */ getApfCapabilities()1529 public ApfCapabilities getApfCapabilities() { 1530 class AnswerBox { 1531 public ApfCapabilities value = sNoApfCapabilities; 1532 } 1533 synchronized (sLock) { 1534 try { 1535 if (mIWifiStaIface == null) return sNoApfCapabilities; 1536 AnswerBox box = new AnswerBox(); 1537 mIWifiStaIface.getApfPacketFilterCapabilities((status, capabilities) -> { 1538 if (!ok(status)) return; 1539 box.value = new ApfCapabilities( 1540 /* apfVersionSupported */ capabilities.version, 1541 /* maximumApfProgramSize */ capabilities.maxLength, 1542 /* apfPacketFormat */ android.system.OsConstants.ARPHRD_ETHER); 1543 }); 1544 return box.value; 1545 } catch (RemoteException e) { 1546 handleRemoteException(e); 1547 return sNoApfCapabilities; 1548 } 1549 } 1550 } 1551 1552 private static final ApfCapabilities sNoApfCapabilities = new ApfCapabilities(0, 0, 0); 1553 1554 /** 1555 * Installs an APF program on this iface, replacing any existing program. 1556 * 1557 * @param filter is the android packet filter program 1558 * @return true for success 1559 */ installPacketFilter(byte[] filter)1560 public boolean installPacketFilter(byte[] filter) { 1561 int cmdId = 0; // We only aspire to support one program at a time 1562 if (filter == null) return boolResult(false); 1563 // Copy the program before taking the lock. 1564 ArrayList<Byte> program = NativeUtil.byteArrayToArrayList(filter); 1565 enter("filter length %").c(filter.length).flush(); 1566 synchronized (sLock) { 1567 try { 1568 if (mIWifiStaIface == null) return boolResult(false); 1569 WifiStatus status = mIWifiStaIface.installApfPacketFilter(cmdId, program); 1570 if (!ok(status)) return false; 1571 return true; 1572 } catch (RemoteException e) { 1573 handleRemoteException(e); 1574 return false; 1575 } 1576 } 1577 } 1578 1579 /** 1580 * Set country code for this AP iface. 1581 * 1582 * @param countryCode - two-letter country code (as ISO 3166) 1583 * @return true for success 1584 */ setCountryCodeHal(String countryCode)1585 public boolean setCountryCodeHal(String countryCode) { 1586 if (countryCode == null) return boolResult(false); 1587 if (countryCode.length() != 2) return boolResult(false); 1588 byte[] code; 1589 try { 1590 code = NativeUtil.stringToByteArray(countryCode); 1591 } catch (IllegalArgumentException e) { 1592 return boolResult(false); 1593 } 1594 synchronized (sLock) { 1595 try { 1596 if (mIWifiApIface == null) return boolResult(false); 1597 WifiStatus status = mIWifiApIface.setCountryCode(code); 1598 if (!ok(status)) return false; 1599 return true; 1600 } catch (RemoteException e) { 1601 handleRemoteException(e); 1602 return false; 1603 } 1604 } 1605 } 1606 1607 private WifiNative.WifiLoggerEventHandler mLogEventHandler = null; 1608 1609 /** 1610 * Registers the logger callback and enables alerts. 1611 * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked. 1612 */ setLoggingEventHandler(WifiNative.WifiLoggerEventHandler handler)1613 public boolean setLoggingEventHandler(WifiNative.WifiLoggerEventHandler handler) { 1614 if (handler == null) return boolResult(false); 1615 synchronized (sLock) { 1616 if (mIWifiChip == null) return boolResult(false); 1617 if (mLogEventHandler != null) return boolResult(false); 1618 try { 1619 WifiStatus status = mIWifiChip.enableDebugErrorAlerts(true); 1620 if (!ok(status)) return false; 1621 mLogEventHandler = handler; 1622 return true; 1623 } catch (RemoteException e) { 1624 handleRemoteException(e); 1625 return false; 1626 } 1627 } 1628 } 1629 1630 /** 1631 * Stops all logging and resets the logger callback. 1632 * This stops both the alerts and ring buffer data collection. 1633 */ resetLogHandler()1634 public boolean resetLogHandler() { 1635 synchronized (sLock) { 1636 if (mIWifiChip == null) return boolResult(false); 1637 if (mLogEventHandler == null) return boolResult(false); 1638 try { 1639 WifiStatus status = mIWifiChip.enableDebugErrorAlerts(false); 1640 if (!ok(status)) return false; 1641 status = mIWifiChip.stopLoggingToDebugRingBuffer(); 1642 if (!ok(status)) return false; 1643 mLogEventHandler = null; 1644 return true; 1645 } catch (RemoteException e) { 1646 handleRemoteException(e); 1647 return false; 1648 } 1649 } 1650 } 1651 1652 /** 1653 * Control debug data collection 1654 * 1655 * @param verboseLevel 0 to 3, inclusive. 0 stops logging. 1656 * @param flags Ignored. 1657 * @param maxIntervalInSec Maximum interval between reports; ignore if 0. 1658 * @param minDataSizeInBytes Minimum data size in buffer for report; ignore if 0. 1659 * @param ringName Name of the ring for which data collection is to start. 1660 * @return true for success 1661 */ startLoggingRingBuffer(int verboseLevel, int flags, int maxIntervalInSec, int minDataSizeInBytes, String ringName)1662 public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxIntervalInSec, 1663 int minDataSizeInBytes, String ringName) { 1664 enter("verboseLevel=%, flags=%, maxIntervalInSec=%, minDataSizeInBytes=%, ringName=%") 1665 .c(verboseLevel).c(flags).c(maxIntervalInSec).c(minDataSizeInBytes).c(ringName) 1666 .flush(); 1667 synchronized (sLock) { 1668 if (mIWifiChip == null) return boolResult(false); 1669 try { 1670 // note - flags are not used 1671 WifiStatus status = mIWifiChip.startLoggingToDebugRingBuffer( 1672 ringName, 1673 verboseLevel, 1674 maxIntervalInSec, 1675 minDataSizeInBytes 1676 ); 1677 return ok(status); 1678 } catch (RemoteException e) { 1679 handleRemoteException(e); 1680 return false; 1681 } 1682 } 1683 } 1684 1685 /** 1686 * Pointlessly fail 1687 * 1688 * @return -1 1689 */ getSupportedLoggerFeatureSet()1690 public int getSupportedLoggerFeatureSet() { 1691 return -1; 1692 } 1693 1694 private String mDriverDescription; // Cached value filled by requestChipDebugInfo() 1695 1696 /** 1697 * Vendor-provided wifi driver version string 1698 */ getDriverVersion()1699 public String getDriverVersion() { 1700 synchronized (sLock) { 1701 if (mDriverDescription == null) requestChipDebugInfo(); 1702 return mDriverDescription; 1703 } 1704 } 1705 1706 private String mFirmwareDescription; // Cached value filled by requestChipDebugInfo() 1707 1708 /** 1709 * Vendor-provided wifi firmware version string 1710 */ getFirmwareVersion()1711 public String getFirmwareVersion() { 1712 synchronized (sLock) { 1713 if (mFirmwareDescription == null) requestChipDebugInfo(); 1714 return mFirmwareDescription; 1715 } 1716 } 1717 1718 /** 1719 * Refreshes our idea of the driver and firmware versions 1720 */ requestChipDebugInfo()1721 private void requestChipDebugInfo() { 1722 mDriverDescription = null; 1723 mFirmwareDescription = null; 1724 try { 1725 if (mIWifiChip == null) return; 1726 mIWifiChip.requestChipDebugInfo((status, chipDebugInfo) -> { 1727 if (!ok(status)) return; 1728 mDriverDescription = chipDebugInfo.driverDescription; 1729 mFirmwareDescription = chipDebugInfo.firmwareDescription; 1730 }); 1731 } catch (RemoteException e) { 1732 handleRemoteException(e); 1733 return; 1734 } 1735 mLog.info("Driver: % Firmware: %") 1736 .c(mDriverDescription) 1737 .c(mFirmwareDescription) 1738 .flush(); 1739 } 1740 1741 /** 1742 * Creates RingBufferStatus from the Hal version 1743 */ ringBufferStatus(WifiDebugRingBufferStatus h)1744 private static WifiNative.RingBufferStatus ringBufferStatus(WifiDebugRingBufferStatus h) { 1745 WifiNative.RingBufferStatus ans = new WifiNative.RingBufferStatus(); 1746 ans.name = h.ringName; 1747 ans.flag = frameworkRingBufferFlagsFromHal(h.flags); 1748 ans.ringBufferId = h.ringId; 1749 ans.ringBufferByteSize = h.sizeInBytes; 1750 ans.verboseLevel = h.verboseLevel; 1751 // Remaining fields are unavailable 1752 // writtenBytes; 1753 // readBytes; 1754 // writtenRecords; 1755 return ans; 1756 } 1757 1758 /** 1759 * Translates a hal wifiDebugRingBufferFlag to the WifiNative version 1760 */ frameworkRingBufferFlagsFromHal(int wifiDebugRingBufferFlag)1761 private static int frameworkRingBufferFlagsFromHal(int wifiDebugRingBufferFlag) { 1762 BitMask checkoff = new BitMask(wifiDebugRingBufferFlag); 1763 int flags = 0; 1764 if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES)) { 1765 flags |= WifiNative.RingBufferStatus.HAS_BINARY_ENTRIES; 1766 } 1767 if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES)) { 1768 flags |= WifiNative.RingBufferStatus.HAS_ASCII_ENTRIES; 1769 } 1770 if (checkoff.testAndClear(WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES)) { 1771 flags |= WifiNative.RingBufferStatus.HAS_PER_PACKET_ENTRIES; 1772 } 1773 if (checkoff.value != 0) { 1774 throw new IllegalArgumentException("Unknown WifiDebugRingBufferFlag " + checkoff.value); 1775 } 1776 return flags; 1777 } 1778 1779 /** 1780 * Creates array of RingBufferStatus from the Hal version 1781 */ makeRingBufferStatusArray( ArrayList<WifiDebugRingBufferStatus> ringBuffers)1782 private static WifiNative.RingBufferStatus[] makeRingBufferStatusArray( 1783 ArrayList<WifiDebugRingBufferStatus> ringBuffers) { 1784 WifiNative.RingBufferStatus[] ans = new WifiNative.RingBufferStatus[ringBuffers.size()]; 1785 int i = 0; 1786 for (WifiDebugRingBufferStatus b : ringBuffers) { 1787 ans[i++] = ringBufferStatus(b); 1788 } 1789 return ans; 1790 } 1791 1792 /** 1793 * API to get the status of all ring buffers supported by driver 1794 */ getRingBufferStatus()1795 public WifiNative.RingBufferStatus[] getRingBufferStatus() { 1796 class AnswerBox { 1797 public WifiNative.RingBufferStatus[] value = null; 1798 } 1799 AnswerBox ans = new AnswerBox(); 1800 synchronized (sLock) { 1801 if (mIWifiChip == null) return null; 1802 try { 1803 mIWifiChip.getDebugRingBuffersStatus((status, ringBuffers) -> { 1804 if (!ok(status)) return; 1805 ans.value = makeRingBufferStatusArray(ringBuffers); 1806 }); 1807 } catch (RemoteException e) { 1808 handleRemoteException(e); 1809 return null; 1810 } 1811 } 1812 return ans.value; 1813 } 1814 1815 /** 1816 * Indicates to driver that all the data has to be uploaded urgently 1817 */ getRingBufferData(String ringName)1818 public boolean getRingBufferData(String ringName) { 1819 enter("ringName %").c(ringName).flush(); 1820 synchronized (sLock) { 1821 if (mIWifiChip == null) return boolResult(false); 1822 try { 1823 WifiStatus status = mIWifiChip.forceDumpToDebugRingBuffer(ringName); 1824 return ok(status); 1825 } catch (RemoteException e) { 1826 handleRemoteException(e); 1827 return false; 1828 } 1829 } 1830 } 1831 1832 /** 1833 * Request vendor debug info from the firmware 1834 */ getFwMemoryDump()1835 public byte[] getFwMemoryDump() { 1836 class AnswerBox { 1837 public byte[] value; 1838 } 1839 AnswerBox ans = new AnswerBox(); 1840 synchronized (sLock) { 1841 if (mIWifiChip == null) return (null); 1842 try { 1843 mIWifiChip.requestFirmwareDebugDump((status, blob) -> { 1844 if (!ok(status)) return; 1845 ans.value = NativeUtil.byteArrayFromArrayList(blob); 1846 }); 1847 } catch (RemoteException e) { 1848 handleRemoteException(e); 1849 return null; 1850 } 1851 } 1852 return ans.value; 1853 } 1854 1855 /** 1856 * Request vendor debug info from the driver 1857 */ getDriverStateDump()1858 public byte[] getDriverStateDump() { 1859 class AnswerBox { 1860 public byte[] value; 1861 } 1862 AnswerBox ans = new AnswerBox(); 1863 synchronized (sLock) { 1864 if (mIWifiChip == null) return (null); 1865 try { 1866 mIWifiChip.requestDriverDebugDump((status, blob) -> { 1867 if (!ok(status)) return; 1868 ans.value = NativeUtil.byteArrayFromArrayList(blob); 1869 }); 1870 } catch (RemoteException e) { 1871 handleRemoteException(e); 1872 return null; 1873 } 1874 } 1875 return ans.value; 1876 } 1877 1878 /** 1879 * Start packet fate monitoring 1880 * <p> 1881 * Once started, monitoring remains active until HAL is unloaded. 1882 * 1883 * @return true for success 1884 */ startPktFateMonitoring()1885 public boolean startPktFateMonitoring() { 1886 synchronized (sLock) { 1887 if (mIWifiStaIface == null) return boolResult(false); 1888 try { 1889 WifiStatus status = mIWifiStaIface.startDebugPacketFateMonitoring(); 1890 return ok(status); 1891 } catch (RemoteException e) { 1892 handleRemoteException(e); 1893 return false; 1894 } 1895 } 1896 } 1897 halToFrameworkPktFateFrameType(int type)1898 private byte halToFrameworkPktFateFrameType(int type) { 1899 switch (type) { 1900 case WifiDebugPacketFateFrameType.UNKNOWN: 1901 return WifiLoggerHal.FRAME_TYPE_UNKNOWN; 1902 case WifiDebugPacketFateFrameType.ETHERNET_II: 1903 return WifiLoggerHal.FRAME_TYPE_ETHERNET_II; 1904 case WifiDebugPacketFateFrameType.MGMT_80211: 1905 return WifiLoggerHal.FRAME_TYPE_80211_MGMT; 1906 default: 1907 throw new IllegalArgumentException("bad " + type); 1908 } 1909 } 1910 halToFrameworkRxPktFate(int type)1911 private byte halToFrameworkRxPktFate(int type) { 1912 switch (type) { 1913 case WifiDebugRxPacketFate.SUCCESS: 1914 return WifiLoggerHal.RX_PKT_FATE_SUCCESS; 1915 case WifiDebugRxPacketFate.FW_QUEUED: 1916 return WifiLoggerHal.RX_PKT_FATE_FW_QUEUED; 1917 case WifiDebugRxPacketFate.FW_DROP_FILTER: 1918 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER; 1919 case WifiDebugRxPacketFate.FW_DROP_INVALID: 1920 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID; 1921 case WifiDebugRxPacketFate.FW_DROP_NOBUFS: 1922 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS; 1923 case WifiDebugRxPacketFate.FW_DROP_OTHER: 1924 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER; 1925 case WifiDebugRxPacketFate.DRV_QUEUED: 1926 return WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED; 1927 case WifiDebugRxPacketFate.DRV_DROP_FILTER: 1928 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER; 1929 case WifiDebugRxPacketFate.DRV_DROP_INVALID: 1930 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID; 1931 case WifiDebugRxPacketFate.DRV_DROP_NOBUFS: 1932 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS; 1933 case WifiDebugRxPacketFate.DRV_DROP_OTHER: 1934 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER; 1935 default: 1936 throw new IllegalArgumentException("bad " + type); 1937 } 1938 } 1939 halToFrameworkTxPktFate(int type)1940 private byte halToFrameworkTxPktFate(int type) { 1941 switch (type) { 1942 case WifiDebugTxPacketFate.ACKED: 1943 return WifiLoggerHal.TX_PKT_FATE_ACKED; 1944 case WifiDebugTxPacketFate.SENT: 1945 return WifiLoggerHal.TX_PKT_FATE_SENT; 1946 case WifiDebugTxPacketFate.FW_QUEUED: 1947 return WifiLoggerHal.TX_PKT_FATE_FW_QUEUED; 1948 case WifiDebugTxPacketFate.FW_DROP_INVALID: 1949 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID; 1950 case WifiDebugTxPacketFate.FW_DROP_NOBUFS: 1951 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS; 1952 case WifiDebugTxPacketFate.FW_DROP_OTHER: 1953 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER; 1954 case WifiDebugTxPacketFate.DRV_QUEUED: 1955 return WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED; 1956 case WifiDebugTxPacketFate.DRV_DROP_INVALID: 1957 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID; 1958 case WifiDebugTxPacketFate.DRV_DROP_NOBUFS: 1959 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS; 1960 case WifiDebugTxPacketFate.DRV_DROP_OTHER: 1961 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER; 1962 default: 1963 throw new IllegalArgumentException("bad " + type); 1964 } 1965 } 1966 1967 /** 1968 * Retrieve fates of outbound packets 1969 * <p> 1970 * Reports the outbound frames for the most recent association (space allowing). 1971 * 1972 * @param reportBufs 1973 * @return true for success 1974 */ getTxPktFates(WifiNative.TxFateReport[] reportBufs)1975 public boolean getTxPktFates(WifiNative.TxFateReport[] reportBufs) { 1976 if (ArrayUtils.isEmpty(reportBufs)) return boolResult(false); 1977 synchronized (sLock) { 1978 if (mIWifiStaIface == null) return boolResult(false); 1979 try { 1980 MutableBoolean ok = new MutableBoolean(false); 1981 mIWifiStaIface.getDebugTxPacketFates((status, fates) -> { 1982 if (!ok(status)) return; 1983 int i = 0; 1984 for (WifiDebugTxPacketFateReport fate : fates) { 1985 if (i >= reportBufs.length) break; 1986 byte code = halToFrameworkTxPktFate(fate.fate); 1987 long us = fate.frameInfo.driverTimestampUsec; 1988 byte type = 1989 halToFrameworkPktFateFrameType(fate.frameInfo.frameType); 1990 byte[] frame = 1991 NativeUtil.byteArrayFromArrayList( 1992 fate.frameInfo.frameContent); 1993 reportBufs[i++] = 1994 new WifiNative.TxFateReport(code, us, type, frame); 1995 } 1996 ok.value = true; 1997 } 1998 ); 1999 return ok.value; 2000 } catch (RemoteException e) { 2001 handleRemoteException(e); 2002 return false; 2003 } 2004 } 2005 } 2006 2007 /** 2008 * Retrieve fates of inbound packets 2009 * <p> 2010 * Reports the inbound frames for the most recent association (space allowing). 2011 * 2012 * @param reportBufs 2013 * @return true for success 2014 */ getRxPktFates(WifiNative.RxFateReport[] reportBufs)2015 public boolean getRxPktFates(WifiNative.RxFateReport[] reportBufs) { 2016 if (ArrayUtils.isEmpty(reportBufs)) return boolResult(false); 2017 synchronized (sLock) { 2018 if (mIWifiStaIface == null) return boolResult(false); 2019 try { 2020 MutableBoolean ok = new MutableBoolean(false); 2021 mIWifiStaIface.getDebugRxPacketFates((status, fates) -> { 2022 if (!ok(status)) return; 2023 int i = 0; 2024 for (WifiDebugRxPacketFateReport fate : fates) { 2025 if (i >= reportBufs.length) break; 2026 byte code = halToFrameworkRxPktFate(fate.fate); 2027 long us = fate.frameInfo.driverTimestampUsec; 2028 byte type = 2029 halToFrameworkPktFateFrameType(fate.frameInfo.frameType); 2030 byte[] frame = 2031 NativeUtil.byteArrayFromArrayList( 2032 fate.frameInfo.frameContent); 2033 reportBufs[i++] = 2034 new WifiNative.RxFateReport(code, us, type, frame); 2035 } 2036 ok.value = true; 2037 } 2038 ); 2039 return ok.value; 2040 } catch (RemoteException e) { 2041 handleRemoteException(e); 2042 return false; 2043 } 2044 } 2045 } 2046 2047 /** 2048 * Start sending the specified keep alive packets periodically. 2049 * 2050 * @param slot 2051 * @param srcMac 2052 * @param keepAlivePacket 2053 * @param periodInMs 2054 * @return 0 for success, -1 for error 2055 */ startSendingOffloadedPacket( int slot, byte[] srcMac, KeepalivePacketData keepAlivePacket, int periodInMs)2056 public int startSendingOffloadedPacket( 2057 int slot, byte[] srcMac, KeepalivePacketData keepAlivePacket, int periodInMs) { 2058 enter("slot=% periodInMs=%").c(slot).c(periodInMs).flush(); 2059 2060 ArrayList<Byte> data = NativeUtil.byteArrayToArrayList(keepAlivePacket.data); 2061 short protocol = (short) (keepAlivePacket.protocol); 2062 2063 synchronized (sLock) { 2064 if (mIWifiStaIface == null) return -1; 2065 try { 2066 WifiStatus status = mIWifiStaIface.startSendingKeepAlivePackets( 2067 slot, 2068 data, 2069 protocol, 2070 srcMac, 2071 keepAlivePacket.dstMac, 2072 periodInMs); 2073 if (!ok(status)) return -1; 2074 return 0; 2075 } catch (RemoteException e) { 2076 handleRemoteException(e); 2077 return -1; 2078 } 2079 } 2080 } 2081 2082 /** 2083 * Stop sending the specified keep alive packets. 2084 * 2085 * @param slot id - same as startSendingOffloadedPacket call. 2086 * @return 0 for success, -1 for error 2087 */ stopSendingOffloadedPacket(int slot)2088 public int stopSendingOffloadedPacket(int slot) { 2089 enter("slot=%").c(slot).flush(); 2090 2091 synchronized (sLock) { 2092 if (mIWifiStaIface == null) return -1; 2093 try { 2094 WifiStatus status = mIWifiStaIface.stopSendingKeepAlivePackets(slot); 2095 if (!ok(status)) return -1; 2096 return 0; 2097 } catch (RemoteException e) { 2098 handleRemoteException(e); 2099 return -1; 2100 } 2101 } 2102 } 2103 2104 /** 2105 * A fixed cmdId for our RssiMonitoring (we only do one at a time) 2106 */ 2107 @VisibleForTesting 2108 static final int sRssiMonCmdId = 7551; 2109 2110 /** 2111 * Our client's handler 2112 */ 2113 private WifiNative.WifiRssiEventHandler mWifiRssiEventHandler; 2114 2115 /** 2116 * Start RSSI monitoring on the currently connected access point. 2117 * 2118 * @param maxRssi Maximum RSSI threshold. 2119 * @param minRssi Minimum RSSI threshold. 2120 * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi 2121 * @return 0 for success, -1 for failure 2122 */ startRssiMonitoring(byte maxRssi, byte minRssi, WifiNative.WifiRssiEventHandler rssiEventHandler)2123 public int startRssiMonitoring(byte maxRssi, byte minRssi, 2124 WifiNative.WifiRssiEventHandler rssiEventHandler) { 2125 enter("maxRssi=% minRssi=%").c(maxRssi).c(minRssi).flush(); 2126 if (maxRssi <= minRssi) return -1; 2127 if (rssiEventHandler == null) return -1; 2128 synchronized (sLock) { 2129 if (mIWifiStaIface == null) return -1; 2130 try { 2131 mIWifiStaIface.stopRssiMonitoring(sRssiMonCmdId); 2132 WifiStatus status; 2133 status = mIWifiStaIface.startRssiMonitoring(sRssiMonCmdId, maxRssi, minRssi); 2134 if (!ok(status)) return -1; 2135 mWifiRssiEventHandler = rssiEventHandler; 2136 return 0; 2137 } catch (RemoteException e) { 2138 handleRemoteException(e); 2139 return -1; 2140 } 2141 } 2142 } 2143 2144 /** 2145 * Stop RSSI monitoring 2146 * 2147 * @return 0 for success, -1 for failure 2148 */ stopRssiMonitoring()2149 public int stopRssiMonitoring() { 2150 synchronized (sLock) { 2151 mWifiRssiEventHandler = null; 2152 if (mIWifiStaIface == null) return -1; 2153 try { 2154 mIWifiStaIface.stopRssiMonitoring(sRssiMonCmdId); 2155 WifiStatus status = mIWifiStaIface.stopRssiMonitoring(sRssiMonCmdId); 2156 if (!ok(status)) return -1; 2157 return 0; 2158 } catch (RemoteException e) { 2159 handleRemoteException(e); 2160 return -1; 2161 } 2162 } 2163 } 2164 2165 //TODO - belongs in NativeUtil intsFromArrayList(ArrayList<Integer> a)2166 private static int[] intsFromArrayList(ArrayList<Integer> a) { 2167 if (a == null) return null; 2168 int[] b = new int[a.size()]; 2169 int i = 0; 2170 for (Integer e : a) b[i++] = e; 2171 return b; 2172 } 2173 2174 /** 2175 * Translates from Hal version of wake reason stats to the framework version of same 2176 * 2177 * @param h - Hal version of wake reason stats 2178 * @return framework version of same 2179 */ halToFrameworkWakeReasons( WifiDebugHostWakeReasonStats h)2180 private static WifiWakeReasonAndCounts halToFrameworkWakeReasons( 2181 WifiDebugHostWakeReasonStats h) { 2182 if (h == null) return null; 2183 WifiWakeReasonAndCounts ans = new WifiWakeReasonAndCounts(); 2184 ans.totalCmdEventWake = h.totalCmdEventWakeCnt; 2185 ans.totalDriverFwLocalWake = h.totalDriverFwLocalWakeCnt; 2186 ans.totalRxDataWake = h.totalRxPacketWakeCnt; 2187 ans.rxUnicast = h.rxPktWakeDetails.rxUnicastCnt; 2188 ans.rxMulticast = h.rxPktWakeDetails.rxMulticastCnt; 2189 ans.rxBroadcast = h.rxPktWakeDetails.rxBroadcastCnt; 2190 ans.icmp = h.rxIcmpPkWakeDetails.icmpPkt; 2191 ans.icmp6 = h.rxIcmpPkWakeDetails.icmp6Pkt; 2192 ans.icmp6Ra = h.rxIcmpPkWakeDetails.icmp6Ra; 2193 ans.icmp6Na = h.rxIcmpPkWakeDetails.icmp6Na; 2194 ans.icmp6Ns = h.rxIcmpPkWakeDetails.icmp6Ns; 2195 ans.ipv4RxMulticast = h.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt; 2196 ans.ipv6Multicast = h.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt; 2197 ans.otherRxMulticast = h.rxMulticastPkWakeDetails.otherRxMulticastAddrCnt; 2198 ans.cmdEventWakeCntArray = intsFromArrayList(h.cmdEventWakeCntPerType); 2199 ans.driverFWLocalWakeCntArray = intsFromArrayList(h.driverFwLocalWakeCntPerType); 2200 return ans; 2201 } 2202 2203 /** 2204 * Fetch the host wakeup reasons stats from wlan driver. 2205 * 2206 * @return the |WifiWakeReasonAndCounts| from the wlan driver, or null on failure. 2207 */ getWlanWakeReasonCount()2208 public WifiWakeReasonAndCounts getWlanWakeReasonCount() { 2209 class AnswerBox { 2210 public WifiDebugHostWakeReasonStats value = null; 2211 } 2212 AnswerBox ans = new AnswerBox(); 2213 synchronized (sLock) { 2214 if (mIWifiChip == null) return null; 2215 try { 2216 mIWifiChip.getDebugHostWakeReasonStats((status, stats) -> { 2217 if (ok(status)) { 2218 ans.value = stats; 2219 } 2220 }); 2221 return halToFrameworkWakeReasons(ans.value); 2222 } catch (RemoteException e) { 2223 handleRemoteException(e); 2224 return null; 2225 } 2226 } 2227 } 2228 2229 /** 2230 * Enable/Disable Neighbour discovery offload functionality in the firmware. 2231 * 2232 * @param enabled true to enable, false to disable. 2233 */ configureNeighborDiscoveryOffload(boolean enabled)2234 public boolean configureNeighborDiscoveryOffload(boolean enabled) { 2235 enter("enabled=%").c(enabled).flush(); 2236 synchronized (sLock) { 2237 if (mIWifiStaIface == null) return boolResult(false); 2238 try { 2239 WifiStatus status = mIWifiStaIface.enableNdOffload(enabled); 2240 if (!ok(status)) return false; 2241 } catch (RemoteException e) { 2242 handleRemoteException(e); 2243 return false; 2244 } 2245 } 2246 return true; 2247 } 2248 2249 // Firmware roaming control. 2250 2251 /** 2252 * Query the firmware roaming capabilities. 2253 * 2254 * @param capabilities object to be filled in 2255 * @return true for success; false for failure 2256 */ getRoamingCapabilities(WifiNative.RoamingCapabilities capabilities)2257 public boolean getRoamingCapabilities(WifiNative.RoamingCapabilities capabilities) { 2258 synchronized (sLock) { 2259 if (mIWifiStaIface == null) return boolResult(false); 2260 try { 2261 MutableBoolean ok = new MutableBoolean(false); 2262 WifiNative.RoamingCapabilities out = capabilities; 2263 mIWifiStaIface.getRoamingCapabilities((status, cap) -> { 2264 if (!ok(status)) return; 2265 out.maxBlacklistSize = cap.maxBlacklistSize; 2266 out.maxWhitelistSize = cap.maxWhitelistSize; 2267 ok.value = true; 2268 }); 2269 return ok.value; 2270 } catch (RemoteException e) { 2271 handleRemoteException(e); 2272 return false; 2273 } 2274 } 2275 } 2276 2277 /** 2278 * Enable/disable firmware roaming. 2279 * 2280 * @param state the intended roaming state 2281 * @return SUCCESS, FAILURE, or BUSY 2282 */ enableFirmwareRoaming(int state)2283 public int enableFirmwareRoaming(int state) { 2284 synchronized (sLock) { 2285 if (mIWifiStaIface == null) return WifiStatusCode.ERROR_NOT_STARTED; 2286 try { 2287 byte val; 2288 switch (state) { 2289 case WifiNative.DISABLE_FIRMWARE_ROAMING: 2290 val = StaRoamingState.DISABLED; 2291 break; 2292 case WifiNative.ENABLE_FIRMWARE_ROAMING: 2293 val = StaRoamingState.ENABLED; 2294 break; 2295 default: 2296 mLog.e("enableFirmwareRoaming invalid argument " + state); 2297 return WifiStatusCode.ERROR_INVALID_ARGS; 2298 } 2299 2300 WifiStatus status = mIWifiStaIface.setRoamingState(val); 2301 mVerboseLog.d("setRoamingState returned " + status.code); 2302 return status.code; 2303 } catch (RemoteException e) { 2304 handleRemoteException(e); 2305 return WifiStatusCode.ERROR_UNKNOWN; 2306 } 2307 } 2308 } 2309 2310 /** 2311 * Set firmware roaming configurations. 2312 * 2313 * @param config new roaming configuration object 2314 * @return true for success; false for failure 2315 */ configureRoaming(WifiNative.RoamingConfig config)2316 public boolean configureRoaming(WifiNative.RoamingConfig config) { 2317 synchronized (sLock) { 2318 if (mIWifiStaIface == null) return boolResult(false); 2319 try { 2320 StaRoamingConfig roamingConfig = new StaRoamingConfig(); 2321 2322 // parse the blacklist BSSIDs if any 2323 if (config.blacklistBssids != null) { 2324 for (String bssid : config.blacklistBssids) { 2325 byte[] mac = NativeUtil.macAddressToByteArray(bssid); 2326 roamingConfig.bssidBlacklist.add(mac); 2327 } 2328 } 2329 2330 // parse the whitelist SSIDs if any 2331 if (config.whitelistSsids != null) { 2332 for (String ssidStr : config.whitelistSsids) { 2333 String unquotedSsidStr = WifiInfo.removeDoubleQuotes(ssidStr); 2334 2335 int len = unquotedSsidStr.length(); 2336 if (len > 32) { 2337 mLog.err("configureRoaming: skip invalid SSID %") 2338 .r(unquotedSsidStr).flush(); 2339 continue; 2340 } 2341 byte[] ssid = new byte[len]; 2342 for (int i = 0; i < len; i++) { 2343 ssid[i] = (byte) unquotedSsidStr.charAt(i); 2344 } 2345 roamingConfig.ssidWhitelist.add(ssid); 2346 } 2347 } 2348 2349 WifiStatus status = mIWifiStaIface.configureRoaming(roamingConfig); 2350 if (!ok(status)) return false; 2351 } catch (RemoteException e) { 2352 handleRemoteException(e); 2353 return false; 2354 } catch (IllegalArgumentException e) { 2355 mLog.err("Illegal argument for roaming configuration").c(e.toString()).flush(); 2356 return false; 2357 } 2358 return true; 2359 } 2360 } 2361 2362 /** 2363 * Method to mock out the V1_1 IWifiChip retrieval in unit tests. 2364 * 2365 * @return 1.1 IWifiChip object if the device is running the 1.1 wifi hal service, null 2366 * otherwise. 2367 */ getWifiChipForV1_1Mockable()2368 protected android.hardware.wifi.V1_1.IWifiChip getWifiChipForV1_1Mockable() { 2369 if (mIWifiChip == null) return null; 2370 return android.hardware.wifi.V1_1.IWifiChip.castFrom(mIWifiChip); 2371 } 2372 frameworkToHalTxPowerScenario(int scenario)2373 private int frameworkToHalTxPowerScenario(int scenario) { 2374 switch (scenario) { 2375 case WifiNative.TX_POWER_SCENARIO_VOICE_CALL: 2376 return android.hardware.wifi.V1_1.IWifiChip.TxPowerScenario.VOICE_CALL; 2377 default: 2378 throw new IllegalArgumentException("bad scenario: " + scenario); 2379 } 2380 } 2381 2382 /** 2383 * Select one of the pre-configured TX power level scenarios or reset it back to normal. 2384 * Primarily used for meeting SAR requirements during voice calls. 2385 * 2386 * @param scenario Should be one {@link WifiNative#TX_POWER_SCENARIO_NORMAL} or 2387 * {@link WifiNative#TX_POWER_SCENARIO_VOICE_CALL}. 2388 * @return true for success; false for failure or if the HAL version does not support this API. 2389 */ selectTxPowerScenario(int scenario)2390 public boolean selectTxPowerScenario(int scenario) { 2391 synchronized (sLock) { 2392 try { 2393 android.hardware.wifi.V1_1.IWifiChip iWifiChipV11 = getWifiChipForV1_1Mockable(); 2394 if (iWifiChipV11 == null) return boolResult(false); 2395 WifiStatus status; 2396 if (scenario != WifiNative.TX_POWER_SCENARIO_NORMAL) { 2397 int halScenario; 2398 try { 2399 halScenario = frameworkToHalTxPowerScenario(scenario); 2400 } catch (IllegalArgumentException e) { 2401 mLog.err("Illegal argument for select tx power scenario") 2402 .c(e.toString()).flush(); 2403 return false; 2404 } 2405 status = iWifiChipV11.selectTxPowerScenario(halScenario); 2406 } else { 2407 status = iWifiChipV11.resetTxPowerScenario(); 2408 } 2409 if (!ok(status)) return false; 2410 } catch (RemoteException e) { 2411 handleRemoteException(e); 2412 return false; 2413 } 2414 return true; 2415 } 2416 } 2417 2418 // This creates a blob of IE elements from the array received. 2419 // TODO: This ugly conversion can be removed if we put IE elements in ScanResult. hidlIeArrayToFrameworkIeBlob(ArrayList<WifiInformationElement> ies)2420 private static byte[] hidlIeArrayToFrameworkIeBlob(ArrayList<WifiInformationElement> ies) { 2421 if (ies == null || ies.isEmpty()) return new byte[0]; 2422 ArrayList<Byte> ieBlob = new ArrayList<>(); 2423 for (WifiInformationElement ie : ies) { 2424 ieBlob.add(ie.id); 2425 ieBlob.addAll(ie.data); 2426 } 2427 return NativeUtil.byteArrayFromArrayList(ieBlob); 2428 } 2429 2430 // This is only filling up the fields of Scan Result used by Gscan clients. hidlToFrameworkScanResult(StaScanResult scanResult)2431 private static ScanResult hidlToFrameworkScanResult(StaScanResult scanResult) { 2432 if (scanResult == null) return null; 2433 ScanResult frameworkScanResult = new ScanResult(); 2434 frameworkScanResult.SSID = NativeUtil.encodeSsid(scanResult.ssid); 2435 frameworkScanResult.wifiSsid = 2436 WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(scanResult.ssid)); 2437 frameworkScanResult.BSSID = NativeUtil.macAddressFromByteArray(scanResult.bssid); 2438 frameworkScanResult.level = scanResult.rssi; 2439 frameworkScanResult.frequency = scanResult.frequency; 2440 frameworkScanResult.timestamp = scanResult.timeStampInUs; 2441 frameworkScanResult.bytes = hidlIeArrayToFrameworkIeBlob(scanResult.informationElements); 2442 return frameworkScanResult; 2443 } 2444 hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults)2445 private static ScanResult[] hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults) { 2446 if (scanResults == null || scanResults.isEmpty()) return new ScanResult[0]; 2447 ScanResult[] frameworkScanResults = new ScanResult[scanResults.size()]; 2448 int i = 0; 2449 for (StaScanResult scanResult : scanResults) { 2450 frameworkScanResults[i++] = hidlToFrameworkScanResult(scanResult); 2451 } 2452 return frameworkScanResults; 2453 } 2454 2455 /** 2456 * This just returns whether the scan was interrupted or not. 2457 */ hidlToFrameworkScanDataFlags(int flag)2458 private static int hidlToFrameworkScanDataFlags(int flag) { 2459 if (flag == StaScanDataFlagMask.INTERRUPTED) { 2460 return 1; 2461 } else { 2462 return 0; 2463 } 2464 } 2465 hidlToFrameworkScanDatas( int cmdId, ArrayList<StaScanData> scanDatas)2466 private static WifiScanner.ScanData[] hidlToFrameworkScanDatas( 2467 int cmdId, ArrayList<StaScanData> scanDatas) { 2468 if (scanDatas == null || scanDatas.isEmpty()) return new WifiScanner.ScanData[0]; 2469 WifiScanner.ScanData[] frameworkScanDatas = new WifiScanner.ScanData[scanDatas.size()]; 2470 int i = 0; 2471 for (StaScanData scanData : scanDatas) { 2472 int flags = hidlToFrameworkScanDataFlags(scanData.flags); 2473 ScanResult[] frameworkScanResults = hidlToFrameworkScanResults(scanData.results); 2474 frameworkScanDatas[i++] = 2475 new WifiScanner.ScanData(cmdId, flags, scanData.bucketsScanned, false, 2476 frameworkScanResults); 2477 } 2478 return frameworkScanDatas; 2479 } 2480 2481 /** 2482 * Callback for events on the STA interface. 2483 */ 2484 private class StaIfaceEventCallback extends IWifiStaIfaceEventCallback.Stub { 2485 @Override onBackgroundScanFailure(int cmdId)2486 public void onBackgroundScanFailure(int cmdId) { 2487 mVerboseLog.d("onBackgroundScanFailure " + cmdId); 2488 WifiNative.ScanEventHandler eventHandler; 2489 synchronized (sLock) { 2490 if (mScan == null || cmdId != mScan.cmdId) return; 2491 eventHandler = mScan.eventHandler; 2492 } 2493 eventHandler.onScanStatus(WifiNative.WIFI_SCAN_FAILED); 2494 } 2495 2496 @Override onBackgroundFullScanResult( int cmdId, int bucketsScanned, StaScanResult result)2497 public void onBackgroundFullScanResult( 2498 int cmdId, int bucketsScanned, StaScanResult result) { 2499 mVerboseLog.d("onBackgroundFullScanResult " + cmdId); 2500 WifiNative.ScanEventHandler eventHandler; 2501 synchronized (sLock) { 2502 if (mScan == null || cmdId != mScan.cmdId) return; 2503 eventHandler = mScan.eventHandler; 2504 } 2505 eventHandler.onFullScanResult(hidlToFrameworkScanResult(result), bucketsScanned); 2506 } 2507 2508 @Override onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas)2509 public void onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas) { 2510 mVerboseLog.d("onBackgroundScanResults " + cmdId); 2511 WifiNative.ScanEventHandler eventHandler; 2512 // WifiScanner currently uses the results callback to fetch the scan results. 2513 // So, simulate that by sending out the notification and then caching the results 2514 // locally. This will then be returned to WifiScanner via getScanResults. 2515 synchronized (sLock) { 2516 if (mScan == null || cmdId != mScan.cmdId) return; 2517 eventHandler = mScan.eventHandler; 2518 mScan.latestScanResults = hidlToFrameworkScanDatas(cmdId, scanDatas); 2519 } 2520 eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); 2521 } 2522 2523 @Override onRssiThresholdBreached(int cmdId, byte[ ] currBssid, int currRssi)2524 public void onRssiThresholdBreached(int cmdId, byte[/* 6 */] currBssid, int currRssi) { 2525 mVerboseLog.d("onRssiThresholdBreached " + cmdId + "currRssi " + currRssi); 2526 WifiNative.WifiRssiEventHandler eventHandler; 2527 synchronized (sLock) { 2528 if (mWifiRssiEventHandler == null || cmdId != sRssiMonCmdId) return; 2529 eventHandler = mWifiRssiEventHandler; 2530 } 2531 eventHandler.onRssiThresholdBreached((byte) currRssi); 2532 } 2533 } 2534 2535 /** 2536 * Callback for events on the STA interface. 2537 */ 2538 private class ChipEventCallback extends IWifiChipEventCallback.Stub { 2539 @Override onChipReconfigured(int modeId)2540 public void onChipReconfigured(int modeId) { 2541 mVerboseLog.d("onChipReconfigured " + modeId); 2542 } 2543 2544 @Override onChipReconfigureFailure(WifiStatus status)2545 public void onChipReconfigureFailure(WifiStatus status) { 2546 mVerboseLog.d("onChipReconfigureFailure " + status); 2547 } 2548 onIfaceAdded(int type, String name)2549 public void onIfaceAdded(int type, String name) { 2550 mVerboseLog.d("onIfaceAdded " + type + ", name: " + name); 2551 } 2552 2553 @Override onIfaceRemoved(int type, String name)2554 public void onIfaceRemoved(int type, String name) { 2555 mVerboseLog.d("onIfaceRemoved " + type + ", name: " + name); 2556 } 2557 2558 @Override onDebugRingBufferDataAvailable( WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data)2559 public void onDebugRingBufferDataAvailable( 2560 WifiDebugRingBufferStatus status, java.util.ArrayList<Byte> data) { 2561 //TODO(b/35875078) Reinstate logging when execessive callbacks are fixed 2562 // mVerboseLog.d("onDebugRingBufferDataAvailable " + status); 2563 mHalEventHandler.post(() -> { 2564 WifiNative.WifiLoggerEventHandler eventHandler; 2565 synchronized (sLock) { 2566 if (mLogEventHandler == null || status == null || data == null) return; 2567 eventHandler = mLogEventHandler; 2568 } 2569 // Because |sLock| has been released, there is a chance that we'll execute 2570 // a spurious callback (after someone has called resetLogHandler()). 2571 // 2572 // However, the alternative risks deadlock. Consider: 2573 // [T1.1] WifiDiagnostics.captureBugReport() 2574 // [T1.2] -- acquire WifiDiagnostics object's intrinsic lock 2575 // [T1.3] -> WifiVendorHal.getRingBufferData() 2576 // [T1.4] -- acquire WifiVendorHal.sLock 2577 // [T2.1] <lambda>() 2578 // [T2.2] -- acquire WifiVendorHal.sLock 2579 // [T2.3] -> WifiDiagnostics.onRingBufferData() 2580 // [T2.4] -- acquire WifiDiagnostics object's intrinsic lock 2581 // 2582 // The problem here is that the two threads acquire the locks in opposite order. 2583 // If, for example, T2.2 executes between T1.2 and 1.4, then T1 and T2 2584 // will be deadlocked. 2585 eventHandler.onRingBufferData( 2586 ringBufferStatus(status), NativeUtil.byteArrayFromArrayList(data)); 2587 }); 2588 } 2589 2590 @Override onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData)2591 public void onDebugErrorAlert(int errorCode, java.util.ArrayList<Byte> debugData) { 2592 mVerboseLog.d("onDebugErrorAlert " + errorCode); 2593 mHalEventHandler.post(() -> { 2594 WifiNative.WifiLoggerEventHandler eventHandler; 2595 synchronized (sLock) { 2596 if (mLogEventHandler == null || debugData == null) return; 2597 eventHandler = mLogEventHandler; 2598 } 2599 // See comment in onDebugRingBufferDataAvailable(), for an explanation 2600 // of why this callback is invoked without |sLock| held. 2601 eventHandler.onWifiAlert( 2602 errorCode, NativeUtil.byteArrayFromArrayList(debugData)); 2603 }); 2604 } 2605 } 2606 2607 /** 2608 * Hal Device Manager callbacks. 2609 */ 2610 public class HalDeviceManagerStatusListener implements HalDeviceManager.ManagerStatusListener { 2611 @Override onStatusChanged()2612 public void onStatusChanged() { 2613 boolean isReady = mHalDeviceManager.isReady(); 2614 boolean isStarted = mHalDeviceManager.isStarted(); 2615 2616 mVerboseLog.i("Device Manager onStatusChanged. isReady(): " + isReady 2617 + ", isStarted(): " + isStarted); 2618 if (!isReady) { 2619 // Probably something unpleasant, e.g. the server died 2620 WifiNative.VendorHalDeathEventHandler handler; 2621 synchronized (sLock) { 2622 clearState(); 2623 handler = mDeathEventHandler; 2624 } 2625 if (handler != null) { 2626 handler.onDeath(); 2627 } 2628 } 2629 } 2630 } 2631 } 2632