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.WifiManager.ROAMING_MODE_NORMAL; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.content.Context; 24 import android.hardware.wifi.WifiStatusCode; 25 import android.net.MacAddress; 26 import android.net.apf.ApfCapabilities; 27 import android.net.wifi.ScanResult; 28 import android.net.wifi.WifiManager.RoamingMode; 29 import android.net.wifi.WifiScanner; 30 import android.net.wifi.twt.TwtRequest; 31 import android.net.wifi.twt.TwtSessionCallback; 32 import android.os.Bundle; 33 import android.util.Log; 34 35 import com.android.server.wifi.SsidTranslator; 36 import com.android.server.wifi.WifiLinkLayerStats; 37 import com.android.server.wifi.WifiNative; 38 39 import java.util.ArrayList; 40 import java.util.BitSet; 41 import java.util.List; 42 import java.util.function.Supplier; 43 44 /** 45 * Wrapper around a WifiStaIface. 46 * May be initialized using a HIDL or AIDL WifiStaIface. 47 */ 48 public class WifiStaIface implements WifiHal.WifiInterface { 49 private static final String TAG = "WifiStaIface"; 50 private final IWifiStaIface mWifiStaIface; 51 52 public static final int SET_ROAMING_STATE_FAILURE_CODE = 53 WifiNative.SET_FIRMWARE_ROAMING_FAILURE; 54 55 /** 56 * Parameters for a background scan request. 57 */ 58 public static class StaBackgroundScanParameters { 59 public int basePeriodInMs; 60 public int maxApPerScan; 61 public int reportThresholdPercent; 62 public int reportThresholdNumScans; 63 public List<WifiNative.BucketSettings> buckets; 64 StaBackgroundScanParameters(int inBasePeriodInMs, int inMaxApPerScan, int inReportThresholdPercent, int inReportThresholdNumScans, List<WifiNative.BucketSettings> inBuckets)65 public StaBackgroundScanParameters(int inBasePeriodInMs, int inMaxApPerScan, 66 int inReportThresholdPercent, int inReportThresholdNumScans, 67 List<WifiNative.BucketSettings> inBuckets) { 68 basePeriodInMs = inBasePeriodInMs; 69 maxApPerScan = inMaxApPerScan; 70 reportThresholdPercent = inReportThresholdPercent; 71 reportThresholdNumScans = inReportThresholdNumScans; 72 buckets = inBuckets; 73 } 74 } 75 76 /** 77 * Framework callback object. Will get called when the equivalent events are received 78 * from the HAL. 79 */ 80 public interface Callback { 81 /** 82 * Called for each received beacon/probe response for a scan with the 83 * |REPORT_EVENTS_FULL_RESULTS| flag set in 84 * |StaBackgroundScanBucketParameters.eventReportScheme|. 85 * 86 * @param cmdId Command ID corresponding to the request. 87 * @param bucketsScanned Bitset where each bit indicates if the bucket with 88 * that index (starting at 0) was scanned. 89 * @param result Full scan result for an AP. 90 */ onBackgroundFullScanResult(int cmdId, int bucketsScanned, ScanResult result)91 void onBackgroundFullScanResult(int cmdId, int bucketsScanned, ScanResult result); 92 93 /** 94 * Callback indicating that an ongoing background scan request has failed. 95 * The background scan needs to be restarted to continue scanning. 96 * 97 * @param cmdId Command ID corresponding to the request. 98 */ onBackgroundScanFailure(int cmdId)99 void onBackgroundScanFailure(int cmdId); 100 101 /** 102 * Called when the |StaBackgroundScanBucketParameters.eventReportScheme| flags 103 * for at least one bucket that was just scanned was |REPORT_EVENTS_EACH_SCAN|, 104 * or one of the configured thresholds was breached. 105 * 106 * @param cmdId Command ID corresponding to the request. 107 * @param scanDatas List of scan results for all APs seen since the last callback. 108 */ onBackgroundScanResults(int cmdId, WifiScanner.ScanData[] scanDatas)109 void onBackgroundScanResults(int cmdId, WifiScanner.ScanData[] scanDatas); 110 111 /** 112 * Called when the RSSI of the currently connected access point goes beyond the 113 * thresholds set via 114 * {@link IWifiStaIface#startRssiMonitoring(int, int, int)} 115 * 116 * @param cmdId Command ID corresponding to the request. 117 * @param currBssid BSSID of the currently connected access point. 118 * @param currRssi RSSI of the currently connected access point. 119 */ onRssiThresholdBreached(int cmdId, byte[] currBssid, int currRssi)120 void onRssiThresholdBreached(int cmdId, byte[] currBssid, int currRssi); 121 122 /** 123 * Called when TWT operation fails. 124 * 125 * @param cmdId Unique command id which is failed 126 * @param twtErrorCode Error code 127 */ onTwtFailure(int cmdId, @TwtSessionCallback.TwtErrorCode int twtErrorCode)128 void onTwtFailure(int cmdId, @TwtSessionCallback.TwtErrorCode int twtErrorCode); 129 130 /** 131 * Called when {@link WifiStaIface#setupTwtSession(int, TwtRequest)} succeeds. 132 * 133 * @param cmdId Unique command id used in 134 * {@link WifiStaIface#setupTwtSession(int, TwtRequest)} 135 * @param wakeDurationUs TWT wake duration for the session in microseconds 136 * @param wakeIntervalUs TWT wake interval for the session in microseconds 137 * @param linkId Multi link operation link id 138 * @param sessionId TWT session id 139 */ onTwtSessionCreate(int cmdId, int wakeDurationUs, long wakeIntervalUs, int linkId, int sessionId)140 void onTwtSessionCreate(int cmdId, int wakeDurationUs, long wakeIntervalUs, int linkId, 141 int sessionId); 142 143 /** 144 * Called when TWT session is torndown by {@link WifiStaIface#tearDownTwtSession(int, int)}. 145 * Can also be called unsolicitedly by the vendor software with proper reason code. 146 * 147 * @param cmdId Unique command id used in {@link WifiStaIface#tearDownTwtSession(int, int)} 148 * @param twtSessionId TWT session Id 149 * @param twtReasonCode Reason code for teardown 150 */ onTwtSessionTeardown(int cmdId, int twtSessionId, @TwtSessionCallback.TwtReasonCode int twtReasonCode)151 void onTwtSessionTeardown(int cmdId, int twtSessionId, 152 @TwtSessionCallback.TwtReasonCode int twtReasonCode); 153 154 /** 155 * Called as a response to {@link WifiStaIface#getStatsTwtSession(int, int)} 156 * 157 * @param cmdId Unique command id used in {@link WifiStaIface#getStatsTwtSession(int, int)} 158 * @param twtSessionId TWT session Id 159 * @param twtStats TWT stats bundle 160 */ onTwtSessionStats(int cmdId, int twtSessionId, Bundle twtStats)161 void onTwtSessionStats(int cmdId, int twtSessionId, Bundle twtStats); 162 } 163 WifiStaIface(@onNull android.hardware.wifi.V1_0.IWifiStaIface staIface, @NonNull Context context, @NonNull SsidTranslator ssidTranslator)164 public WifiStaIface(@NonNull android.hardware.wifi.V1_0.IWifiStaIface staIface, 165 @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { 166 mWifiStaIface = createWifiStaIfaceHidlImplMockable(staIface, context, ssidTranslator); 167 } 168 WifiStaIface(@onNull android.hardware.wifi.IWifiStaIface staIface, @NonNull Context context, @NonNull SsidTranslator ssidTranslator)169 public WifiStaIface(@NonNull android.hardware.wifi.IWifiStaIface staIface, 170 @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { 171 mWifiStaIface = createWifiStaIfaceAidlImplMockable(staIface, context, ssidTranslator); 172 } 173 createWifiStaIfaceHidlImplMockable( android.hardware.wifi.V1_0.IWifiStaIface staIface, @NonNull Context context, @NonNull SsidTranslator ssidTranslator)174 protected WifiStaIfaceHidlImpl createWifiStaIfaceHidlImplMockable( 175 android.hardware.wifi.V1_0.IWifiStaIface staIface, @NonNull Context context, 176 @NonNull SsidTranslator ssidTranslator) { 177 return new WifiStaIfaceHidlImpl(staIface, context, ssidTranslator); 178 } 179 createWifiStaIfaceAidlImplMockable( android.hardware.wifi.IWifiStaIface staIface, @NonNull Context context, @NonNull SsidTranslator ssidTranslator)180 protected WifiStaIfaceAidlImpl createWifiStaIfaceAidlImplMockable( 181 android.hardware.wifi.IWifiStaIface staIface, @NonNull Context context, 182 @NonNull SsidTranslator ssidTranslator) { 183 return new WifiStaIfaceAidlImpl(staIface, context, ssidTranslator); 184 } 185 validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier)186 private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { 187 if (mWifiStaIface == null) { 188 Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiStaIface is null"); 189 return defaultVal; 190 } 191 return supplier.get(); 192 } 193 194 /** 195 * See comments for {@link IWifiStaIface#registerFrameworkCallback(Callback)} 196 */ registerFrameworkCallback(Callback callback)197 public boolean registerFrameworkCallback(Callback callback) { 198 return validateAndCall("registerFrameworkCallback", false, 199 () -> mWifiStaIface.registerFrameworkCallback(callback)); 200 } 201 202 /** 203 * See comments for {@link IWifiStaIface#getName()} 204 */ 205 @Override 206 @Nullable getName()207 public String getName() { 208 return validateAndCall("getName", null, 209 () -> mWifiStaIface.getName()); 210 } 211 212 /** 213 * See comments for {@link IWifiStaIface#configureRoaming(List, List)} 214 */ configureRoaming(List<MacAddress> bssidBlocklist, List<byte[]> ssidAllowlist)215 public boolean configureRoaming(List<MacAddress> bssidBlocklist, 216 List<byte[]> ssidAllowlist) { 217 return validateAndCall("configureRoaming", false, 218 () -> mWifiStaIface.configureRoaming(bssidBlocklist, ssidAllowlist)); 219 } 220 221 /** 222 * See comments for {@link IWifiStaIface#enableLinkLayerStatsCollection(boolean)} 223 */ enableLinkLayerStatsCollection(boolean debug)224 public boolean enableLinkLayerStatsCollection(boolean debug) { 225 return validateAndCall("enableLinkLayerStatsCollection", false, 226 () -> mWifiStaIface.enableLinkLayerStatsCollection(debug)); 227 } 228 229 /** 230 * See comments for {@link IWifiStaIface#enableNdOffload(boolean)} 231 */ enableNdOffload(boolean enable)232 public boolean enableNdOffload(boolean enable) { 233 return validateAndCall("enableNdOffload", false, 234 () -> mWifiStaIface.enableNdOffload(enable)); 235 } 236 237 /** 238 * See comments for {@link IWifiStaIface#getApfPacketFilterCapabilities()} 239 */ getApfPacketFilterCapabilities()240 public ApfCapabilities getApfPacketFilterCapabilities() { 241 return validateAndCall("getApfPacketFilterCapabilities", new ApfCapabilities(0, 0, 0), 242 () -> mWifiStaIface.getApfPacketFilterCapabilities()); 243 } 244 245 /** 246 * See comments for {@link IWifiStaIface#getBackgroundScanCapabilities()} 247 */ 248 @Nullable getBackgroundScanCapabilities()249 public WifiNative.ScanCapabilities getBackgroundScanCapabilities() { 250 return validateAndCall("getBackgroundScanCapabilities", null, 251 () -> mWifiStaIface.getBackgroundScanCapabilities()); 252 } 253 254 /** 255 * See comments for {@link IWifiStaIface#getCapabilities()} 256 */ getCapabilities()257 public BitSet getCapabilities() { 258 return validateAndCall("getCapabilities", new BitSet(), 259 () -> mWifiStaIface.getCapabilities()); 260 } 261 262 /** 263 * See comments for {@link IWifiStaIface#getDebugRxPacketFates()} 264 */ getDebugRxPacketFates()265 public List<WifiNative.RxFateReport> getDebugRxPacketFates() { 266 return validateAndCall("getDebugRxPacketFates", new ArrayList<>(), 267 () -> mWifiStaIface.getDebugRxPacketFates()); 268 } 269 270 /** 271 * See comments for {@link IWifiStaIface#getDebugTxPacketFates()} 272 */ getDebugTxPacketFates()273 public List<WifiNative.TxFateReport> getDebugTxPacketFates() { 274 return validateAndCall("getDebugTxPacketFates", new ArrayList<>(), 275 () -> mWifiStaIface.getDebugTxPacketFates()); 276 } 277 278 /** 279 * See comments for {@link IWifiStaIface#getFactoryMacAddress()} 280 */ 281 @Nullable getFactoryMacAddress()282 public MacAddress getFactoryMacAddress() { 283 return validateAndCall("getFactoryMacAddress", null, 284 () -> mWifiStaIface.getFactoryMacAddress()); 285 } 286 287 /** 288 * See comments for {@link IWifiStaIface#getCachedScanData()} 289 */ 290 @Nullable getCachedScanData()291 public WifiScanner.ScanData getCachedScanData() { 292 return validateAndCall("getCachedScanData", null, 293 () -> mWifiStaIface.getCachedScanData()); 294 } 295 296 297 /** 298 * See comments for {@link IWifiStaIface#getLinkLayerStats()} 299 */ 300 @Nullable getLinkLayerStats()301 public WifiLinkLayerStats getLinkLayerStats() { 302 return validateAndCall("getLinkLayerStats", null, 303 () -> mWifiStaIface.getLinkLayerStats()); 304 } 305 306 /** 307 * See comments for {@link IWifiStaIface#getRoamingCapabilities()} 308 */ 309 @Nullable getRoamingCapabilities()310 public WifiNative.RoamingCapabilities getRoamingCapabilities() { 311 return validateAndCall("getRoamingCapabilities", null, 312 () -> mWifiStaIface.getRoamingCapabilities()); 313 } 314 315 /** 316 * See comments for {@link IWifiStaIface#installApfPacketFilter(byte[])} 317 */ installApfPacketFilter(byte[] program)318 public boolean installApfPacketFilter(byte[] program) { 319 return validateAndCall("installApfPacketFilter", false, 320 () -> mWifiStaIface.installApfPacketFilter(program)); 321 } 322 323 /** 324 * See comments for {@link IWifiStaIface#readApfPacketFilterData()} 325 */ 326 @Nullable readApfPacketFilterData()327 public byte[] readApfPacketFilterData() { 328 return validateAndCall("readApfPacketFilterData", null, 329 () -> mWifiStaIface.readApfPacketFilterData()); 330 } 331 332 /** 333 * See comments for {@link IWifiStaIface#setMacAddress(MacAddress)} 334 */ setMacAddress(MacAddress mac)335 public boolean setMacAddress(MacAddress mac) { 336 return validateAndCall("setMacAddress", false, 337 () -> mWifiStaIface.setMacAddress(mac)); 338 } 339 340 /** 341 * See comments for {@link IWifiStaIface#setRoamingState(int)} 342 */ setRoamingState( @ifiNative.RoamingEnableState int state)343 public @WifiNative.RoamingEnableStatus int setRoamingState( 344 @WifiNative.RoamingEnableState int state) { 345 return validateAndCall("setRoamingState", SET_ROAMING_STATE_FAILURE_CODE, 346 () -> mWifiStaIface.setRoamingState(state)); 347 } 348 349 /** 350 * See comments for {@link IWifiStaIface#setScanMode(boolean)} 351 */ setScanMode(boolean enable)352 public boolean setScanMode(boolean enable) { 353 return validateAndCall("setScanMode", false, 354 () -> mWifiStaIface.setScanMode(enable)); 355 } 356 357 /** 358 * See comments for {@link IWifiStaIface#startBackgroundScan(int, StaBackgroundScanParameters)} 359 */ startBackgroundScan(int cmdId, StaBackgroundScanParameters params)360 public boolean startBackgroundScan(int cmdId, StaBackgroundScanParameters params) { 361 return validateAndCall("startBackgroundScan", false, 362 () -> mWifiStaIface.startBackgroundScan(cmdId, params)); 363 } 364 365 /** 366 * See comments for {@link IWifiStaIface#startDebugPacketFateMonitoring()} 367 */ startDebugPacketFateMonitoring()368 public boolean startDebugPacketFateMonitoring() { 369 return validateAndCall("startDebugPacketFateMonitoring", false, 370 () -> mWifiStaIface.startDebugPacketFateMonitoring()); 371 } 372 373 /** 374 * See comments for {@link IWifiStaIface#startRssiMonitoring(int, int, int)} 375 */ startRssiMonitoring(int cmdId, int maxRssi, int minRssi)376 public boolean startRssiMonitoring(int cmdId, int maxRssi, int minRssi) { 377 return validateAndCall("startRssiMonitoring", false, 378 () -> mWifiStaIface.startRssiMonitoring(cmdId, maxRssi, minRssi)); 379 } 380 381 /** 382 * See comments for {@link IWifiStaIface#startSendingKeepAlivePackets(int, byte[], int, 383 * MacAddress, MacAddress, int)} 384 */ startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType, MacAddress srcAddress, MacAddress dstAddress, int periodInMs)385 public boolean startSendingKeepAlivePackets(int cmdId, byte[] ipPacketData, int etherType, 386 MacAddress srcAddress, MacAddress dstAddress, int periodInMs) { 387 return validateAndCall("startSendingKeepAlivePackets", false, 388 () -> mWifiStaIface.startSendingKeepAlivePackets(cmdId, ipPacketData, etherType, 389 srcAddress, dstAddress, periodInMs)); 390 } 391 392 /** 393 * See comments for {@link IWifiStaIface#stopBackgroundScan(int)} 394 */ stopBackgroundScan(int cmdId)395 public boolean stopBackgroundScan(int cmdId) { 396 return validateAndCall("stopBackgroundScan", false, 397 () -> mWifiStaIface.stopBackgroundScan(cmdId)); 398 } 399 400 /** 401 * See comments for {@link IWifiStaIface#stopRssiMonitoring(int)} 402 */ stopRssiMonitoring(int cmdId)403 public boolean stopRssiMonitoring(int cmdId) { 404 return validateAndCall("stopRssiMonitoring", false, 405 () -> mWifiStaIface.stopRssiMonitoring(cmdId)); 406 } 407 408 /** 409 * See comments for {@link IWifiStaIface#stopSendingKeepAlivePackets(int)} 410 */ stopSendingKeepAlivePackets(int cmdId)411 public boolean stopSendingKeepAlivePackets(int cmdId) { 412 return validateAndCall("stopSendingKeepAlivePackets", false, 413 () -> mWifiStaIface.stopSendingKeepAlivePackets(cmdId)); 414 } 415 416 /** 417 * See comments for {@link IWifiStaIface#setDtimMultiplier(int)} 418 */ setDtimMultiplier(int multiplier)419 public boolean setDtimMultiplier(int multiplier) { 420 return validateAndCall("setDtimMultiplier", false, 421 () -> mWifiStaIface.setDtimMultiplier(multiplier)); 422 } 423 424 /** 425 * See comments for {@link IWifiStaIface#setRoamingMode(int)} 426 */ setRoamingMode(@oamingMode int roamingMode)427 public @WifiStatusCode int setRoamingMode(@RoamingMode int roamingMode) { 428 return validateAndCall("setRoamingMode", ROAMING_MODE_NORMAL, 429 () -> mWifiStaIface.setRoamingMode(roamingMode)); 430 } 431 432 /** 433 * See {@link IWifiStaIface#getTwtCapabilities()} 434 */ getTwtCapabilities()435 public Bundle getTwtCapabilities() { 436 return validateAndCall("getTwtCapabilities", null, 437 () -> mWifiStaIface.getTwtCapabilities()); 438 } 439 440 /** 441 * See {@link IWifiStaIface#setupTwtSession(int, TwtRequest)} 442 */ setupTwtSession(int cmdId, TwtRequest twtRequest)443 public boolean setupTwtSession(int cmdId, TwtRequest twtRequest) { 444 return validateAndCall("setupTwtSession", false, 445 () -> mWifiStaIface.setupTwtSession(cmdId, twtRequest)); 446 } 447 448 /** 449 * See {@link IWifiStaIface#tearDownTwtSession(int, int)} 450 */ tearDownTwtSession(int commandId, int sessionId)451 public boolean tearDownTwtSession(int commandId, int sessionId) { 452 return validateAndCall("tearDownTwtSession", false, 453 () -> mWifiStaIface.tearDownTwtSession(commandId, sessionId)); 454 } 455 456 /** 457 * See {@link IWifiStaIface#getStatsTwtSession(int, int)} 458 */ getStatsTwtSession(int commandId, int sessionId)459 public boolean getStatsTwtSession(int commandId, int sessionId) { 460 return validateAndCall("getStatsTwtSession", false, 461 () -> mWifiStaIface.getStatsTwtSession(commandId, sessionId)); 462 } 463 } 464 465