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