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