1 /* 2 * Copyright (C) 2022 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 17 package com.android.server.wifi.hal; 18 19 import static android.net.wifi.WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.content.Context; 24 import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback; 25 import android.hardware.wifi.V1_0.StaBackgroundScanBucketEventReportSchemeMask; 26 import android.hardware.wifi.V1_0.StaBackgroundScanBucketParameters; 27 import android.hardware.wifi.V1_0.StaBackgroundScanParameters; 28 import android.hardware.wifi.V1_0.StaLinkLayerIfaceStats; 29 import android.hardware.wifi.V1_0.StaLinkLayerRadioStats; 30 import android.hardware.wifi.V1_0.StaLinkLayerStats; 31 import android.hardware.wifi.V1_0.StaRoamingConfig; 32 import android.hardware.wifi.V1_0.StaRoamingState; 33 import android.hardware.wifi.V1_0.StaScanData; 34 import android.hardware.wifi.V1_0.StaScanDataFlagMask; 35 import android.hardware.wifi.V1_0.StaScanResult; 36 import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType; 37 import android.hardware.wifi.V1_0.WifiDebugRxPacketFate; 38 import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport; 39 import android.hardware.wifi.V1_0.WifiDebugTxPacketFate; 40 import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport; 41 import android.hardware.wifi.V1_0.WifiStatus; 42 import android.hardware.wifi.V1_0.WifiStatusCode; 43 import android.hardware.wifi.V1_5.WifiBand; 44 import android.net.MacAddress; 45 import android.net.apf.ApfCapabilities; 46 import android.net.wifi.ScanResult; 47 import android.net.wifi.WifiManager; 48 import android.net.wifi.WifiScanner; 49 import android.net.wifi.WifiSsid; 50 import android.os.RemoteException; 51 import android.util.Log; 52 53 import com.android.internal.annotations.VisibleForTesting; 54 import com.android.server.wifi.SsidTranslator; 55 import com.android.server.wifi.WifiLinkLayerStats; 56 import com.android.server.wifi.WifiLoggerHal; 57 import com.android.server.wifi.WifiNative; 58 import com.android.server.wifi.util.BitMask; 59 import com.android.server.wifi.util.GeneralUtil; 60 import com.android.server.wifi.util.NativeUtil; 61 import com.android.wifi.resources.R; 62 63 import java.util.ArrayList; 64 import java.util.List; 65 import java.util.function.Supplier; 66 67 68 /** 69 * HIDL implementation of the IWifiStaIface interface. 70 */ 71 public class WifiStaIfaceHidlImpl implements IWifiStaIface { 72 private static final String TAG = "WifiStaIfaceHidlImpl"; 73 private android.hardware.wifi.V1_0.IWifiStaIface mWifiStaIface; 74 private String mIfaceName; 75 private IWifiStaIfaceEventCallback mHalCallback; 76 private WifiStaIface.Callback mFrameworkCallback; 77 private Context mContext; 78 private SsidTranslator mSsidTranslator; 79 private static final int DEFAULT_LINK = 0; 80 private static final int NUM_OF_LINKS = 1; 81 private final boolean mWifiLinkLayerAllRadiosStatsAggregationEnabled; 82 WifiStaIfaceHidlImpl(@onNull android.hardware.wifi.V1_0.IWifiStaIface staIface, @NonNull Context context, @NonNull SsidTranslator ssidTranslator)83 public WifiStaIfaceHidlImpl(@NonNull android.hardware.wifi.V1_0.IWifiStaIface staIface, 84 @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { 85 mWifiStaIface = staIface; 86 mContext = context; 87 mSsidTranslator = ssidTranslator; 88 mHalCallback = new StaIfaceEventCallback(); 89 mWifiLinkLayerAllRadiosStatsAggregationEnabled = mContext.getResources() 90 .getBoolean(R.bool.config_wifiLinkLayerAllRadiosStatsAggregationEnabled); 91 } 92 93 /** 94 * See comments for {@link IWifiStaIface#registerFrameworkCallback(WifiStaIface.Callback)} 95 */ registerFrameworkCallback(WifiStaIface.Callback callback)96 public boolean registerFrameworkCallback(WifiStaIface.Callback callback) { 97 final String methodStr = "registerFrameworkCallback"; 98 return validateAndCall(methodStr, false, 99 () -> registerFrameworkCallbackInternal(methodStr, callback)); 100 } 101 102 /** 103 * See comments for {@link IWifiStaIface#getName()} 104 */ 105 @Nullable getName()106 public String getName() { 107 final String methodStr = "getName"; 108 return validateAndCall(methodStr, null, 109 () -> getNameInternal(methodStr)); 110 } 111 112 /** 113 * See comments for {@link IWifiStaIface#configureRoaming(List, List)} 114 */ configureRoaming(List<MacAddress> bssidBlocklist, List<byte[]> ssidAllowlist)115 public boolean configureRoaming(List<MacAddress> bssidBlocklist, 116 List<byte[]> ssidAllowlist) { 117 final String methodStr = "configureRoaming"; 118 return validateAndCall(methodStr, false, 119 () -> configureRoamingInternal(methodStr, bssidBlocklist, ssidAllowlist)); 120 } 121 122 /** 123 * See comments for {@link IWifiStaIface#enableLinkLayerStatsCollection(boolean)} 124 */ enableLinkLayerStatsCollection(boolean debug)125 public boolean enableLinkLayerStatsCollection(boolean debug) { 126 final String methodStr = "enableLinkLayerStatsCollection"; 127 return validateAndCall(methodStr, false, 128 () -> enableLinkLayerStatsCollectionInternal(methodStr, debug)); 129 } 130 131 /** 132 * See comments for {@link IWifiStaIface#enableNdOffload(boolean)} 133 */ enableNdOffload(boolean enable)134 public boolean enableNdOffload(boolean enable) { 135 final String methodStr = "enableNdOffload"; 136 return validateAndCall(methodStr, false, 137 () -> enableNdOffloadInternal(methodStr, enable)); 138 } 139 140 /** 141 * See comments for {@link IWifiStaIface#getApfPacketFilterCapabilities()} 142 */ getApfPacketFilterCapabilities()143 public ApfCapabilities getApfPacketFilterCapabilities() { 144 final String methodStr = "getApfPacketFilterCapabilities"; 145 return validateAndCall(methodStr, new ApfCapabilities(0, 0, 0), 146 () -> getApfPacketFilterCapabilitiesInternal(methodStr)); 147 } 148 149 /** 150 * See comments for {@link IWifiStaIface#getBackgroundScanCapabilities()} 151 */ 152 @Nullable getBackgroundScanCapabilities()153 public WifiNative.ScanCapabilities getBackgroundScanCapabilities() { 154 final String methodStr = "getBackgroundScanCapabilities"; 155 return validateAndCall(methodStr, null, 156 () -> getBackgroundScanCapabilitiesInternal(methodStr)); 157 } 158 159 /** 160 * See comments for {@link IWifiStaIface#getCapabilities()} 161 */ getCapabilities()162 public long getCapabilities() { 163 final String methodStr = "getCapabilities"; 164 return validateAndCall(methodStr, 0L, 165 () -> getCapabilitiesInternal(methodStr)); 166 } 167 168 /** 169 * See comments for {@link IWifiStaIface#getDebugRxPacketFates()} 170 */ getDebugRxPacketFates()171 public List<WifiNative.RxFateReport> getDebugRxPacketFates() { 172 final String methodStr = "getDebugRxPacketFates"; 173 return validateAndCall(methodStr, new ArrayList<>(), 174 () -> getDebugRxPacketFatesInternal(methodStr)); 175 } 176 177 /** 178 * See comments for {@link IWifiStaIface#getDebugTxPacketFates()} 179 */ getDebugTxPacketFates()180 public List<WifiNative.TxFateReport> getDebugTxPacketFates() { 181 final String methodStr = "getDebugTxPacketFates"; 182 return validateAndCall(methodStr, new ArrayList<>(), 183 () -> getDebugTxPacketFatesInternal(methodStr)); 184 } 185 186 /** 187 * See comments for {@link IWifiStaIface#getFactoryMacAddress()} 188 */ 189 @Nullable getFactoryMacAddress()190 public MacAddress getFactoryMacAddress() { 191 final String methodStr = "getFactoryMacAddress"; 192 return validateAndCall(methodStr, null, 193 () -> getFactoryMacAddressInternal(methodStr)); 194 } 195 196 /** 197 * See comments for {@link IWifiStaIface#getCachedScanData()} 198 */ 199 @Nullable getCachedScanData()200 public WifiScanner.ScanData getCachedScanData() { 201 Log.d(TAG, "getCachedScanData is not implemented by HIDL"); 202 return null; 203 } 204 205 /** 206 * See comments for {@link IWifiStaIface#getLinkLayerStats()} 207 */ 208 @Nullable getLinkLayerStats()209 public WifiLinkLayerStats getLinkLayerStats() { 210 final String methodStr = "getLinkLayerStats"; 211 return validateAndCall(methodStr, null, 212 () -> getLinkLayerStatsInternal(methodStr)); 213 } 214 215 /** 216 * See comments for {@link IWifiStaIface#getRoamingCapabilities()} 217 */ 218 @Nullable getRoamingCapabilities()219 public WifiNative.RoamingCapabilities getRoamingCapabilities() { 220 final String methodStr = "getRoamingCapabilities"; 221 return validateAndCall(methodStr, null, 222 () -> getRoamingCapabilitiesInternal(methodStr)); 223 } 224 225 /** 226 * See comments for {@link IWifiStaIface#installApfPacketFilter(byte[])} 227 */ installApfPacketFilter(byte[] program)228 public boolean installApfPacketFilter(byte[] program) { 229 final String methodStr = "installApfPacketFilter"; 230 return validateAndCall(methodStr, false, 231 () -> installApfPacketFilterInternal(methodStr, program)); 232 } 233 234 /** 235 * See comments for {@link IWifiStaIface#readApfPacketFilterData()} 236 */ 237 @Nullable readApfPacketFilterData()238 public byte[] readApfPacketFilterData() { 239 final String methodStr = "readApfPacketFilterData"; 240 return validateAndCall(methodStr, null, 241 () -> readApfPacketFilterDataInternal(methodStr)); 242 } 243 244 /** 245 * See comments for {@link IWifiStaIface#setMacAddress(MacAddress)} 246 */ setMacAddress(MacAddress mac)247 public boolean setMacAddress(MacAddress mac) { 248 final String methodStr = "setMacAddress"; 249 return validateAndCall(methodStr, false, 250 () -> setMacAddressInternal(methodStr, mac)); 251 } 252 253 /** 254 * See comments for {@link IWifiStaIface#setRoamingState(int)} 255 */ setRoamingState( @ifiNative.RoamingEnableState int state)256 public @WifiNative.RoamingEnableStatus int setRoamingState( 257 @WifiNative.RoamingEnableState int state) { 258 final String methodStr = "setRoamingState"; 259 return validateAndCall(methodStr, WifiNative.SET_FIRMWARE_ROAMING_FAILURE, 260 () -> setRoamingStateInternal(methodStr, state)); 261 } 262 263 /** 264 * See comments for {@link IWifiStaIface#setScanMode(boolean)} 265 */ setScanMode(boolean enable)266 public boolean setScanMode(boolean enable) { 267 final String methodStr = "setScanMode"; 268 return validateAndCall(methodStr, false, 269 () -> setScanModeInternal(methodStr, enable)); 270 } 271 272 /** 273 * See comments for 274 * {@link IWifiStaIface#startBackgroundScan(int, WifiStaIface.StaBackgroundScanParameters)} 275 */ startBackgroundScan(int cmdId, WifiStaIface.StaBackgroundScanParameters params)276 public boolean startBackgroundScan(int cmdId, WifiStaIface.StaBackgroundScanParameters params) { 277 final String methodStr = "startBackgroundScan"; 278 return validateAndCall(methodStr, false, 279 () -> startBackgroundScanInternal(methodStr, cmdId, params)); 280 } 281 282 /** 283 * See comments for {@link IWifiStaIface#startDebugPacketFateMonitoring()} 284 */ startDebugPacketFateMonitoring()285 public boolean startDebugPacketFateMonitoring() { 286 final String methodStr = "startDebugPacketFateMonitoring"; 287 return validateAndCall(methodStr, false, 288 () -> startDebugPacketFateMonitoringInternal(methodStr)); 289 } 290 291 /** 292 * See comments for 293 * {@link IWifiStaIface#startRssiMonitoring(int, int, int)} 294 */ startRssiMonitoring(int cmdId, int maxRssi, int minRssi)295 public boolean startRssiMonitoring(int cmdId, int maxRssi, int minRssi) { 296 final String methodStr = "startRssiMonitoring"; 297 return validateAndCall(methodStr, false, 298 () -> startRssiMonitoringInternal(methodStr, cmdId, maxRssi, minRssi)); 299 } 300 301 /** 302 * See comments for {@link IWifiStaIface#startSendingKeepAlivePackets(int, byte[], int, 303 * MacAddress, MacAddress, int)} 304 */ startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType, MacAddress srcAddress, MacAddress dstAddress, int periodInMs)305 public boolean startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType, 306 MacAddress srcAddress, MacAddress dstAddress, int periodInMs) { 307 final String methodStr = "startSendingKeepAlivePackets"; 308 return validateAndCall(methodStr, false, 309 () -> startSendingKeepAlivePacketsInternal(methodStr, cmdId, ipPacketData, 310 etherType, srcAddress, dstAddress, periodInMs)); 311 } 312 313 /** 314 * See comments for {@link IWifiStaIface#stopBackgroundScan(int)} 315 */ stopBackgroundScan(int cmdId)316 public boolean stopBackgroundScan(int cmdId) { 317 final String methodStr = "stopBackgroundScan"; 318 return validateAndCall(methodStr, false, 319 () -> stopBackgroundScanInternal(methodStr, cmdId)); 320 } 321 322 /** 323 * See comments for {@link IWifiStaIface#stopRssiMonitoring(int)} 324 */ stopRssiMonitoring(int cmdId)325 public boolean stopRssiMonitoring(int cmdId) { 326 final String methodStr = "stopRssiMonitoring"; 327 return validateAndCall(methodStr, false, 328 () -> stopRssiMonitoringInternal(methodStr, cmdId)); 329 } 330 331 /** 332 * See comments for {@link IWifiStaIface#stopSendingKeepAlivePackets(int)} 333 */ stopSendingKeepAlivePackets(int cmdId)334 public boolean stopSendingKeepAlivePackets(int cmdId) { 335 final String methodStr = "stopSendingKeepAlivePackets"; 336 return validateAndCall(methodStr, false, 337 () -> stopSendingKeepAlivePacketsInternal(methodStr, cmdId)); 338 } 339 340 /** 341 * See comments for {@link IWifiStaIface#setDtimMultiplier(int)} 342 */ setDtimMultiplier(int multiplier)343 public boolean setDtimMultiplier(int multiplier) { 344 Log.d(TAG, "setDtimMultiplier is not implemented by HIDL"); 345 return false; 346 } 347 348 /** 349 * See comments for {@link IWifiStaIface#setRoamingMode(int)} 350 */ setRoamingMode(int roamingMode)351 public int setRoamingMode(int roamingMode) { 352 Log.d(TAG, "setRoamingMode is not implemented by HIDL"); 353 return 0; 354 } 355 356 // Internal Implementations 357 registerFrameworkCallbackInternal(String methodStr, WifiStaIface.Callback callback)358 private boolean registerFrameworkCallbackInternal(String methodStr, 359 WifiStaIface.Callback callback) { 360 if (mFrameworkCallback != null) { 361 Log.e(TAG, "Framework callback is already registered"); 362 return false; 363 } else if (callback == null) { 364 Log.e(TAG, "Cannot register a null callback"); 365 return false; 366 } 367 368 try { 369 WifiStatus status = mWifiStaIface.registerEventCallback(mHalCallback); 370 if (!isOk(status, methodStr)) return false; 371 mFrameworkCallback = callback; 372 return true; 373 } catch (RemoteException e) { 374 handleRemoteException(e, methodStr); 375 return false; 376 } 377 } 378 getNameInternal(String methodStr)379 private String getNameInternal(String methodStr) { 380 if (mIfaceName != null) return mIfaceName; 381 GeneralUtil.Mutable<String> nameResp = new GeneralUtil.Mutable<>(); 382 try { 383 mWifiStaIface.getName((WifiStatus status, String name) -> { 384 if (isOk(status, methodStr)) { 385 nameResp.value = name; 386 mIfaceName = name; 387 } 388 }); 389 } catch (RemoteException e) { 390 handleRemoteException(e, methodStr); 391 } 392 return nameResp.value; 393 } 394 configureRoamingInternal(String methodStr, List<MacAddress> bssidBlocklist, List<byte[]> ssidAllowlist)395 private boolean configureRoamingInternal(String methodStr, List<MacAddress> bssidBlocklist, 396 List<byte[]> ssidAllowlist) { 397 StaRoamingConfig config = new StaRoamingConfig(); 398 config.ssidWhitelist = new ArrayList<>(ssidAllowlist); 399 config.bssidBlacklist = new ArrayList<>(); 400 for (MacAddress bssid : bssidBlocklist) { 401 config.bssidBlacklist.add(bssid.toByteArray()); 402 } 403 try { 404 WifiStatus status = mWifiStaIface.configureRoaming(config); 405 return isOk(status, methodStr); 406 } catch (RemoteException e) { 407 handleRemoteException(e, methodStr); 408 return false; 409 } 410 } 411 enableLinkLayerStatsCollectionInternal(String methodStr, boolean debug)412 private boolean enableLinkLayerStatsCollectionInternal(String methodStr, boolean debug) { 413 try { 414 WifiStatus status = mWifiStaIface.enableLinkLayerStatsCollection(debug); 415 return isOk(status, methodStr); 416 } catch (RemoteException e) { 417 handleRemoteException(e, methodStr); 418 return false; 419 } 420 } 421 enableNdOffloadInternal(String methodStr, boolean enable)422 private boolean enableNdOffloadInternal(String methodStr, boolean enable) { 423 try { 424 WifiStatus status = mWifiStaIface.enableNdOffload(enable); 425 return isOk(status, methodStr); 426 } catch (RemoteException e) { 427 handleRemoteException(e, methodStr); 428 return false; 429 } 430 } 431 getApfPacketFilterCapabilitiesInternal(String methodStr)432 private ApfCapabilities getApfPacketFilterCapabilitiesInternal(String methodStr) { 433 GeneralUtil.Mutable<ApfCapabilities> apfResp = 434 new GeneralUtil.Mutable<>(new ApfCapabilities(0, 0, 0)); 435 try { 436 mWifiStaIface.getApfPacketFilterCapabilities((status, caps) -> { 437 if (isOk(status, methodStr)) { 438 apfResp.value = new ApfCapabilities( 439 /* apfVersionSupported */ caps.version, 440 /* maximumApfProgramSize */ caps.maxLength, 441 /* apfPacketFormat */ android.system.OsConstants.ARPHRD_ETHER); 442 } 443 }); 444 } catch (RemoteException e) { 445 handleRemoteException(e, methodStr); 446 } 447 return apfResp.value; 448 } 449 getBackgroundScanCapabilitiesInternal(String methodStr)450 private WifiNative.ScanCapabilities getBackgroundScanCapabilitiesInternal(String methodStr) { 451 GeneralUtil.Mutable<WifiNative.ScanCapabilities> scanResp = new GeneralUtil.Mutable<>(); 452 try { 453 mWifiStaIface.getBackgroundScanCapabilities((status, caps) -> { 454 if (isOk(status, methodStr)) { 455 WifiNative.ScanCapabilities out = new WifiNative.ScanCapabilities(); 456 out.max_scan_cache_size = caps.maxCacheSize; 457 out.max_ap_cache_per_scan = caps.maxApCachePerScan; 458 out.max_scan_buckets = caps.maxBuckets; 459 out.max_rssi_sample_size = 0; 460 out.max_scan_reporting_threshold = caps.maxReportingThreshold; 461 scanResp.value = out; 462 } 463 }); 464 } catch (RemoteException e) { 465 handleRemoteException(e, methodStr); 466 } 467 return scanResp.value; 468 } 469 getCapabilitiesInternal(String methodStr)470 private long getCapabilitiesInternal(String methodStr) { 471 GeneralUtil.Mutable<Long> capsResp = new GeneralUtil.Mutable<>(0L); 472 try { 473 mWifiStaIface.getCapabilities((status, caps) -> { 474 if (isOk(status, methodStr)) { 475 capsResp.value = halToFrameworkStaIfaceCapability(caps); 476 } 477 }); 478 } catch (RemoteException e) { 479 handleRemoteException(e, methodStr); 480 } 481 return capsResp.value; 482 } 483 getDebugRxPacketFatesInternal(String methodStr)484 private List<WifiNative.RxFateReport> getDebugRxPacketFatesInternal(String methodStr) { 485 try { 486 List<WifiNative.RxFateReport> reportBufs = new ArrayList<>(); 487 mWifiStaIface.getDebugRxPacketFates((status, fates) -> { 488 if (!isOk(status, methodStr)) return; 489 for (WifiDebugRxPacketFateReport fate : fates) { 490 if (reportBufs.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break; 491 byte code = halToFrameworkRxPktFate(fate.fate); 492 long us = fate.frameInfo.driverTimestampUsec; 493 byte type = halToFrameworkPktFateFrameType(fate.frameInfo.frameType); 494 byte[] frame = NativeUtil.byteArrayFromArrayList( 495 fate.frameInfo.frameContent); 496 reportBufs.add(new WifiNative.RxFateReport(code, us, type, frame)); 497 } 498 }); 499 return reportBufs; 500 } catch (RemoteException e) { 501 handleRemoteException(e, methodStr); 502 return new ArrayList<>(); 503 } 504 } 505 getDebugTxPacketFatesInternal(String methodStr)506 private List<WifiNative.TxFateReport> getDebugTxPacketFatesInternal(String methodStr) { 507 try { 508 List<WifiNative.TxFateReport> reportBufs = new ArrayList<>(); 509 mWifiStaIface.getDebugTxPacketFates((status, fates) -> { 510 if (!isOk(status, methodStr)) return; 511 for (WifiDebugTxPacketFateReport fate : fates) { 512 if (reportBufs.size() >= WifiLoggerHal.MAX_FATE_LOG_LEN) break; 513 byte code = halToFrameworkTxPktFate(fate.fate); 514 long us = fate.frameInfo.driverTimestampUsec; 515 byte type = halToFrameworkPktFateFrameType(fate.frameInfo.frameType); 516 byte[] frame = NativeUtil.byteArrayFromArrayList( 517 fate.frameInfo.frameContent); 518 reportBufs.add(new WifiNative.TxFateReport(code, us, type, frame)); 519 } 520 }); 521 return reportBufs; 522 } catch (RemoteException e) { 523 handleRemoteException(e, methodStr); 524 return new ArrayList<>(); 525 } 526 } 527 getFactoryMacAddressInternal(String methodStr)528 private MacAddress getFactoryMacAddressInternal(String methodStr) { 529 GeneralUtil.Mutable<MacAddress> macResp = new GeneralUtil.Mutable<>(); 530 try { 531 android.hardware.wifi.V1_3.IWifiStaIface sta13 = getWifiStaIfaceV1_3Mockable(); 532 if (sta13 == null) return null; 533 sta13.getFactoryMacAddress((status, macBytes) -> { 534 if (isOk(status, methodStr)) { 535 macResp.value = MacAddress.fromBytes(macBytes); 536 } 537 }); 538 } catch (RemoteException e) { 539 handleRemoteException(e, methodStr); 540 } 541 return macResp.value; 542 } 543 getLinkLayerStatsInternal(String methodStr)544 private WifiLinkLayerStats getLinkLayerStatsInternal(String methodStr) { 545 if (getWifiStaIfaceV1_6Mockable() != null) { 546 return getLinkLayerStatsV1_6Internal(methodStr); 547 } else if (getWifiStaIfaceV1_5Mockable() != null) { 548 return getLinkLayerStatsV1_5Internal(methodStr); 549 } else if (getWifiStaIfaceV1_3Mockable() != null) { 550 return getLinkLayerStatsV1_3Internal(methodStr); 551 } else { 552 return getLinkLayerStatsV1_0Internal(methodStr); 553 } 554 } 555 getLinkLayerStatsV1_0Internal(String methodStr)556 private WifiLinkLayerStats getLinkLayerStatsV1_0Internal(String methodStr) { 557 final String methodStrV1_0 = methodStr + "V1_0"; 558 GeneralUtil.Mutable<StaLinkLayerStats> statsResp = new GeneralUtil.Mutable<>(); 559 try { 560 mWifiStaIface.getLinkLayerStats((status, stats) -> { 561 if (isOk(status, methodStrV1_0)) { 562 statsResp.value = stats; 563 } 564 }); 565 } catch (RemoteException e) { 566 handleRemoteException(e, methodStrV1_0); 567 return null; 568 } 569 return frameworkFromHalLinkLayerStats(statsResp.value); 570 } 571 getLinkLayerStatsV1_3Internal(String methodStr)572 private WifiLinkLayerStats getLinkLayerStatsV1_3Internal(String methodStr) { 573 final String methodStrV1_3 = methodStr + "V1_3"; 574 GeneralUtil.Mutable<android.hardware.wifi.V1_3.StaLinkLayerStats> statsResp = 575 new GeneralUtil.Mutable<>(); 576 try { 577 android.hardware.wifi.V1_3.IWifiStaIface iface13 = getWifiStaIfaceV1_3Mockable(); 578 if (iface13 == null) return null; 579 iface13.getLinkLayerStats_1_3((status, stats) -> { 580 if (isOk(status, methodStrV1_3)) { 581 statsResp.value = stats; 582 } 583 }); 584 } catch (RemoteException e) { 585 handleRemoteException(e, methodStrV1_3); 586 return null; 587 } 588 return frameworkFromHalLinkLayerStats_1_3(statsResp.value); 589 } 590 getLinkLayerStatsV1_5Internal(String methodStr)591 private WifiLinkLayerStats getLinkLayerStatsV1_5Internal(String methodStr) { 592 final String methodStrV1_5 = methodStr + "V1_5"; 593 GeneralUtil.Mutable<android.hardware.wifi.V1_5.StaLinkLayerStats> statsResp = 594 new GeneralUtil.Mutable<>(); 595 try { 596 android.hardware.wifi.V1_5.IWifiStaIface iface15 = getWifiStaIfaceV1_5Mockable(); 597 if (iface15 == null) return null; 598 iface15.getLinkLayerStats_1_5((status, stats) -> { 599 if (isOk(status, methodStrV1_5)) { 600 statsResp.value = stats; 601 } 602 }); 603 } catch (RemoteException e) { 604 handleRemoteException(e, methodStrV1_5); 605 return null; 606 } 607 return frameworkFromHalLinkLayerStats_1_5(statsResp.value); 608 } 609 getLinkLayerStatsV1_6Internal(String methodStr)610 private WifiLinkLayerStats getLinkLayerStatsV1_6Internal(String methodStr) { 611 final String methodStrV1_6 = methodStr + "V1_6"; 612 GeneralUtil.Mutable<android.hardware.wifi.V1_6.StaLinkLayerStats> statsResp = 613 new GeneralUtil.Mutable<>(); 614 try { 615 android.hardware.wifi.V1_6.IWifiStaIface iface16 = getWifiStaIfaceV1_6Mockable(); 616 if (iface16 == null) return null; 617 iface16.getLinkLayerStats_1_6((status, stats) -> { 618 if (isOk(status, methodStrV1_6)) { 619 statsResp.value = stats; 620 } 621 }); 622 } catch (RemoteException e) { 623 handleRemoteException(e, methodStrV1_6); 624 return null; 625 } catch (Exception e) { 626 handleException(e, methodStrV1_6); 627 return null; 628 } 629 return frameworkFromHalLinkLayerStats_1_6(statsResp.value); 630 } 631 getRoamingCapabilitiesInternal(String methodStr)632 private WifiNative.RoamingCapabilities getRoamingCapabilitiesInternal(String methodStr) { 633 GeneralUtil.Mutable<WifiNative.RoamingCapabilities> capsResp = new GeneralUtil.Mutable<>(); 634 try { 635 mWifiStaIface.getRoamingCapabilities((status, caps) -> { 636 if (isOk(status, methodStr)) { 637 WifiNative.RoamingCapabilities out = new WifiNative.RoamingCapabilities(); 638 out.maxBlocklistSize = caps.maxBlacklistSize; 639 out.maxAllowlistSize = caps.maxWhitelistSize; 640 capsResp.value = out; 641 } 642 }); 643 } catch (RemoteException e) { 644 handleRemoteException(e, methodStr); 645 } 646 return capsResp.value; 647 } 648 installApfPacketFilterInternal(String methodStr, byte[] program)649 private boolean installApfPacketFilterInternal(String methodStr, byte[] program) { 650 try { 651 int cmdId = 0; // We only aspire to support one program at a time. 652 ArrayList<Byte> filter = NativeUtil.byteArrayToArrayList(program); 653 WifiStatus status = mWifiStaIface.installApfPacketFilter(cmdId, filter); 654 return isOk(status, methodStr); 655 } catch (RemoteException e) { 656 handleRemoteException(e, methodStr); 657 return false; 658 } 659 } 660 readApfPacketFilterDataInternal(String methodStr)661 private byte[] readApfPacketFilterDataInternal(String methodStr) { 662 GeneralUtil.Mutable<byte[]> dataResp = new GeneralUtil.Mutable<>(); 663 try { 664 android.hardware.wifi.V1_2.IWifiStaIface iface12 = getWifiStaIfaceV1_2Mockable(); 665 if (iface12 == null) return null; 666 iface12.readApfPacketFilterData((status, data) -> { 667 if (isOk(status, methodStr)) { 668 dataResp.value = NativeUtil.byteArrayFromArrayList(data); 669 } 670 }); 671 } catch (RemoteException e) { 672 handleRemoteException(e, methodStr); 673 } 674 return dataResp.value; 675 } 676 setMacAddressInternal(String methodStr, MacAddress mac)677 private boolean setMacAddressInternal(String methodStr, MacAddress mac) { 678 try { 679 android.hardware.wifi.V1_2.IWifiStaIface iface12 = getWifiStaIfaceV1_2Mockable(); 680 if (iface12 == null) return false; 681 byte[] macBytes = mac.toByteArray(); 682 WifiStatus status = iface12.setMacAddress(macBytes); 683 return isOk(status, methodStr); 684 } catch (RemoteException e) { 685 handleRemoteException(e, methodStr); 686 return false; 687 } 688 } 689 setRoamingStateInternal(String methodStr, @WifiNative.RoamingEnableState int state)690 private @WifiNative.RoamingEnableStatus int setRoamingStateInternal(String methodStr, 691 @WifiNative.RoamingEnableState int state) { 692 byte halState = frameworkToHalStaRoamingState(state); 693 if (halState == -1) { 694 return WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE; 695 } 696 697 try { 698 WifiStatus status = mWifiStaIface.setRoamingState(halState); 699 if (isOk(status, methodStr)) { 700 return WifiNative.SET_FIRMWARE_ROAMING_SUCCESS; 701 } else if (status.code == WifiStatusCode.ERROR_BUSY) { 702 return WifiNative.SET_FIRMWARE_ROAMING_BUSY; 703 } else { 704 return WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE; 705 } 706 } catch (RemoteException e) { 707 handleRemoteException(e, methodStr); 708 return WifiStaIface.SET_ROAMING_STATE_FAILURE_CODE; 709 } 710 } 711 setScanModeInternal(String methodStr, boolean enable)712 private boolean setScanModeInternal(String methodStr, boolean enable) { 713 try { 714 android.hardware.wifi.V1_5.IWifiStaIface iface15 = getWifiStaIfaceV1_5Mockable(); 715 if (iface15 == null) return false; 716 WifiStatus status = iface15.setScanMode(enable); 717 return isOk(status, methodStr); 718 } catch (RemoteException e) { 719 handleRemoteException(e, methodStr); 720 return false; 721 } 722 } 723 startBackgroundScanInternal(String methodStr, int cmdId, WifiStaIface.StaBackgroundScanParameters params)724 private boolean startBackgroundScanInternal(String methodStr, int cmdId, 725 WifiStaIface.StaBackgroundScanParameters params) { 726 try { 727 StaBackgroundScanParameters halParams = frameworkToHalBackgroundScanParams(params); 728 WifiStatus status = mWifiStaIface.startBackgroundScan(cmdId, halParams); 729 return isOk(status, methodStr); 730 } catch (RemoteException e) { 731 handleRemoteException(e, methodStr); 732 return false; 733 } 734 } 735 startDebugPacketFateMonitoringInternal(String methodStr)736 private boolean startDebugPacketFateMonitoringInternal(String methodStr) { 737 try { 738 WifiStatus status = mWifiStaIface.startDebugPacketFateMonitoring(); 739 return isOk(status, methodStr); 740 } catch (RemoteException e) { 741 handleRemoteException(e, methodStr); 742 return false; 743 } 744 } 745 startRssiMonitoringInternal(String methodStr, int cmdId, int maxRssi, int minRssi)746 private boolean startRssiMonitoringInternal(String methodStr, int cmdId, int maxRssi, 747 int minRssi) { 748 try { 749 WifiStatus status = mWifiStaIface.startRssiMonitoring(cmdId, maxRssi, minRssi); 750 return isOk(status, methodStr); 751 } catch (RemoteException e) { 752 handleRemoteException(e, methodStr); 753 return false; 754 } 755 } 756 startSendingKeepAlivePacketsInternal(String methodStr, int cmdId, byte[] ipPacketData, int etherType, MacAddress srcAddress, MacAddress dstAddress, int periodInMs)757 private boolean startSendingKeepAlivePacketsInternal(String methodStr, int cmdId, 758 byte[] ipPacketData, int etherType, MacAddress srcAddress, MacAddress dstAddress, 759 int periodInMs) { 760 try { 761 ArrayList<Byte> data = NativeUtil.byteArrayToArrayList(ipPacketData); 762 byte[] srcMac = srcAddress.toByteArray(); 763 byte[] dstMac = dstAddress.toByteArray(); 764 WifiStatus status = mWifiStaIface.startSendingKeepAlivePackets( 765 cmdId, data, (short) etherType, srcMac, dstMac, periodInMs); 766 return isOk(status, methodStr); 767 } catch (RemoteException e) { 768 handleRemoteException(e, methodStr); 769 return false; 770 } 771 } 772 stopBackgroundScanInternal(String methodStr, int cmdId)773 private boolean stopBackgroundScanInternal(String methodStr, int cmdId) { 774 try { 775 WifiStatus status = mWifiStaIface.stopBackgroundScan(cmdId); 776 return isOk(status, methodStr); 777 } catch (RemoteException e) { 778 handleRemoteException(e, methodStr); 779 return false; 780 } 781 } 782 stopRssiMonitoringInternal(String methodStr, int cmdId)783 private boolean stopRssiMonitoringInternal(String methodStr, int cmdId) { 784 try { 785 WifiStatus status = mWifiStaIface.stopRssiMonitoring(cmdId); 786 return isOk(status, methodStr); 787 } catch (RemoteException e) { 788 handleRemoteException(e, methodStr); 789 return false; 790 } 791 } 792 stopSendingKeepAlivePacketsInternal(String methodStr, int cmdId)793 private boolean stopSendingKeepAlivePacketsInternal(String methodStr, int cmdId) { 794 try { 795 WifiStatus status = mWifiStaIface.stopSendingKeepAlivePackets(cmdId); 796 return isOk(status, methodStr); 797 } catch (RemoteException e) { 798 handleRemoteException(e, methodStr); 799 return false; 800 } 801 } 802 803 804 // Helper Functions 805 frameworkToHalStaRoamingState(@ifiNative.RoamingEnableState int state)806 private static byte frameworkToHalStaRoamingState(@WifiNative.RoamingEnableState int state) { 807 switch (state) { 808 case WifiNative.DISABLE_FIRMWARE_ROAMING: 809 return StaRoamingState.DISABLED; 810 case WifiNative.ENABLE_FIRMWARE_ROAMING: 811 return StaRoamingState.ENABLED; 812 default: 813 Log.e(TAG, "Invalid firmware roaming state enum: " + state); 814 return -1; 815 } 816 } 817 halToFrameworkPktFateFrameType(int type)818 private static byte halToFrameworkPktFateFrameType(int type) { 819 switch (type) { 820 case WifiDebugPacketFateFrameType.UNKNOWN: 821 return WifiLoggerHal.FRAME_TYPE_UNKNOWN; 822 case WifiDebugPacketFateFrameType.ETHERNET_II: 823 return WifiLoggerHal.FRAME_TYPE_ETHERNET_II; 824 case WifiDebugPacketFateFrameType.MGMT_80211: 825 return WifiLoggerHal.FRAME_TYPE_80211_MGMT; 826 default: 827 throw new IllegalArgumentException("bad " + type); 828 } 829 } 830 halToFrameworkRxPktFate(int type)831 private static byte halToFrameworkRxPktFate(int type) { 832 switch (type) { 833 case WifiDebugRxPacketFate.SUCCESS: 834 return WifiLoggerHal.RX_PKT_FATE_SUCCESS; 835 case WifiDebugRxPacketFate.FW_QUEUED: 836 return WifiLoggerHal.RX_PKT_FATE_FW_QUEUED; 837 case WifiDebugRxPacketFate.FW_DROP_FILTER: 838 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER; 839 case WifiDebugRxPacketFate.FW_DROP_INVALID: 840 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID; 841 case WifiDebugRxPacketFate.FW_DROP_NOBUFS: 842 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS; 843 case WifiDebugRxPacketFate.FW_DROP_OTHER: 844 return WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER; 845 case WifiDebugRxPacketFate.DRV_QUEUED: 846 return WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED; 847 case WifiDebugRxPacketFate.DRV_DROP_FILTER: 848 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER; 849 case WifiDebugRxPacketFate.DRV_DROP_INVALID: 850 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID; 851 case WifiDebugRxPacketFate.DRV_DROP_NOBUFS: 852 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS; 853 case WifiDebugRxPacketFate.DRV_DROP_OTHER: 854 return WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER; 855 default: 856 throw new IllegalArgumentException("bad " + type); 857 } 858 } 859 halToFrameworkTxPktFate(int type)860 private static byte halToFrameworkTxPktFate(int type) { 861 switch (type) { 862 case WifiDebugTxPacketFate.ACKED: 863 return WifiLoggerHal.TX_PKT_FATE_ACKED; 864 case WifiDebugTxPacketFate.SENT: 865 return WifiLoggerHal.TX_PKT_FATE_SENT; 866 case WifiDebugTxPacketFate.FW_QUEUED: 867 return WifiLoggerHal.TX_PKT_FATE_FW_QUEUED; 868 case WifiDebugTxPacketFate.FW_DROP_INVALID: 869 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID; 870 case WifiDebugTxPacketFate.FW_DROP_NOBUFS: 871 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS; 872 case WifiDebugTxPacketFate.FW_DROP_OTHER: 873 return WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER; 874 case WifiDebugTxPacketFate.DRV_QUEUED: 875 return WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED; 876 case WifiDebugTxPacketFate.DRV_DROP_INVALID: 877 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID; 878 case WifiDebugTxPacketFate.DRV_DROP_NOBUFS: 879 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS; 880 case WifiDebugTxPacketFate.DRV_DROP_OTHER: 881 return WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER; 882 default: 883 throw new IllegalArgumentException("bad " + type); 884 } 885 } 886 hasCapability(long capabilities, long desiredCapability)887 private static boolean hasCapability(long capabilities, long desiredCapability) { 888 return (capabilities & desiredCapability) != 0; 889 } 890 891 @VisibleForTesting halToFrameworkStaIfaceCapability(int caps)892 long halToFrameworkStaIfaceCapability(int caps) { 893 long features = 0; 894 if (hasCapability(caps, 895 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT)) { 896 features |= WifiManager.WIFI_FEATURE_PASSPOINT; 897 } 898 if (hasCapability(caps, 899 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN)) { 900 features |= WifiManager.WIFI_FEATURE_SCANNER; 901 } 902 if (hasCapability(caps, 903 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.PNO)) { 904 features |= WifiManager.WIFI_FEATURE_PNO; 905 } 906 if (hasCapability(caps, 907 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS)) { 908 features |= WifiManager.WIFI_FEATURE_TDLS; 909 } 910 if (hasCapability(caps, 911 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL)) { 912 features |= WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL; 913 } 914 if (hasCapability(caps, 915 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS)) { 916 features |= WifiManager.WIFI_FEATURE_LINK_LAYER_STATS; 917 } 918 if (hasCapability(caps, 919 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR)) { 920 features |= WifiManager.WIFI_FEATURE_RSSI_MONITOR; 921 } 922 if (hasCapability(caps, 923 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE)) { 924 features |= WifiManager.WIFI_FEATURE_MKEEP_ALIVE; 925 } 926 if (hasCapability(caps, 927 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD)) { 928 features |= WifiManager.WIFI_FEATURE_CONFIG_NDO; 929 } 930 if (hasCapability(caps, 931 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING)) { 932 features |= WifiManager.WIFI_FEATURE_CONTROL_ROAMING; 933 } 934 if (hasCapability(caps, 935 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask 936 .PROBE_IE_WHITELIST)) { 937 features |= WifiManager.WIFI_FEATURE_IE_WHITELIST; 938 } 939 if (hasCapability(caps, 940 android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND)) { 941 features |= WifiManager.WIFI_FEATURE_SCAN_RAND; 942 } 943 return features; 944 } 945 946 @VisibleForTesting frameworkFromHalLinkLayerStats(StaLinkLayerStats stats)947 WifiLinkLayerStats frameworkFromHalLinkLayerStats(StaLinkLayerStats stats) { 948 if (stats == null) return null; 949 WifiLinkLayerStats out = new WifiLinkLayerStats(); 950 setIfaceStats(out, stats.iface); 951 setRadioStats(out, stats.radios); 952 out.timeStampInMs = stats.timeStampInMs; 953 out.version = WifiLinkLayerStats.V1_0; 954 return out; 955 } 956 957 /** 958 * Makes the framework version of link layer stats from the hal version. 959 */ 960 @VisibleForTesting frameworkFromHalLinkLayerStats_1_3( android.hardware.wifi.V1_3.StaLinkLayerStats stats)961 WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_3( 962 android.hardware.wifi.V1_3.StaLinkLayerStats stats) { 963 if (stats == null) return null; 964 WifiLinkLayerStats out = new WifiLinkLayerStats(); 965 setIfaceStats(out, stats.iface); 966 setRadioStats_1_3(out, stats.radios); 967 out.timeStampInMs = stats.timeStampInMs; 968 out.version = WifiLinkLayerStats.V1_3; 969 return out; 970 } 971 972 /** 973 * Makes the framework version of link layer stats from the hal version. 974 */ 975 @VisibleForTesting frameworkFromHalLinkLayerStats_1_5( android.hardware.wifi.V1_5.StaLinkLayerStats stats)976 WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_5( 977 android.hardware.wifi.V1_5.StaLinkLayerStats stats) { 978 if (stats == null) return null; 979 WifiLinkLayerStats out = new WifiLinkLayerStats(); 980 setIfaceStats_1_5(out, stats.iface); 981 setRadioStats_1_5(out, stats.radios); 982 out.timeStampInMs = stats.timeStampInMs; 983 out.version = WifiLinkLayerStats.V1_5; 984 return out; 985 } 986 987 /** 988 * Makes the framework version of link layer stats from the hal version. 989 */ 990 @VisibleForTesting frameworkFromHalLinkLayerStats_1_6( android.hardware.wifi.V1_6.StaLinkLayerStats stats)991 WifiLinkLayerStats frameworkFromHalLinkLayerStats_1_6( 992 android.hardware.wifi.V1_6.StaLinkLayerStats stats) { 993 if (stats == null) return null; 994 WifiLinkLayerStats out = new WifiLinkLayerStats(); 995 setIfaceStats_1_6(out, stats.iface); 996 setRadioStats_1_6(out, stats.radios); 997 out.timeStampInMs = stats.timeStampInMs; 998 out.version = WifiLinkLayerStats.V1_5; 999 return out; 1000 } 1001 setIfaceStats(WifiLinkLayerStats stats, StaLinkLayerIfaceStats iface)1002 private static void setIfaceStats(WifiLinkLayerStats stats, StaLinkLayerIfaceStats iface) { 1003 if (iface == null) return; 1004 stats.links = new WifiLinkLayerStats.LinkSpecificStats[NUM_OF_LINKS]; 1005 stats.links[DEFAULT_LINK] = new WifiLinkLayerStats.LinkSpecificStats(); 1006 stats.links[DEFAULT_LINK].link_id = 0; 1007 stats.links[DEFAULT_LINK].state = LINK_STATE_UNKNOWN; 1008 stats.links[DEFAULT_LINK].beacon_rx = iface.beaconRx; 1009 /* HIDL is using legacy single link layer stats. */ 1010 stats.links[DEFAULT_LINK].radio_id = 0; 1011 stats.links[DEFAULT_LINK].frequencyMhz = 0; 1012 stats.links[DEFAULT_LINK].rssi_mgmt = iface.avgRssiMgmt; 1013 // Statistics are broken out by Wireless Multimedia Extensions categories 1014 // WME Best Effort Access Category 1015 stats.links[DEFAULT_LINK].rxmpdu_be = iface.wmeBePktStats.rxMpdu; 1016 stats.links[DEFAULT_LINK].txmpdu_be = iface.wmeBePktStats.txMpdu; 1017 stats.links[DEFAULT_LINK].lostmpdu_be = iface.wmeBePktStats.lostMpdu; 1018 stats.links[DEFAULT_LINK].retries_be = iface.wmeBePktStats.retries; 1019 // WME Background Access Category 1020 stats.links[DEFAULT_LINK].rxmpdu_bk = iface.wmeBkPktStats.rxMpdu; 1021 stats.links[DEFAULT_LINK].txmpdu_bk = iface.wmeBkPktStats.txMpdu; 1022 stats.links[DEFAULT_LINK].lostmpdu_bk = iface.wmeBkPktStats.lostMpdu; 1023 stats.links[DEFAULT_LINK].retries_bk = iface.wmeBkPktStats.retries; 1024 // WME Video Access Category 1025 stats.links[DEFAULT_LINK].rxmpdu_vi = iface.wmeViPktStats.rxMpdu; 1026 stats.links[DEFAULT_LINK].txmpdu_vi = iface.wmeViPktStats.txMpdu; 1027 stats.links[DEFAULT_LINK].lostmpdu_vi = iface.wmeViPktStats.lostMpdu; 1028 stats.links[DEFAULT_LINK].retries_vi = iface.wmeViPktStats.retries; 1029 // WME Voice Access Category 1030 stats.links[DEFAULT_LINK].rxmpdu_vo = iface.wmeVoPktStats.rxMpdu; 1031 stats.links[DEFAULT_LINK].txmpdu_vo = iface.wmeVoPktStats.txMpdu; 1032 stats.links[DEFAULT_LINK].lostmpdu_vo = iface.wmeVoPktStats.lostMpdu; 1033 stats.links[DEFAULT_LINK].retries_vo = iface.wmeVoPktStats.retries; 1034 } 1035 setIfaceStats_1_5(WifiLinkLayerStats stats, android.hardware.wifi.V1_5.StaLinkLayerIfaceStats iface)1036 private static void setIfaceStats_1_5(WifiLinkLayerStats stats, 1037 android.hardware.wifi.V1_5.StaLinkLayerIfaceStats iface) { 1038 if (iface == null) return; 1039 setIfaceStats(stats, iface.V1_0); 1040 stats.links[DEFAULT_LINK].timeSliceDutyCycleInPercent = iface.timeSliceDutyCycleInPercent; 1041 // WME Best Effort Access Category 1042 stats.links[DEFAULT_LINK].contentionTimeMinBeInUsec = 1043 iface.wmeBeContentionTimeStats.contentionTimeMinInUsec; 1044 stats.links[DEFAULT_LINK].contentionTimeMaxBeInUsec = 1045 iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec; 1046 stats.links[DEFAULT_LINK].contentionTimeAvgBeInUsec = 1047 iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec; 1048 stats.links[DEFAULT_LINK].contentionNumSamplesBe = 1049 iface.wmeBeContentionTimeStats.contentionNumSamples; 1050 // WME Background Access Category 1051 stats.links[DEFAULT_LINK].contentionTimeMinBkInUsec = 1052 iface.wmeBkContentionTimeStats.contentionTimeMinInUsec; 1053 stats.links[DEFAULT_LINK].contentionTimeMaxBkInUsec = 1054 iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec; 1055 stats.links[DEFAULT_LINK].contentionTimeAvgBkInUsec = 1056 iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec; 1057 stats.links[DEFAULT_LINK].contentionNumSamplesBk = 1058 iface.wmeBkContentionTimeStats.contentionNumSamples; 1059 // WME Video Access Category 1060 stats.links[DEFAULT_LINK].contentionTimeMinViInUsec = 1061 iface.wmeViContentionTimeStats.contentionTimeMinInUsec; 1062 stats.links[DEFAULT_LINK].contentionTimeMaxViInUsec = 1063 iface.wmeViContentionTimeStats.contentionTimeMaxInUsec; 1064 stats.links[DEFAULT_LINK].contentionTimeAvgViInUsec = 1065 iface.wmeViContentionTimeStats.contentionTimeAvgInUsec; 1066 stats.links[DEFAULT_LINK].contentionNumSamplesVi = 1067 iface.wmeViContentionTimeStats.contentionNumSamples; 1068 // WME Voice Access Category 1069 stats.links[DEFAULT_LINK].contentionTimeMinVoInUsec = 1070 iface.wmeVoContentionTimeStats.contentionTimeMinInUsec; 1071 stats.links[DEFAULT_LINK].contentionTimeMaxVoInUsec = 1072 iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec; 1073 stats.links[DEFAULT_LINK].contentionTimeAvgVoInUsec = 1074 iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec; 1075 stats.links[DEFAULT_LINK].contentionNumSamplesVo = 1076 iface.wmeVoContentionTimeStats.contentionNumSamples; 1077 // Peer information statistics 1078 stats.links[DEFAULT_LINK].peerInfo = new WifiLinkLayerStats.PeerInfo[iface.peers.size()]; 1079 for (int i = 0; i < stats.links[DEFAULT_LINK].peerInfo.length; i++) { 1080 WifiLinkLayerStats.PeerInfo peer = new WifiLinkLayerStats.PeerInfo(); 1081 android.hardware.wifi.V1_5.StaPeerInfo staPeerInfo = iface.peers.get(i); 1082 peer.staCount = staPeerInfo.staCount; 1083 peer.chanUtil = staPeerInfo.chanUtil; 1084 WifiLinkLayerStats.RateStat[] rateStats = 1085 new WifiLinkLayerStats.RateStat[staPeerInfo.rateStats.size()]; 1086 for (int j = 0; j < staPeerInfo.rateStats.size(); j++) { 1087 rateStats[j] = new WifiLinkLayerStats.RateStat(); 1088 android.hardware.wifi.V1_5.StaRateStat staRateStat = staPeerInfo.rateStats.get(j); 1089 rateStats[j].preamble = staRateStat.rateInfo.preamble; 1090 rateStats[j].nss = staRateStat.rateInfo.nss; 1091 rateStats[j].bw = staRateStat.rateInfo.bw; 1092 rateStats[j].rateMcsIdx = staRateStat.rateInfo.rateMcsIdx; 1093 rateStats[j].bitRateInKbps = staRateStat.rateInfo.bitRateInKbps; 1094 rateStats[j].txMpdu = staRateStat.txMpdu; 1095 rateStats[j].rxMpdu = staRateStat.rxMpdu; 1096 rateStats[j].mpduLost = staRateStat.mpduLost; 1097 rateStats[j].retries = staRateStat.retries; 1098 } 1099 peer.rateStats = rateStats; 1100 stats.links[DEFAULT_LINK].peerInfo[i] = peer; 1101 } 1102 } 1103 setIfaceStats_1_6(WifiLinkLayerStats stats, android.hardware.wifi.V1_6.StaLinkLayerIfaceStats iface)1104 private static void setIfaceStats_1_6(WifiLinkLayerStats stats, 1105 android.hardware.wifi.V1_6.StaLinkLayerIfaceStats iface) { 1106 if (iface == null) return; 1107 setIfaceStats(stats, iface.V1_0); 1108 stats.links[DEFAULT_LINK].timeSliceDutyCycleInPercent = iface.timeSliceDutyCycleInPercent; 1109 // WME Best Effort Access Category 1110 stats.links[DEFAULT_LINK].contentionTimeMinBeInUsec = 1111 iface.wmeBeContentionTimeStats.contentionTimeMinInUsec; 1112 stats.links[DEFAULT_LINK].contentionTimeMaxBeInUsec = 1113 iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec; 1114 stats.links[DEFAULT_LINK].contentionTimeAvgBeInUsec = 1115 iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec; 1116 stats.links[DEFAULT_LINK].contentionNumSamplesBe = 1117 iface.wmeBeContentionTimeStats.contentionNumSamples; 1118 // WME Background Access Category 1119 stats.links[DEFAULT_LINK].contentionTimeMinBkInUsec = 1120 iface.wmeBkContentionTimeStats.contentionTimeMinInUsec; 1121 stats.links[DEFAULT_LINK].contentionTimeMaxBkInUsec = 1122 iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec; 1123 stats.links[DEFAULT_LINK].contentionTimeAvgBkInUsec = 1124 iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec; 1125 stats.links[DEFAULT_LINK].contentionNumSamplesBk = 1126 iface.wmeBkContentionTimeStats.contentionNumSamples; 1127 // WME Video Access Category 1128 stats.links[DEFAULT_LINK].contentionTimeMinViInUsec = 1129 iface.wmeViContentionTimeStats.contentionTimeMinInUsec; 1130 stats.links[DEFAULT_LINK].contentionTimeMaxViInUsec = 1131 iface.wmeViContentionTimeStats.contentionTimeMaxInUsec; 1132 stats.links[DEFAULT_LINK].contentionTimeAvgViInUsec = 1133 iface.wmeViContentionTimeStats.contentionTimeAvgInUsec; 1134 stats.links[DEFAULT_LINK].contentionNumSamplesVi = 1135 iface.wmeViContentionTimeStats.contentionNumSamples; 1136 // WME Voice Access Category 1137 stats.links[DEFAULT_LINK].contentionTimeMinVoInUsec = 1138 iface.wmeVoContentionTimeStats.contentionTimeMinInUsec; 1139 stats.links[DEFAULT_LINK].contentionTimeMaxVoInUsec = 1140 iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec; 1141 stats.links[DEFAULT_LINK].contentionTimeAvgVoInUsec = 1142 iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec; 1143 stats.links[DEFAULT_LINK].contentionNumSamplesVo = 1144 iface.wmeVoContentionTimeStats.contentionNumSamples; 1145 // Peer information statistics 1146 stats.links[DEFAULT_LINK].peerInfo = new WifiLinkLayerStats.PeerInfo[iface.peers.size()]; 1147 for (int i = 0; i < stats.links[DEFAULT_LINK].peerInfo.length; i++) { 1148 WifiLinkLayerStats.PeerInfo peer = new WifiLinkLayerStats.PeerInfo(); 1149 android.hardware.wifi.V1_6.StaPeerInfo staPeerInfo = iface.peers.get(i); 1150 peer.staCount = staPeerInfo.staCount; 1151 peer.chanUtil = staPeerInfo.chanUtil; 1152 WifiLinkLayerStats.RateStat[] rateStats = 1153 new WifiLinkLayerStats.RateStat[staPeerInfo.rateStats.size()]; 1154 for (int j = 0; j < staPeerInfo.rateStats.size(); j++) { 1155 rateStats[j] = new WifiLinkLayerStats.RateStat(); 1156 android.hardware.wifi.V1_6.StaRateStat staRateStat = staPeerInfo.rateStats.get(j); 1157 rateStats[j].preamble = staRateStat.rateInfo.preamble; 1158 rateStats[j].nss = staRateStat.rateInfo.nss; 1159 rateStats[j].bw = staRateStat.rateInfo.bw; 1160 rateStats[j].rateMcsIdx = staRateStat.rateInfo.rateMcsIdx; 1161 rateStats[j].bitRateInKbps = staRateStat.rateInfo.bitRateInKbps; 1162 rateStats[j].txMpdu = staRateStat.txMpdu; 1163 rateStats[j].rxMpdu = staRateStat.rxMpdu; 1164 rateStats[j].mpduLost = staRateStat.mpduLost; 1165 rateStats[j].retries = staRateStat.retries; 1166 } 1167 peer.rateStats = rateStats; 1168 stats.links[DEFAULT_LINK].peerInfo[i] = peer; 1169 } 1170 } 1171 setRadioStats(WifiLinkLayerStats stats, List<StaLinkLayerRadioStats> radios)1172 private static void setRadioStats(WifiLinkLayerStats stats, 1173 List<StaLinkLayerRadioStats> radios) { 1174 if (radios == null) return; 1175 // Do not coalesce this info for multi radio devices with older HALs. 1176 if (radios.size() > 0) { 1177 StaLinkLayerRadioStats radioStats = radios.get(0); 1178 stats.on_time = radioStats.onTimeInMs; 1179 stats.tx_time = radioStats.txTimeInMs; 1180 stats.tx_time_per_level = new int[radioStats.txTimeInMsPerLevel.size()]; 1181 for (int i = 0; i < stats.tx_time_per_level.length; i++) { 1182 stats.tx_time_per_level[i] = radioStats.txTimeInMsPerLevel.get(i); 1183 } 1184 stats.rx_time = radioStats.rxTimeInMs; 1185 stats.on_time_scan = radioStats.onTimeInMsForScan; 1186 stats.numRadios = 1; 1187 } 1188 } 1189 setRadioStats_1_3(WifiLinkLayerStats stats, List<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> radios)1190 private void setRadioStats_1_3(WifiLinkLayerStats stats, 1191 List<android.hardware.wifi.V1_3.StaLinkLayerRadioStats> radios) { 1192 if (radios == null) return; 1193 int radioIndex = 0; 1194 for (android.hardware.wifi.V1_3.StaLinkLayerRadioStats radioStats : radios) { 1195 aggregateFrameworkRadioStatsFromHidl_1_3(radioIndex, stats, radioStats); 1196 radioIndex++; 1197 } 1198 } 1199 setRadioStats_1_5(WifiLinkLayerStats stats, List<android.hardware.wifi.V1_5.StaLinkLayerRadioStats> radios)1200 private void setRadioStats_1_5(WifiLinkLayerStats stats, 1201 List<android.hardware.wifi.V1_5.StaLinkLayerRadioStats> radios) { 1202 if (radios == null) return; 1203 int radioIndex = 0; 1204 stats.radioStats = new WifiLinkLayerStats.RadioStat[radios.size()]; 1205 for (android.hardware.wifi.V1_5.StaLinkLayerRadioStats radioStats : radios) { 1206 WifiLinkLayerStats.RadioStat radio = new WifiLinkLayerStats.RadioStat(); 1207 setFrameworkPerRadioStatsFromHidl_1_3(radioStats.radioId, radio, radioStats.V1_3); 1208 stats.radioStats[radioIndex] = radio; 1209 aggregateFrameworkRadioStatsFromHidl_1_3(radioIndex, stats, radioStats.V1_3); 1210 radioIndex++; 1211 } 1212 } 1213 setRadioStats_1_6(WifiLinkLayerStats stats, List<android.hardware.wifi.V1_6.StaLinkLayerRadioStats> radios)1214 private void setRadioStats_1_6(WifiLinkLayerStats stats, 1215 List<android.hardware.wifi.V1_6.StaLinkLayerRadioStats> radios) { 1216 if (radios == null) return; 1217 int radioIndex = 0; 1218 stats.radioStats = new WifiLinkLayerStats.RadioStat[radios.size()]; 1219 for (android.hardware.wifi.V1_6.StaLinkLayerRadioStats radioStats : radios) { 1220 WifiLinkLayerStats.RadioStat radio = new WifiLinkLayerStats.RadioStat(); 1221 setFrameworkPerRadioStatsFromHidl_1_6(radio, radioStats); 1222 stats.radioStats[radioIndex] = radio; 1223 aggregateFrameworkRadioStatsFromHidl_1_6(radioIndex, stats, radioStats); 1224 radioIndex++; 1225 } 1226 } 1227 1228 /** 1229 * Set individual radio stats from the hal radio stats for V1_3 1230 */ setFrameworkPerRadioStatsFromHidl_1_3(int radioId, WifiLinkLayerStats.RadioStat radio, android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats)1231 private void setFrameworkPerRadioStatsFromHidl_1_3(int radioId, 1232 WifiLinkLayerStats.RadioStat radio, 1233 android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats) { 1234 radio.radio_id = radioId; 1235 radio.on_time = hidlRadioStats.V1_0.onTimeInMs; 1236 radio.tx_time = hidlRadioStats.V1_0.txTimeInMs; 1237 radio.rx_time = hidlRadioStats.V1_0.rxTimeInMs; 1238 radio.on_time_scan = hidlRadioStats.V1_0.onTimeInMsForScan; 1239 radio.on_time_nan_scan = hidlRadioStats.onTimeInMsForNanScan; 1240 radio.on_time_background_scan = hidlRadioStats.onTimeInMsForBgScan; 1241 radio.on_time_roam_scan = hidlRadioStats.onTimeInMsForRoamScan; 1242 radio.on_time_pno_scan = hidlRadioStats.onTimeInMsForPnoScan; 1243 radio.on_time_hs20_scan = hidlRadioStats.onTimeInMsForHs20Scan; 1244 /* Copy list of channel stats */ 1245 for (android.hardware.wifi.V1_3.WifiChannelStats channelStats 1246 : hidlRadioStats.channelStats) { 1247 WifiLinkLayerStats.ChannelStats channelStatsEntry = 1248 new WifiLinkLayerStats.ChannelStats(); 1249 channelStatsEntry.frequency = channelStats.channel.centerFreq; 1250 channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs; 1251 channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs; 1252 radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); 1253 } 1254 } 1255 1256 /** 1257 * Set individual radio stats from the hal radio stats for V1_6 1258 */ setFrameworkPerRadioStatsFromHidl_1_6(WifiLinkLayerStats.RadioStat radio, android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats)1259 private void setFrameworkPerRadioStatsFromHidl_1_6(WifiLinkLayerStats.RadioStat radio, 1260 android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats) { 1261 radio.radio_id = hidlRadioStats.radioId; 1262 radio.on_time = hidlRadioStats.V1_0.onTimeInMs; 1263 radio.tx_time = hidlRadioStats.V1_0.txTimeInMs; 1264 radio.rx_time = hidlRadioStats.V1_0.rxTimeInMs; 1265 radio.on_time_scan = hidlRadioStats.V1_0.onTimeInMsForScan; 1266 radio.on_time_nan_scan = hidlRadioStats.onTimeInMsForNanScan; 1267 radio.on_time_background_scan = hidlRadioStats.onTimeInMsForBgScan; 1268 radio.on_time_roam_scan = hidlRadioStats.onTimeInMsForRoamScan; 1269 radio.on_time_pno_scan = hidlRadioStats.onTimeInMsForPnoScan; 1270 radio.on_time_hs20_scan = hidlRadioStats.onTimeInMsForHs20Scan; 1271 /* Copy list of channel stats */ 1272 for (android.hardware.wifi.V1_6.WifiChannelStats channelStats 1273 : hidlRadioStats.channelStats) { 1274 WifiLinkLayerStats.ChannelStats channelStatsEntry = 1275 new WifiLinkLayerStats.ChannelStats(); 1276 channelStatsEntry.frequency = channelStats.channel.centerFreq; 1277 channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs; 1278 channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs; 1279 radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); 1280 } 1281 } 1282 1283 /** 1284 * If config_wifiLinkLayerAllRadiosStatsAggregationEnabled is set to true, aggregate 1285 * the radio stats from all the radios else process the stats from Radio 0 only. 1286 * This method is for V1_3 1287 */ aggregateFrameworkRadioStatsFromHidl_1_3(int radioIndex, WifiLinkLayerStats stats, android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats)1288 private void aggregateFrameworkRadioStatsFromHidl_1_3(int radioIndex, 1289 WifiLinkLayerStats stats, 1290 android.hardware.wifi.V1_3.StaLinkLayerRadioStats hidlRadioStats) { 1291 if (!mWifiLinkLayerAllRadiosStatsAggregationEnabled && radioIndex > 0) { 1292 return; 1293 } 1294 // Aggregate the radio stats from all the radios 1295 stats.on_time += hidlRadioStats.V1_0.onTimeInMs; 1296 stats.tx_time += hidlRadioStats.V1_0.txTimeInMs; 1297 // Aggregate tx_time_per_level based on the assumption that the length of 1298 // txTimeInMsPerLevel is the same across all radios. So txTimeInMsPerLevel on other 1299 // radios at array indices greater than the length of first radio will be dropped. 1300 if (stats.tx_time_per_level == null) { 1301 stats.tx_time_per_level = new int[hidlRadioStats.V1_0.txTimeInMsPerLevel.size()]; 1302 } 1303 for (int i = 0; i < hidlRadioStats.V1_0.txTimeInMsPerLevel.size() 1304 && i < stats.tx_time_per_level.length; i++) { 1305 stats.tx_time_per_level[i] += hidlRadioStats.V1_0.txTimeInMsPerLevel.get(i); 1306 } 1307 stats.rx_time += hidlRadioStats.V1_0.rxTimeInMs; 1308 stats.on_time_scan += hidlRadioStats.V1_0.onTimeInMsForScan; 1309 stats.on_time_nan_scan += hidlRadioStats.onTimeInMsForNanScan; 1310 stats.on_time_background_scan += hidlRadioStats.onTimeInMsForBgScan; 1311 stats.on_time_roam_scan += hidlRadioStats.onTimeInMsForRoamScan; 1312 stats.on_time_pno_scan += hidlRadioStats.onTimeInMsForPnoScan; 1313 stats.on_time_hs20_scan += hidlRadioStats.onTimeInMsForHs20Scan; 1314 /* Copy list of channel stats */ 1315 for (android.hardware.wifi.V1_3.WifiChannelStats channelStats 1316 : hidlRadioStats.channelStats) { 1317 WifiLinkLayerStats.ChannelStats channelStatsEntry = 1318 stats.channelStatsMap.get(channelStats.channel.centerFreq); 1319 if (channelStatsEntry == null) { 1320 channelStatsEntry = new WifiLinkLayerStats.ChannelStats(); 1321 channelStatsEntry.frequency = channelStats.channel.centerFreq; 1322 stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); 1323 } 1324 channelStatsEntry.radioOnTimeMs += channelStats.onTimeInMs; 1325 channelStatsEntry.ccaBusyTimeMs += channelStats.ccaBusyTimeInMs; 1326 } 1327 stats.numRadios++; 1328 } 1329 1330 /** 1331 * If config_wifiLinkLayerAllRadiosStatsAggregationEnabled is set to true, aggregate 1332 * the radio stats from all the radios else process the stats from Radio 0 only. 1333 * This method is for V1_6 1334 */ aggregateFrameworkRadioStatsFromHidl_1_6(int radioIndex, WifiLinkLayerStats stats, android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats)1335 private void aggregateFrameworkRadioStatsFromHidl_1_6(int radioIndex, 1336 WifiLinkLayerStats stats, 1337 android.hardware.wifi.V1_6.StaLinkLayerRadioStats hidlRadioStats) { 1338 if (!mWifiLinkLayerAllRadiosStatsAggregationEnabled && radioIndex > 0) { 1339 return; 1340 } 1341 // Aggregate the radio stats from all the radios 1342 stats.on_time += hidlRadioStats.V1_0.onTimeInMs; 1343 stats.tx_time += hidlRadioStats.V1_0.txTimeInMs; 1344 // Aggregate tx_time_per_level based on the assumption that the length of 1345 // txTimeInMsPerLevel is the same across all radios. So txTimeInMsPerLevel on other 1346 // radios at array indices greater than the length of first radio will be dropped. 1347 if (stats.tx_time_per_level == null) { 1348 stats.tx_time_per_level = new int[hidlRadioStats.V1_0.txTimeInMsPerLevel.size()]; 1349 } 1350 for (int i = 0; i < hidlRadioStats.V1_0.txTimeInMsPerLevel.size() 1351 && i < stats.tx_time_per_level.length; i++) { 1352 stats.tx_time_per_level[i] += hidlRadioStats.V1_0.txTimeInMsPerLevel.get(i); 1353 } 1354 stats.rx_time += hidlRadioStats.V1_0.rxTimeInMs; 1355 stats.on_time_scan += hidlRadioStats.V1_0.onTimeInMsForScan; 1356 stats.on_time_nan_scan += hidlRadioStats.onTimeInMsForNanScan; 1357 stats.on_time_background_scan += hidlRadioStats.onTimeInMsForBgScan; 1358 stats.on_time_roam_scan += hidlRadioStats.onTimeInMsForRoamScan; 1359 stats.on_time_pno_scan += hidlRadioStats.onTimeInMsForPnoScan; 1360 stats.on_time_hs20_scan += hidlRadioStats.onTimeInMsForHs20Scan; 1361 /* Copy list of channel stats */ 1362 for (android.hardware.wifi.V1_6.WifiChannelStats channelStats 1363 : hidlRadioStats.channelStats) { 1364 WifiLinkLayerStats.ChannelStats channelStatsEntry = 1365 stats.channelStatsMap.get(channelStats.channel.centerFreq); 1366 if (channelStatsEntry == null) { 1367 channelStatsEntry = new WifiLinkLayerStats.ChannelStats(); 1368 channelStatsEntry.frequency = channelStats.channel.centerFreq; 1369 stats.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); 1370 } 1371 channelStatsEntry.radioOnTimeMs += channelStats.onTimeInMs; 1372 channelStatsEntry.ccaBusyTimeMs += channelStats.ccaBusyTimeInMs; 1373 } 1374 stats.numRadios++; 1375 } 1376 frameworkToHalBackgroundScanParams( WifiStaIface.StaBackgroundScanParameters frameworkParams)1377 private static StaBackgroundScanParameters frameworkToHalBackgroundScanParams( 1378 WifiStaIface.StaBackgroundScanParameters frameworkParams) { 1379 StaBackgroundScanParameters halParams = new StaBackgroundScanParameters(); 1380 halParams.basePeriodInMs = frameworkParams.basePeriodInMs; 1381 halParams.maxApPerScan = frameworkParams.maxApPerScan; 1382 halParams.reportThresholdPercent = frameworkParams.reportThresholdPercent; 1383 halParams.reportThresholdNumScans = frameworkParams.reportThresholdNumScans; 1384 if (frameworkParams.buckets != null) { 1385 for (WifiNative.BucketSettings bucket : frameworkParams.buckets) { 1386 halParams.buckets.add(frameworkToHalBucketParams(bucket)); 1387 } 1388 } 1389 return halParams; 1390 } 1391 frameworkToHalBucketParams( WifiNative.BucketSettings frameworkBucket)1392 private static StaBackgroundScanBucketParameters frameworkToHalBucketParams( 1393 WifiNative.BucketSettings frameworkBucket) { 1394 StaBackgroundScanBucketParameters halBucket = new StaBackgroundScanBucketParameters(); 1395 halBucket.bucketIdx = frameworkBucket.bucket; 1396 halBucket.band = frameworkToHalWifiBand(frameworkBucket.band); 1397 if (frameworkBucket.channels != null) { 1398 for (WifiNative.ChannelSettings cs : frameworkBucket.channels) { 1399 halBucket.frequencies.add(cs.frequency); 1400 } 1401 } 1402 halBucket.periodInMs = frameworkBucket.period_ms; 1403 halBucket.eventReportScheme = frameworkToHalReportSchemeMask(frameworkBucket.report_events); 1404 halBucket.exponentialMaxPeriodInMs = frameworkBucket.max_period_ms; 1405 // Although HAL API allows configurable base value for the truncated 1406 // exponential back off scan. Native API and above support only 1407 // truncated binary exponential back off scan. 1408 // Hard code value of base to 2 here. 1409 halBucket.exponentialBase = 2; 1410 halBucket.exponentialStepCount = frameworkBucket.step_count; 1411 return halBucket; 1412 } 1413 1414 /** 1415 * Convert WifiBand from framework to HAL. 1416 * 1417 * Note: This method is only used by background scan which does not 1418 * support 6GHz, hence band combinations including 6GHz are considered invalid 1419 * 1420 * @param frameworkBand one of WifiScanner.WIFI_BAND_* 1421 * @return A WifiBand value 1422 * @throws IllegalArgumentException if frameworkBand is not recognized 1423 */ frameworkToHalWifiBand(int frameworkBand)1424 private static int frameworkToHalWifiBand(int frameworkBand) { 1425 switch (frameworkBand) { 1426 case WifiScanner.WIFI_BAND_UNSPECIFIED: 1427 return WifiBand.BAND_UNSPECIFIED; 1428 case WifiScanner.WIFI_BAND_24_GHZ: 1429 return WifiBand.BAND_24GHZ; 1430 case WifiScanner.WIFI_BAND_5_GHZ: 1431 return WifiBand.BAND_5GHZ; 1432 case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: 1433 return WifiBand.BAND_5GHZ_DFS; 1434 case WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS: 1435 return WifiBand.BAND_5GHZ_WITH_DFS; 1436 case WifiScanner.WIFI_BAND_BOTH: 1437 return WifiBand.BAND_24GHZ_5GHZ; 1438 case WifiScanner.WIFI_BAND_BOTH_WITH_DFS: 1439 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS; 1440 case WifiScanner.WIFI_BAND_6_GHZ: 1441 return WifiBand.BAND_6GHZ; 1442 case WifiScanner.WIFI_BAND_24_5_6_GHZ: 1443 return WifiBand.BAND_24GHZ_5GHZ_6GHZ; 1444 case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_GHZ: 1445 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ; 1446 case WifiScanner.WIFI_BAND_60_GHZ: 1447 return WifiBand.BAND_60GHZ; 1448 case WifiScanner.WIFI_BAND_24_5_6_60_GHZ: 1449 return WifiBand.BAND_24GHZ_5GHZ_6GHZ_60GHZ; 1450 case WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ: 1451 return WifiBand.BAND_24GHZ_5GHZ_WITH_DFS_6GHZ_60GHZ; 1452 case WifiScanner.WIFI_BAND_24_GHZ_WITH_5GHZ_DFS: 1453 default: 1454 throw new IllegalArgumentException("bad band " + frameworkBand); 1455 } 1456 } 1457 1458 /** 1459 * Convert the report scheme mask from framework to hal. 1460 * 1461 * @param reportUnderscoreEvents is logical OR of WifiScanner.REPORT_EVENT_* values 1462 * @return Corresponding StaBackgroundScanBucketEventReportSchemeMask value 1463 * @throws IllegalArgumentException if a mask bit is not recognized 1464 */ frameworkToHalReportSchemeMask(int reportUnderscoreEvents)1465 private static int frameworkToHalReportSchemeMask(int reportUnderscoreEvents) { 1466 int ans = 0; 1467 BitMask in = new BitMask(reportUnderscoreEvents); 1468 if (in.testAndClear(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN)) { 1469 ans |= StaBackgroundScanBucketEventReportSchemeMask.EACH_SCAN; 1470 } 1471 if (in.testAndClear(WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)) { 1472 ans |= StaBackgroundScanBucketEventReportSchemeMask.FULL_RESULTS; 1473 } 1474 if (in.testAndClear(WifiScanner.REPORT_EVENT_NO_BATCH)) { 1475 ans |= StaBackgroundScanBucketEventReportSchemeMask.NO_BATCH; 1476 } 1477 if (in.value != 0) throw new IllegalArgumentException("bad " + reportUnderscoreEvents); 1478 return ans; 1479 } 1480 1481 // Only sets the fields of ScanResult used by Gscan clients. hidlToFrameworkScanResult(StaScanResult scanResult)1482 private ScanResult hidlToFrameworkScanResult(StaScanResult scanResult) { 1483 if (scanResult == null) return null; 1484 WifiSsid originalSsid = WifiSsid.fromBytes( 1485 NativeUtil.byteArrayFromArrayList(scanResult.ssid)); 1486 MacAddress bssid; 1487 try { 1488 bssid = MacAddress.fromString(NativeUtil.macAddressFromByteArray(scanResult.bssid)); 1489 } catch (IllegalArgumentException e) { 1490 Log.e(TAG, "Failed to get BSSID of scan result: " + e); 1491 return null; 1492 } 1493 ScanResult frameworkScanResult = new ScanResult(); 1494 frameworkScanResult.setWifiSsid(mSsidTranslator.getTranslatedSsidAndRecordBssidCharset( 1495 originalSsid, bssid)); 1496 frameworkScanResult.BSSID = bssid.toString(); 1497 frameworkScanResult.level = scanResult.rssi; 1498 frameworkScanResult.frequency = scanResult.frequency; 1499 frameworkScanResult.timestamp = scanResult.timeStampInUs; 1500 return frameworkScanResult; 1501 } 1502 hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults)1503 private ScanResult[] hidlToFrameworkScanResults(ArrayList<StaScanResult> scanResults) { 1504 if (scanResults == null || scanResults.isEmpty()) return new ScanResult[0]; 1505 ScanResult[] frameworkScanResults = new ScanResult[scanResults.size()]; 1506 int i = 0; 1507 for (StaScanResult scanResult : scanResults) { 1508 ScanResult frameworkScanResult = hidlToFrameworkScanResult(scanResult); 1509 if (frameworkScanResult == null) { 1510 Log.e(TAG, "hidlToFrameworkScanResults: unable to convert hidl to framework " 1511 + "scan result!"); 1512 continue; 1513 } 1514 frameworkScanResults[i++] = frameworkScanResult; 1515 } 1516 return frameworkScanResults; 1517 } 1518 hidlToFrameworkScanDataFlags(int flag)1519 private static int hidlToFrameworkScanDataFlags(int flag) { 1520 if (flag == StaScanDataFlagMask.INTERRUPTED) { 1521 return 1; 1522 } else { 1523 return 0; 1524 } 1525 } 1526 hidlToFrameworkScanDatas( int cmdId, ArrayList<StaScanData> scanDatas)1527 private WifiScanner.ScanData[] hidlToFrameworkScanDatas( 1528 int cmdId, ArrayList<StaScanData> scanDatas) { 1529 if (scanDatas == null || scanDatas.isEmpty()) return new WifiScanner.ScanData[0]; 1530 WifiScanner.ScanData[] frameworkScanDatas = new WifiScanner.ScanData[scanDatas.size()]; 1531 int i = 0; 1532 for (StaScanData scanData : scanDatas) { 1533 int flags = hidlToFrameworkScanDataFlags(scanData.flags); 1534 ScanResult[] frameworkScanResults = hidlToFrameworkScanResults(scanData.results); 1535 frameworkScanDatas[i++] = 1536 new WifiScanner.ScanData(cmdId, flags, scanData.bucketsScanned, 1537 WifiScanner.WIFI_BAND_UNSPECIFIED, frameworkScanResults); 1538 } 1539 return frameworkScanDatas; 1540 } 1541 getWifiStaIfaceV1_2Mockable()1542 protected android.hardware.wifi.V1_2.IWifiStaIface getWifiStaIfaceV1_2Mockable() { 1543 return android.hardware.wifi.V1_2.IWifiStaIface.castFrom(mWifiStaIface); 1544 } 1545 getWifiStaIfaceV1_3Mockable()1546 protected android.hardware.wifi.V1_3.IWifiStaIface getWifiStaIfaceV1_3Mockable() { 1547 return android.hardware.wifi.V1_3.IWifiStaIface.castFrom(mWifiStaIface); 1548 } 1549 getWifiStaIfaceV1_5Mockable()1550 protected android.hardware.wifi.V1_5.IWifiStaIface getWifiStaIfaceV1_5Mockable() { 1551 return android.hardware.wifi.V1_5.IWifiStaIface.castFrom(mWifiStaIface); 1552 } 1553 getWifiStaIfaceV1_6Mockable()1554 protected android.hardware.wifi.V1_6.IWifiStaIface getWifiStaIfaceV1_6Mockable() { 1555 return android.hardware.wifi.V1_6.IWifiStaIface.castFrom(mWifiStaIface); 1556 } 1557 isOk(WifiStatus status, String methodStr)1558 private boolean isOk(WifiStatus status, String methodStr) { 1559 if (status.code == WifiStatusCode.SUCCESS) return true; 1560 Log.e(TAG, methodStr + " failed with status: " + status); 1561 return false; 1562 } 1563 handleRemoteException(RemoteException e, String methodStr)1564 private void handleRemoteException(RemoteException e, String methodStr) { 1565 Log.e(TAG, methodStr + " failed with remote exception: " + e); 1566 mWifiStaIface = null; 1567 } 1568 handleException(Exception e, String methodStr)1569 private void handleException(Exception e, String methodStr) { 1570 Log.e(TAG, methodStr + " failed with exception: " + e); 1571 } 1572 validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier)1573 private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { 1574 if (mWifiStaIface == null) { 1575 Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiStaIface is null"); 1576 return defaultVal; 1577 } 1578 return supplier.get(); 1579 } 1580 1581 1582 // HAL Callback 1583 private class StaIfaceEventCallback extends IWifiStaIfaceEventCallback.Stub { 1584 @Override onBackgroundScanFailure(int cmdId)1585 public void onBackgroundScanFailure(int cmdId) { 1586 if (mFrameworkCallback == null) return; 1587 mFrameworkCallback.onBackgroundScanFailure(cmdId); 1588 } 1589 1590 @Override onBackgroundFullScanResult(int cmdId, int bucketsScanned, StaScanResult result)1591 public void onBackgroundFullScanResult(int cmdId, int bucketsScanned, 1592 StaScanResult result) { 1593 if (mFrameworkCallback == null) return; 1594 ScanResult frameworkScanResult = hidlToFrameworkScanResult(result); 1595 if (frameworkScanResult == null) { 1596 Log.e(TAG, "Unable to convert scan result from HAL to framework"); 1597 return; 1598 } 1599 mFrameworkCallback.onBackgroundFullScanResult(cmdId, bucketsScanned, 1600 frameworkScanResult); 1601 } 1602 1603 @Override onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas)1604 public void onBackgroundScanResults(int cmdId, ArrayList<StaScanData> scanDatas) { 1605 if (mFrameworkCallback == null) return; 1606 WifiScanner.ScanData[] frameworkScanDatas = hidlToFrameworkScanDatas(cmdId, scanDatas); 1607 mFrameworkCallback.onBackgroundScanResults(cmdId, frameworkScanDatas); 1608 } 1609 1610 @Override onRssiThresholdBreached(int cmdId, byte[ ] currBssid, int currRssi)1611 public void onRssiThresholdBreached(int cmdId, byte[/* 6 */] currBssid, int currRssi) { 1612 if (mFrameworkCallback == null) return; 1613 mFrameworkCallback.onRssiThresholdBreached(cmdId, currBssid, currRssi); 1614 } 1615 } 1616 } 1617