1 /* 2 * Copyright (C) 2008 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; 18 19 import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; 20 21 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP; 22 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE; 23 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_NAN; 24 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; 25 import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_P2P; 26 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES; 27 import static com.android.server.wifi.p2p.WifiP2pNative.P2P_IFACE_NAME; 28 import static com.android.server.wifi.p2p.WifiP2pNative.P2P_INTERFACE_PROPERTY; 29 30 import android.annotation.IntDef; 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.annotation.SuppressLint; 34 import android.hardware.wifi.WifiStatusCode; 35 import android.net.MacAddress; 36 import android.net.TrafficStats; 37 import android.net.apf.ApfCapabilities; 38 import android.net.wifi.CoexUnsafeChannel; 39 import android.net.wifi.MscsParams; 40 import android.net.wifi.OuiKeyedData; 41 import android.net.wifi.QosPolicyParams; 42 import android.net.wifi.ScanResult; 43 import android.net.wifi.SecurityParams; 44 import android.net.wifi.SoftApConfiguration; 45 import android.net.wifi.WifiAnnotations; 46 import android.net.wifi.WifiAvailableChannel; 47 import android.net.wifi.WifiConfiguration; 48 import android.net.wifi.WifiContext; 49 import android.net.wifi.WifiManager; 50 import android.net.wifi.WifiManager.RoamingMode; 51 import android.net.wifi.WifiScanner; 52 import android.net.wifi.WifiScanner.ScanData; 53 import android.net.wifi.WifiSsid; 54 import android.net.wifi.nl80211.DeviceWiphyCapabilities; 55 import android.net.wifi.nl80211.NativeScanResult; 56 import android.net.wifi.nl80211.NativeWifiClient; 57 import android.net.wifi.nl80211.RadioChainInfo; 58 import android.net.wifi.nl80211.WifiNl80211Manager; 59 import android.net.wifi.twt.TwtRequest; 60 import android.net.wifi.twt.TwtSessionCallback; 61 import android.os.Bundle; 62 import android.os.Handler; 63 import android.os.IBinder; 64 import android.os.SystemClock; 65 import android.os.WorkSource; 66 import android.text.TextUtils; 67 import android.util.ArrayMap; 68 import android.util.ArraySet; 69 import android.util.Log; 70 import android.util.SparseArray; 71 import android.util.SparseIntArray; 72 73 import com.android.internal.annotations.Immutable; 74 import com.android.internal.annotations.VisibleForTesting; 75 import com.android.internal.util.HexDump; 76 import com.android.modules.utils.build.SdkLevel; 77 import com.android.server.wifi.SupplicantStaIfaceHal.QosPolicyStatus; 78 import com.android.server.wifi.hal.WifiChip; 79 import com.android.server.wifi.hal.WifiHal; 80 import com.android.server.wifi.hal.WifiNanIface; 81 import com.android.server.wifi.hotspot2.NetworkDetail; 82 import com.android.server.wifi.mockwifi.MockWifiServiceUtil; 83 import com.android.server.wifi.proto.WifiStatsLog; 84 import com.android.server.wifi.util.FrameParser; 85 import com.android.server.wifi.util.InformationElementUtil; 86 import com.android.server.wifi.util.NativeUtil; 87 import com.android.server.wifi.util.NetdWrapper; 88 import com.android.server.wifi.util.NetdWrapper.NetdEventObserver; 89 import com.android.wifi.resources.R; 90 91 import java.io.PrintWriter; 92 import java.io.StringWriter; 93 import java.lang.annotation.Retention; 94 import java.lang.annotation.RetentionPolicy; 95 import java.nio.ByteBuffer; 96 import java.nio.ByteOrder; 97 import java.text.SimpleDateFormat; 98 import java.util.ArrayList; 99 import java.util.Arrays; 100 import java.util.BitSet; 101 import java.util.Collections; 102 import java.util.Date; 103 import java.util.HashMap; 104 import java.util.HashSet; 105 import java.util.Iterator; 106 import java.util.List; 107 import java.util.Map; 108 import java.util.Objects; 109 import java.util.Random; 110 import java.util.Set; 111 import java.util.TimeZone; 112 113 /** 114 * Native calls for bring up/shut down of the supplicant daemon and for 115 * sending requests to the supplicant daemon 116 * 117 * {@hide} 118 */ 119 public class WifiNative { 120 private static final String TAG = "WifiNative"; 121 122 private final SupplicantStaIfaceHal mSupplicantStaIfaceHal; 123 private final HostapdHal mHostapdHal; 124 private final WifiVendorHal mWifiVendorHal; 125 private final WifiNl80211Manager mWifiCondManager; 126 private final WifiMonitor mWifiMonitor; 127 private final PropertyService mPropertyService; 128 private final WifiMetrics mWifiMetrics; 129 private final Handler mHandler; 130 private final Random mRandom; 131 private final BuildProperties mBuildProperties; 132 private final WifiInjector mWifiInjector; 133 private final WifiContext mContext; 134 private NetdWrapper mNetdWrapper; 135 private boolean mVerboseLoggingEnabled = false; 136 private boolean mIsEnhancedOpenSupported = false; 137 private final List<CoexUnsafeChannel> mCachedCoexUnsafeChannels = new ArrayList<>(); 138 private int mCachedCoexRestrictions; 139 private CountryCodeChangeListenerInternal mCountryCodeChangeListener; 140 private boolean mUseFakeScanDetails; 141 private final ArrayList<ScanDetail> mFakeScanDetails = new ArrayList<>(); 142 private long mCachedFeatureSet; 143 private boolean mQosPolicyFeatureEnabled = false; 144 private final Map<String, String> mWifiCondIfacesForBridgedAp = new ArrayMap<>(); 145 private MockWifiServiceUtil mMockWifiModem = null; 146 private InterfaceObserverInternal mInterfaceObserver; 147 private InterfaceEventCallback mInterfaceListener; 148 private @WifiManager.MloMode int mCachedMloMode = WifiManager.MLO_MODE_DEFAULT; 149 private boolean mIsLocationModeEnabled = false; 150 private long mLastLocationModeEnabledTimeMs = 0; 151 private Map<String, Bundle> mCachedTwtCapabilities = new ArrayMap<>(); 152 /** 153 * Mapping of unknown AKMs configured in overlay config item 154 * config_wifiUnknownAkmToKnownAkmMapping to ScanResult security key management scheme 155 * (ScanResult.KEY_MGMT_XX) 156 */ 157 @VisibleForTesting @Nullable SparseIntArray mUnknownAkmMap; 158 WifiNative(WifiVendorHal vendorHal, SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal, WifiNl80211Manager condManager, WifiMonitor wifiMonitor, PropertyService propertyService, WifiMetrics wifiMetrics, Handler handler, Random random, BuildProperties buildProperties, WifiInjector wifiInjector)159 public WifiNative(WifiVendorHal vendorHal, 160 SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal, 161 WifiNl80211Manager condManager, WifiMonitor wifiMonitor, 162 PropertyService propertyService, WifiMetrics wifiMetrics, 163 Handler handler, Random random, BuildProperties buildProperties, 164 WifiInjector wifiInjector) { 165 mWifiVendorHal = vendorHal; 166 mSupplicantStaIfaceHal = staIfaceHal; 167 mHostapdHal = hostapdHal; 168 mWifiCondManager = condManager; 169 mWifiMonitor = wifiMonitor; 170 mPropertyService = propertyService; 171 mWifiMetrics = wifiMetrics; 172 mHandler = handler; 173 mRandom = random; 174 mBuildProperties = buildProperties; 175 mWifiInjector = wifiInjector; 176 mContext = wifiInjector.getContext(); 177 initializeUnknownAkmMapping(); 178 } 179 initializeUnknownAkmMapping()180 private void initializeUnknownAkmMapping() { 181 String[] unknownAkmMapping = 182 mContext.getResources() 183 .getStringArray(R.array.config_wifiUnknownAkmToKnownAkmMapping); 184 if (unknownAkmMapping == null) { 185 return; 186 } 187 for (String line : unknownAkmMapping) { 188 if (line == null) { 189 continue; 190 } 191 String[] items = line.split(","); 192 if (items.length != 2) { 193 Log.e( 194 TAG, 195 "Failed to parse config_wifiUnknownAkmToKnownAkmMapping line=" 196 + line 197 + ". Should contain only two values separated by comma"); 198 continue; 199 } 200 try { 201 int unknownAkm = Integer.parseInt(items[0].trim()); 202 int knownAkm = Integer.parseInt(items[1].trim()); 203 // Convert the OEM configured known AKM suite selector to 204 // ScanResult security key management scheme(ScanResult.KEY_MGMT_XX)*/ 205 int keyMgmtScheme = 206 InformationElementUtil.Capabilities.akmToScanResultKeyManagementScheme( 207 knownAkm); 208 if (keyMgmtScheme != ScanResult.KEY_MGMT_UNKNOWN) { 209 if (mUnknownAkmMap == null) { 210 mUnknownAkmMap = new SparseIntArray(); 211 } 212 mUnknownAkmMap.put(unknownAkm, keyMgmtScheme); 213 Log.d( 214 TAG, 215 "unknown AKM = " 216 + unknownAkm 217 + " - converted keyMgmtScheme: " 218 + keyMgmtScheme); 219 } else { 220 Log.e( 221 TAG, 222 "Known AKM: " 223 + knownAkm 224 + " is not defined in the framework." 225 + " Hence Failed to add AKM: " 226 + unknownAkm 227 + " in UnknownAkmMap." 228 + " Parsed config from overlay: " 229 + line); 230 } 231 } catch (Exception e) { 232 // failure to parse. Something is wrong with the configuration. 233 Log.e( 234 TAG, 235 "Parsing config_wifiUnknownAkmToKnownAkmMapping line=" 236 + line 237 + ". Exception occurred:" 238 + e); 239 } 240 } 241 } 242 243 /** 244 * Enable verbose logging for all sub modules. 245 */ enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled)246 public void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) { 247 Log.d(TAG, "enableVerboseLogging " + verboseEnabled + " hal " + halVerboseEnabled); 248 mVerboseLoggingEnabled = verboseEnabled; 249 mWifiCondManager.enableVerboseLogging(verboseEnabled); 250 mSupplicantStaIfaceHal.enableVerboseLogging(verboseEnabled, halVerboseEnabled); 251 mHostapdHal.enableVerboseLogging(verboseEnabled, halVerboseEnabled); 252 mWifiVendorHal.enableVerboseLogging(verboseEnabled, halVerboseEnabled); 253 mIfaceMgr.enableVerboseLogging(verboseEnabled); 254 } 255 256 /** 257 * Get TWT capabilities for the interface 258 */ getTwtCapabilities(String interfaceName)259 public Bundle getTwtCapabilities(String interfaceName) { 260 return mCachedTwtCapabilities.get(interfaceName); 261 } 262 263 /** 264 * Callbacks for SoftAp interface. 265 */ 266 public class SoftApHalCallbackFromWificond implements WifiNl80211Manager.SoftApCallback { 267 // placeholder for now - provide a shell so that clients don't use a 268 // WifiNl80211Manager-specific API. 269 private String mIfaceName; 270 private SoftApHalCallback mSoftApHalCallback; 271 SoftApHalCallbackFromWificond(String ifaceName, SoftApHalCallback softApHalCallback)272 SoftApHalCallbackFromWificond(String ifaceName, 273 SoftApHalCallback softApHalCallback) { 274 mIfaceName = ifaceName; 275 mSoftApHalCallback = softApHalCallback; 276 } 277 278 @Override onFailure()279 public void onFailure() { 280 mSoftApHalCallback.onFailure(); 281 } 282 283 @Override onSoftApChannelSwitched(int frequency, int bandwidth)284 public void onSoftApChannelSwitched(int frequency, int bandwidth) { 285 mSoftApHalCallback.onInfoChanged(mIfaceName, frequency, bandwidth, 286 ScanResult.WIFI_STANDARD_UNKNOWN, null, Collections.emptyList()); 287 } 288 289 @Override onConnectedClientsChanged(NativeWifiClient client, boolean isConnected)290 public void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected) { 291 mSoftApHalCallback.onConnectedClientsChanged(mIfaceName, 292 client.getMacAddress(), isConnected); 293 } 294 } 295 296 @SuppressLint("NewApi") 297 private static class CountryCodeChangeListenerInternal implements 298 WifiNl80211Manager.CountryCodeChangedListener { 299 private WifiCountryCode.ChangeListener mListener; 300 setChangeListener(@onNull WifiCountryCode.ChangeListener listener)301 public void setChangeListener(@NonNull WifiCountryCode.ChangeListener listener) { 302 mListener = listener; 303 } 304 onSetCountryCodeSucceeded(String country)305 public void onSetCountryCodeSucceeded(String country) { 306 Log.d(TAG, "onSetCountryCodeSucceeded: " + country); 307 if (mListener != null) { 308 mListener.onSetCountryCodeSucceeded(country); 309 } 310 } 311 312 @Override onCountryCodeChanged(String country)313 public void onCountryCodeChanged(String country) { 314 Log.d(TAG, "onCountryCodeChanged: " + country); 315 if (mListener != null) { 316 mListener.onDriverCountryCodeChanged(country); 317 } 318 } 319 } 320 321 /** 322 * Callbacks for SoftAp instance. 323 */ 324 public interface SoftApHalCallback { 325 /** 326 * Invoked when there is a fatal failure and the SoftAp is shutdown. 327 */ onFailure()328 void onFailure(); 329 330 /** 331 * Invoked when there is a fatal happen in specific instance only. 332 */ onInstanceFailure(String instanceName)333 default void onInstanceFailure(String instanceName) {} 334 335 /** 336 * Invoked when a channel switch event happens - i.e. the SoftAp is moved to a different 337 * channel. Also called on initial registration. 338 * 339 * @param apIfaceInstance The identity of the ap instance. 340 * @param frequency The new frequency of the SoftAp. A value of 0 is invalid and is an 341 * indication that the SoftAp is not enabled. 342 * @param bandwidth The new bandwidth of the SoftAp. 343 * @param generation The new generation of the SoftAp. 344 * @param vendorData List of {@link OuiKeyedData} containing vendor-specific configuration 345 * data, or empty list if not provided. 346 */ onInfoChanged(String apIfaceInstance, int frequency, int bandwidth, int generation, MacAddress apIfaceInstanceMacAddress, @NonNull List<OuiKeyedData> vendorData)347 void onInfoChanged(String apIfaceInstance, int frequency, int bandwidth, 348 int generation, MacAddress apIfaceInstanceMacAddress, 349 @NonNull List<OuiKeyedData> vendorData); 350 /** 351 * Invoked when there is a change in the associated station (STA). 352 * 353 * @param apIfaceInstance The identity of the ap instance. 354 * @param clientAddress Macaddress of the client. 355 * @param isConnected Indication as to whether the client is connected (true), or 356 * disconnected (false). 357 */ onConnectedClientsChanged(String apIfaceInstance, MacAddress clientAddress, boolean isConnected)358 void onConnectedClientsChanged(String apIfaceInstance, MacAddress clientAddress, 359 boolean isConnected); 360 } 361 362 /******************************************************** 363 * Interface management related methods. 364 ********************************************************/ 365 /** 366 * Meta-info about every iface that is active. 367 */ 368 public static class Iface { 369 /** Type of ifaces possible */ 370 public static final int IFACE_TYPE_AP = 0; 371 public static final int IFACE_TYPE_STA_FOR_CONNECTIVITY = 1; 372 public static final int IFACE_TYPE_STA_FOR_SCAN = 2; 373 public static final int IFACE_TYPE_P2P = 3; 374 public static final int IFACE_TYPE_NAN = 4; 375 376 @IntDef({IFACE_TYPE_AP, IFACE_TYPE_STA_FOR_CONNECTIVITY, IFACE_TYPE_STA_FOR_SCAN, 377 IFACE_TYPE_P2P, IFACE_TYPE_NAN}) 378 @Retention(RetentionPolicy.SOURCE) 379 public @interface IfaceType{} 380 381 /** Identifier allocated for the interface */ 382 public final int id; 383 /** Type of the iface: STA (for Connectivity or Scan) or AP */ 384 public @IfaceType int type; 385 /** Name of the interface */ 386 public String name; 387 /** Is the interface up? This is used to mask up/down notifications to external clients. */ 388 public boolean isUp; 389 /** External iface destroyed listener for the iface */ 390 public InterfaceCallback externalListener; 391 /** Network observer registered for this interface */ 392 public NetworkObserverInternal networkObserver; 393 /** Interface feature set / capabilities */ 394 public long featureSet; 395 public int bandsSupported; 396 public DeviceWiphyCapabilities phyCapabilities; 397 public WifiHal.WifiInterface iface; 398 Iface(int id, @Iface.IfaceType int type)399 Iface(int id, @Iface.IfaceType int type) { 400 this.id = id; 401 this.type = type; 402 } 403 404 @Override toString()405 public String toString() { 406 StringBuffer sb = new StringBuffer(); 407 String typeString; 408 switch(type) { 409 case IFACE_TYPE_STA_FOR_CONNECTIVITY: 410 typeString = "STA_CONNECTIVITY"; 411 break; 412 case IFACE_TYPE_STA_FOR_SCAN: 413 typeString = "STA_SCAN"; 414 break; 415 case IFACE_TYPE_AP: 416 typeString = "AP"; 417 break; 418 default: 419 typeString = "<UNKNOWN>"; 420 break; 421 } 422 sb.append("Iface:") 423 .append("{") 424 .append("Name=").append(name) 425 .append(",") 426 .append("Id=").append(id) 427 .append(",") 428 .append("Type=").append(typeString) 429 .append("}"); 430 return sb.toString(); 431 } 432 } 433 434 /** 435 * Iface Management entity. This class maintains list of all the active ifaces. 436 */ 437 private static class IfaceManager { 438 /** Integer to allocate for the next iface being created */ 439 private int mNextId; 440 /** Map of the id to the iface structure */ 441 private HashMap<Integer, Iface> mIfaces = new HashMap<>(); 442 private boolean mVerboseLoggingEnabled = false; 443 enableVerboseLogging(boolean enable)444 public void enableVerboseLogging(boolean enable) { 445 mVerboseLoggingEnabled = enable; 446 } 447 448 /** Allocate a new iface for the given type */ allocateIface(@face.IfaceType int type)449 private Iface allocateIface(@Iface.IfaceType int type) { 450 if (mVerboseLoggingEnabled) { 451 Log.d(TAG, "IfaceManager#allocateIface: type=" + type + ", pre-map=" + mIfaces); 452 } 453 Iface iface = new Iface(mNextId, type); 454 mIfaces.put(mNextId, iface); 455 mNextId++; 456 return iface; 457 } 458 459 /** Remove the iface using the provided id */ removeIface(int id)460 private Iface removeIface(int id) { 461 if (mVerboseLoggingEnabled) { 462 Log.d(TAG, "IfaceManager#removeIface: id=" + id + ", pre-map=" + mIfaces); 463 } 464 return mIfaces.remove(id); 465 } 466 467 /** Lookup the iface using the provided id */ getIface(int id)468 private Iface getIface(int id) { 469 return mIfaces.get(id); 470 } 471 472 /** Lookup the iface using the provided name */ getIface(@onNull String ifaceName)473 private Iface getIface(@NonNull String ifaceName) { 474 for (Iface iface : mIfaces.values()) { 475 if (TextUtils.equals(iface.name, ifaceName)) { 476 return iface; 477 } 478 } 479 return null; 480 } 481 482 /** Iterator to use for deleting all the ifaces while performing teardown on each of them */ getIfaceIdIter()483 private Iterator<Integer> getIfaceIdIter() { 484 return mIfaces.keySet().iterator(); 485 } 486 487 /** Checks if there are any iface active. */ hasAnyIface()488 private boolean hasAnyIface() { 489 return !mIfaces.isEmpty(); 490 } 491 492 /** Checks if there are any iface of the given type active. */ hasAnyIfaceOfType(@face.IfaceType int type)493 private boolean hasAnyIfaceOfType(@Iface.IfaceType int type) { 494 for (Iface iface : mIfaces.values()) { 495 if (iface.type == type) { 496 return true; 497 } 498 } 499 return false; 500 } 501 502 /** Checks if there are any P2P iface active. */ hasAnyP2pIface()503 private boolean hasAnyP2pIface() { 504 return hasAnyIfaceOfType(Iface.IFACE_TYPE_P2P); 505 } 506 507 /** Checks if there are any STA (for connectivity) iface active. */ hasAnyStaIfaceForConnectivity()508 private boolean hasAnyStaIfaceForConnectivity() { 509 return hasAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY); 510 } 511 512 /** Checks if there are any STA (for scan) iface active. */ hasAnyStaIfaceForScan()513 private boolean hasAnyStaIfaceForScan() { 514 return hasAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_SCAN); 515 } 516 517 /** Checks if there are any AP iface active. */ hasAnyApIface()518 private boolean hasAnyApIface() { 519 return hasAnyIfaceOfType(Iface.IFACE_TYPE_AP); 520 } 521 findAllStaIfaceNames()522 private @NonNull Set<String> findAllStaIfaceNames() { 523 Set<String> ifaceNames = new ArraySet<>(); 524 for (Iface iface : mIfaces.values()) { 525 if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY 526 || iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { 527 ifaceNames.add(iface.name); 528 } 529 } 530 return ifaceNames; 531 } 532 findAllApIfaceNames()533 private @NonNull Set<String> findAllApIfaceNames() { 534 Set<String> ifaceNames = new ArraySet<>(); 535 for (Iface iface : mIfaces.values()) { 536 if (iface.type == Iface.IFACE_TYPE_AP) { 537 ifaceNames.add(iface.name); 538 } 539 } 540 return ifaceNames; 541 } 542 543 /** Removes the existing iface that does not match the provided id. */ removeExistingIface(int newIfaceId)544 public Iface removeExistingIface(int newIfaceId) { 545 if (mVerboseLoggingEnabled) { 546 Log.d(TAG, "IfaceManager#removeExistingIface: newIfaceId=" + newIfaceId 547 + ", pre-map=" + mIfaces); 548 } 549 Iface removedIface = null; 550 // The number of ifaces in the database could be 1 existing & 1 new at the max. 551 if (mIfaces.size() > 2) { 552 Log.wtf(TAG, "More than 1 existing interface found"); 553 } 554 Iterator<Map.Entry<Integer, Iface>> iter = mIfaces.entrySet().iterator(); 555 while (iter.hasNext()) { 556 Map.Entry<Integer, Iface> entry = iter.next(); 557 if (entry.getKey() != newIfaceId) { 558 removedIface = entry.getValue(); 559 iter.remove(); 560 } 561 } 562 return removedIface; 563 } 564 565 @Override toString()566 public String toString() { 567 return mIfaces.toString(); 568 } 569 } 570 571 private class NormalScanEventCallback implements WifiNl80211Manager.ScanEventCallback { 572 private String mIfaceName; 573 NormalScanEventCallback(String ifaceName)574 NormalScanEventCallback(String ifaceName) { 575 mIfaceName = ifaceName; 576 } 577 578 @Override onScanResultReady()579 public void onScanResultReady() { 580 Log.d(TAG, "Scan result ready event"); 581 mWifiMonitor.broadcastScanResultEvent(mIfaceName); 582 } 583 584 @Override onScanFailed()585 public void onScanFailed() { 586 Log.d(TAG, "Scan failed event"); 587 mWifiMonitor.broadcastScanFailedEvent(mIfaceName, WifiScanner.REASON_UNSPECIFIED); 588 } 589 590 @Override onScanFailed(int errorCode)591 public void onScanFailed(int errorCode) { 592 Log.d(TAG, "Scan failed event: errorCode: " + errorCode); 593 mWifiMonitor.broadcastScanFailedEvent(mIfaceName, errorCode); 594 } 595 } 596 597 private class PnoScanEventCallback implements WifiNl80211Manager.ScanEventCallback { 598 private String mIfaceName; 599 PnoScanEventCallback(String ifaceName)600 PnoScanEventCallback(String ifaceName) { 601 mIfaceName = ifaceName; 602 } 603 604 @Override onScanResultReady()605 public void onScanResultReady() { 606 Log.d(TAG, "Pno scan result event"); 607 mWifiMonitor.broadcastPnoScanResultEvent(mIfaceName); 608 mWifiMetrics.incrementPnoFoundNetworkEventCount(); 609 } 610 611 @Override onScanFailed()612 public void onScanFailed() { 613 Log.d(TAG, "Pno Scan failed event"); 614 WifiStatsLog.write(WifiStatsLog.PNO_SCAN_STOPPED, 615 WifiStatsLog.PNO_SCAN_STOPPED__STOP_REASON__SCAN_FAILED, 616 0, false, false, false, false, // default values 617 WifiStatsLog.PNO_SCAN_STOPPED__FAILURE_CODE__WIFICOND_SCAN_FAILURE); 618 } 619 } 620 621 private final Object mLock = new Object(); 622 private final IfaceManager mIfaceMgr = new IfaceManager(); 623 private HashSet<StatusListener> mStatusListeners = new HashSet<>(); 624 625 /** Helper method invoked to start supplicant if there were no ifaces */ startHal()626 private boolean startHal() { 627 synchronized (mLock) { 628 if (!mIfaceMgr.hasAnyIface()) { 629 if (mWifiVendorHal.isVendorHalSupported()) { 630 if (!mWifiVendorHal.startVendorHal()) { 631 Log.e(TAG, "Failed to start vendor HAL"); 632 return false; 633 } 634 if (SdkLevel.isAtLeastS()) { 635 mWifiVendorHal.setCoexUnsafeChannels( 636 mCachedCoexUnsafeChannels, mCachedCoexRestrictions); 637 } 638 } else { 639 Log.i(TAG, "Vendor Hal not supported, ignoring start."); 640 } 641 } 642 registerWificondListenerIfNecessary(); 643 return true; 644 } 645 } 646 647 /** Helper method invoked to stop HAL if there are no more ifaces */ stopHalAndWificondIfNecessary()648 private void stopHalAndWificondIfNecessary() { 649 synchronized (mLock) { 650 if (!mIfaceMgr.hasAnyIface()) { 651 if (!mWifiCondManager.tearDownInterfaces()) { 652 Log.e(TAG, "Failed to teardown ifaces from wificond"); 653 } 654 if (mWifiVendorHal.isVendorHalSupported()) { 655 mWifiVendorHal.stopVendorHal(); 656 } else { 657 Log.i(TAG, "Vendor Hal not supported, ignoring stop."); 658 } 659 } 660 } 661 } 662 663 /** 664 * Helper method invoked to setup wificond related callback/listener. 665 */ registerWificondListenerIfNecessary()666 private void registerWificondListenerIfNecessary() { 667 if (mCountryCodeChangeListener == null && SdkLevel.isAtLeastS()) { 668 // The country code listener is a new API in S. 669 mCountryCodeChangeListener = new CountryCodeChangeListenerInternal(); 670 mWifiCondManager.registerCountryCodeChangedListener(Runnable::run, 671 mCountryCodeChangeListener); 672 } 673 } 674 675 private static final int CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS = 100; 676 private static final int CONNECT_TO_SUPPLICANT_RETRY_TIMES = 50; 677 /** 678 * This method is called to wait for establishing connection to wpa_supplicant. 679 * 680 * @return true if connection is established, false otherwise. 681 */ startAndWaitForSupplicantConnection()682 private boolean startAndWaitForSupplicantConnection() { 683 // Start initialization if not already started. 684 if (!mSupplicantStaIfaceHal.isInitializationStarted() 685 && !mSupplicantStaIfaceHal.initialize()) { 686 return false; 687 } 688 if (!mSupplicantStaIfaceHal.startDaemon()) { 689 Log.e(TAG, "Failed to startup supplicant"); 690 return false; 691 } 692 boolean connected = false; 693 int connectTries = 0; 694 while (!connected && connectTries++ < CONNECT_TO_SUPPLICANT_RETRY_TIMES) { 695 // Check if the initialization is complete. 696 connected = mSupplicantStaIfaceHal.isInitializationComplete(); 697 if (connected) { 698 break; 699 } 700 try { 701 Thread.sleep(CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS); 702 } catch (InterruptedException ignore) { 703 } 704 } 705 return connected; 706 } 707 708 /** Helper method invoked to start supplicant if there were no STA ifaces */ startSupplicant()709 private boolean startSupplicant() { 710 synchronized (mLock) { 711 if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) { 712 if (!startAndWaitForSupplicantConnection()) { 713 Log.e(TAG, "Failed to connect to supplicant"); 714 return false; 715 } 716 if (!mSupplicantStaIfaceHal.registerDeathHandler( 717 new SupplicantDeathHandlerInternal())) { 718 Log.e(TAG, "Failed to register supplicant death handler"); 719 return false; 720 } 721 } 722 return true; 723 } 724 } 725 726 /** Helper method invoked to stop supplicant if there are no more STA ifaces */ stopSupplicantIfNecessary()727 private void stopSupplicantIfNecessary() { 728 synchronized (mLock) { 729 if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) { 730 if (mSupplicantStaIfaceHal.isInitializationStarted()) { 731 if (!mSupplicantStaIfaceHal.deregisterDeathHandler()) { 732 Log.e(TAG, "Failed to deregister supplicant death handler"); 733 } 734 735 } 736 if (!mIfaceMgr.hasAnyP2pIface()) { 737 if (mSupplicantStaIfaceHal.isInitializationStarted()) { 738 mSupplicantStaIfaceHal.terminate(); 739 } else { 740 mWifiInjector.getWifiP2pNative().stopP2pSupplicantIfNecessary(); 741 } 742 } 743 } 744 } 745 } 746 747 /** Helper method invoked to start hostapd if there were no AP ifaces */ startHostapd()748 private boolean startHostapd() { 749 synchronized (mLock) { 750 if (!mIfaceMgr.hasAnyApIface()) { 751 if (!startAndWaitForHostapdConnection()) { 752 Log.e(TAG, "Failed to connect to hostapd"); 753 return false; 754 } 755 if (!mHostapdHal.registerDeathHandler( 756 new HostapdDeathHandlerInternal())) { 757 Log.e(TAG, "Failed to register hostapd death handler"); 758 return false; 759 } 760 } 761 return true; 762 } 763 } 764 765 /** Helper method invoked to stop hostapd if there are no more AP ifaces */ stopHostapdIfNecessary()766 private void stopHostapdIfNecessary() { 767 synchronized (mLock) { 768 if (!mIfaceMgr.hasAnyApIface()) { 769 if (!mHostapdHal.deregisterDeathHandler()) { 770 Log.e(TAG, "Failed to deregister hostapd death handler"); 771 } 772 mHostapdHal.terminate(); 773 } 774 } 775 } 776 777 /** 778 * Helper method to register a new {@link InterfaceObserverInternal}, if there is no previous 779 * observer in place and {@link WifiGlobals#isWifiInterfaceAddedSelfRecoveryEnabled()} is 780 * enabled. 781 */ registerInterfaceObserver()782 private void registerInterfaceObserver() { 783 if (!mWifiInjector.getWifiGlobals().isWifiInterfaceAddedSelfRecoveryEnabled()) { 784 return; 785 } 786 if (mInterfaceObserver != null) { 787 Log.d(TAG, "Interface observer has previously been registered."); 788 return; 789 } 790 mInterfaceObserver = new InterfaceObserverInternal(); 791 mNetdWrapper.registerObserver(mInterfaceObserver); 792 Log.d(TAG, "Registered new interface observer."); 793 } 794 795 /** Helper method to register a network observer and return it */ registerNetworkObserver(NetworkObserverInternal observer)796 private boolean registerNetworkObserver(NetworkObserverInternal observer) { 797 if (observer == null) return false; 798 mNetdWrapper.registerObserver(observer); 799 return true; 800 } 801 802 /** Helper method to unregister a network observer */ unregisterNetworkObserver(NetworkObserverInternal observer)803 private boolean unregisterNetworkObserver(NetworkObserverInternal observer) { 804 if (observer == null) return false; 805 mNetdWrapper.unregisterObserver(observer); 806 return true; 807 } 808 809 /** 810 * Helper method invoked to teardown client iface (for connectivity) and perform 811 * necessary cleanup 812 */ onClientInterfaceForConnectivityDestroyed(@onNull Iface iface)813 private void onClientInterfaceForConnectivityDestroyed(@NonNull Iface iface) { 814 synchronized (mLock) { 815 mWifiMonitor.stopMonitoring(iface.name); 816 if (!unregisterNetworkObserver(iface.networkObserver)) { 817 Log.e(TAG, "Failed to unregister network observer on " + iface); 818 } 819 if (!mSupplicantStaIfaceHal.teardownIface(iface.name)) { 820 Log.e(TAG, "Failed to teardown iface in supplicant on " + iface); 821 } 822 if (!mWifiCondManager.tearDownClientInterface(iface.name)) { 823 Log.e(TAG, "Failed to teardown iface in wificond on " + iface); 824 } 825 stopSupplicantIfNecessary(); 826 stopHalAndWificondIfNecessary(); 827 } 828 } 829 830 /** Helper method invoked to teardown client iface (for scan) and perform necessary cleanup */ onClientInterfaceForScanDestroyed(@onNull Iface iface)831 private void onClientInterfaceForScanDestroyed(@NonNull Iface iface) { 832 synchronized (mLock) { 833 mWifiMonitor.stopMonitoring(iface.name); 834 if (!unregisterNetworkObserver(iface.networkObserver)) { 835 Log.e(TAG, "Failed to unregister network observer on " + iface); 836 } 837 if (!mWifiCondManager.tearDownClientInterface(iface.name)) { 838 Log.e(TAG, "Failed to teardown iface in wificond on " + iface); 839 } 840 stopHalAndWificondIfNecessary(); 841 } 842 } 843 844 /** Helper method invoked to teardown softAp iface and perform necessary cleanup */ onSoftApInterfaceDestroyed(@onNull Iface iface)845 private void onSoftApInterfaceDestroyed(@NonNull Iface iface) { 846 synchronized (mLock) { 847 if (!unregisterNetworkObserver(iface.networkObserver)) { 848 Log.e(TAG, "Failed to unregister network observer on " + iface); 849 } 850 if (!mHostapdHal.removeAccessPoint(iface.name)) { 851 Log.e(TAG, "Failed to remove access point on " + iface); 852 } 853 String wificondIface = iface.name; 854 String bridgedApInstance = mWifiCondIfacesForBridgedAp.remove(iface.name); 855 if (bridgedApInstance != null) { 856 wificondIface = bridgedApInstance; 857 } 858 if (!mWifiCondManager.tearDownSoftApInterface(wificondIface)) { 859 Log.e(TAG, "Failed to teardown iface in wificond on " + iface); 860 } 861 stopHostapdIfNecessary(); 862 stopHalAndWificondIfNecessary(); 863 } 864 } 865 866 /** Helper method invoked to teardown iface and perform necessary cleanup */ onInterfaceDestroyed(@onNull Iface iface)867 private void onInterfaceDestroyed(@NonNull Iface iface) { 868 synchronized (mLock) { 869 if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY) { 870 onClientInterfaceForConnectivityDestroyed(iface); 871 } else if (iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { 872 onClientInterfaceForScanDestroyed(iface); 873 } else if (iface.type == Iface.IFACE_TYPE_AP) { 874 onSoftApInterfaceDestroyed(iface); 875 } 876 // Invoke the external callback only if the iface was not destroyed because of vendor 877 // HAL crash. In case of vendor HAL crash, let the crash recovery destroy the mode 878 // managers. 879 if (mWifiVendorHal.isVendorHalReady()) { 880 iface.externalListener.onDestroyed(iface.name); 881 } 882 } 883 } 884 885 /** 886 * Callback to be invoked by HalDeviceManager when an interface is destroyed. 887 */ 888 private class InterfaceDestoyedListenerInternal 889 implements HalDeviceManager.InterfaceDestroyedListener { 890 /** Identifier allocated for the interface */ 891 private final int mInterfaceId; 892 InterfaceDestoyedListenerInternal(int ifaceId)893 InterfaceDestoyedListenerInternal(int ifaceId) { 894 mInterfaceId = ifaceId; 895 } 896 897 @Override onDestroyed(@onNull String ifaceName)898 public void onDestroyed(@NonNull String ifaceName) { 899 synchronized (mLock) { 900 final Iface iface = mIfaceMgr.removeIface(mInterfaceId); 901 if (iface == null) { 902 if (mVerboseLoggingEnabled) { 903 Log.v(TAG, "Received iface destroyed notification on an invalid iface=" 904 + ifaceName); 905 } 906 return; 907 } 908 onInterfaceDestroyed(iface); 909 Log.i(TAG, "Successfully torn down " + iface); 910 } 911 } 912 } 913 914 /** 915 * Helper method invoked to trigger the status changed callback after one of the native 916 * daemon's death. 917 */ onNativeDaemonDeath()918 private void onNativeDaemonDeath() { 919 synchronized (mLock) { 920 for (StatusListener listener : mStatusListeners) { 921 listener.onStatusChanged(false); 922 } 923 for (StatusListener listener : mStatusListeners) { 924 listener.onStatusChanged(true); 925 } 926 } 927 } 928 929 /** 930 * Death handler for the Vendor HAL daemon. 931 */ 932 private class VendorHalDeathHandlerInternal implements VendorHalDeathEventHandler { 933 @Override onDeath()934 public void onDeath() { 935 mHandler.post(() -> { 936 Log.i(TAG, "Vendor HAL died. Cleaning up internal state."); 937 onNativeDaemonDeath(); 938 mWifiMetrics.incrementNumHalCrashes(); 939 }); 940 } 941 } 942 943 /** 944 * Death handler for the wificond daemon. 945 */ 946 private class WificondDeathHandlerInternal implements Runnable { 947 @Override run()948 public void run() { 949 mHandler.post(() -> { 950 Log.i(TAG, "wificond died. Cleaning up internal state."); 951 onNativeDaemonDeath(); 952 mWifiMetrics.incrementNumWificondCrashes(); 953 }); 954 } 955 } 956 957 /** 958 * Death handler for the supplicant daemon. 959 */ 960 private class SupplicantDeathHandlerInternal implements SupplicantDeathEventHandler { 961 @Override onDeath()962 public void onDeath() { 963 mHandler.post(() -> { 964 Log.i(TAG, "wpa_supplicant died. Cleaning up internal state."); 965 onNativeDaemonDeath(); 966 mWifiMetrics.incrementNumSupplicantCrashes(); 967 }); 968 } 969 } 970 971 /** 972 * Death handler for the hostapd daemon. 973 */ 974 private class HostapdDeathHandlerInternal implements HostapdDeathEventHandler { 975 @Override onDeath()976 public void onDeath() { 977 mHandler.post(() -> { 978 Log.i(TAG, "hostapd died. Cleaning up internal state."); 979 onNativeDaemonDeath(); 980 mWifiMetrics.incrementNumHostapdCrashes(); 981 }); 982 } 983 } 984 985 /** Helper method invoked to handle interface change. */ onInterfaceStateChanged(Iface iface, boolean isUp)986 private void onInterfaceStateChanged(Iface iface, boolean isUp) { 987 synchronized (mLock) { 988 // Mask multiple notifications with the same state. 989 if (isUp == iface.isUp) { 990 if (mVerboseLoggingEnabled) { 991 Log.v(TAG, "Interface status unchanged on " + iface + " from " + isUp 992 + ", Ignoring..."); 993 } 994 return; 995 } 996 Log.i(TAG, "Interface state changed on " + iface + ", isUp=" + isUp); 997 if (isUp) { 998 iface.externalListener.onUp(iface.name); 999 } else { 1000 iface.externalListener.onDown(iface.name); 1001 if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY 1002 || iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { 1003 mWifiMetrics.incrementNumClientInterfaceDown(); 1004 } else if (iface.type == Iface.IFACE_TYPE_AP) { 1005 mWifiMetrics.incrementNumSoftApInterfaceDown(); 1006 } 1007 } 1008 iface.isUp = isUp; 1009 } 1010 } 1011 1012 /** 1013 * Listener for wifi interface events. 1014 */ 1015 public interface InterfaceEventCallback { 1016 1017 /** 1018 * Interface physical-layer link state has changed. 1019 * 1020 * @param ifaceName The interface. 1021 * @param isLinkUp True if the physical link-layer connection signal is valid. 1022 */ onInterfaceLinkStateChanged(String ifaceName, boolean isLinkUp)1023 void onInterfaceLinkStateChanged(String ifaceName, boolean isLinkUp); 1024 1025 /** 1026 * Interface has been added. 1027 * 1028 * @param ifaceName Name of the interface. 1029 */ onInterfaceAdded(String ifaceName)1030 void onInterfaceAdded(String ifaceName); 1031 } 1032 1033 /** 1034 * Register a listener for wifi interface events. 1035 * 1036 * @param ifaceEventCallback Listener object. 1037 */ setWifiNativeInterfaceEventCallback(InterfaceEventCallback ifaceEventCallback)1038 public void setWifiNativeInterfaceEventCallback(InterfaceEventCallback ifaceEventCallback) { 1039 mInterfaceListener = ifaceEventCallback; 1040 Log.d(TAG, "setWifiNativeInterfaceEventCallback"); 1041 } 1042 1043 private class InterfaceObserverInternal implements NetdEventObserver { 1044 private static final String TAG = "InterfaceObserverInternal"; 1045 private final String mSelfRecoveryInterfaceName = mContext.getResources().getString( 1046 R.string.config_wifiSelfRecoveryInterfaceName); 1047 1048 @Override interfaceLinkStateChanged(String ifaceName, boolean isLinkUp)1049 public void interfaceLinkStateChanged(String ifaceName, boolean isLinkUp) { 1050 if (!ifaceName.equals(mSelfRecoveryInterfaceName)) { 1051 return; 1052 } 1053 Log.d(TAG, "Received interfaceLinkStateChanged, iface=" + ifaceName + " up=" 1054 + isLinkUp); 1055 if (mInterfaceListener != null) { 1056 mInterfaceListener.onInterfaceLinkStateChanged(ifaceName, isLinkUp); 1057 } else { 1058 Log.e(TAG, "Received interfaceLinkStateChanged, interfaceListener=null"); 1059 } 1060 } 1061 1062 @Override interfaceStatusChanged(String iface, boolean up)1063 public void interfaceStatusChanged(String iface, boolean up) { 1064 // unused. 1065 } 1066 1067 @Override interfaceAdded(String ifaceName)1068 public void interfaceAdded(String ifaceName) { 1069 if (!ifaceName.equals(mSelfRecoveryInterfaceName)) { 1070 return; 1071 } 1072 Log.d(TAG, "Received interfaceAdded, iface=" + ifaceName); 1073 if (mInterfaceListener != null) { 1074 mInterfaceListener.onInterfaceAdded(ifaceName); 1075 } else { 1076 Log.e(TAG, "Received interfaceAdded, interfaceListener=null"); 1077 } 1078 } 1079 1080 } 1081 1082 /** 1083 * Network observer to use for all interface up/down notifications. 1084 */ 1085 private class NetworkObserverInternal implements NetdEventObserver { 1086 /** Identifier allocated for the interface */ 1087 private final int mInterfaceId; 1088 NetworkObserverInternal(int id)1089 NetworkObserverInternal(int id) { 1090 mInterfaceId = id; 1091 } 1092 1093 /** 1094 * Note: We should ideally listen to 1095 * {@link NetdEventObserver#interfaceStatusChanged(String, boolean)} here. But, that 1096 * callback is not working currently (broken in netd). So, instead listen to link state 1097 * change callbacks as triggers to query the real interface state. We should get rid of 1098 * this workaround if we get the |interfaceStatusChanged| callback to work in netd. 1099 * Also, this workaround will not detect an interface up event, if the link state is 1100 * still down. 1101 */ 1102 @Override interfaceLinkStateChanged(String ifaceName, boolean unusedIsLinkUp)1103 public void interfaceLinkStateChanged(String ifaceName, boolean unusedIsLinkUp) { 1104 // This is invoked from the main system_server thread. Post to our handler. 1105 mHandler.post(() -> { 1106 synchronized (mLock) { 1107 if (mVerboseLoggingEnabled) { 1108 Log.d(TAG, "interfaceLinkStateChanged: ifaceName=" + ifaceName 1109 + ", mInterfaceId = " + mInterfaceId 1110 + ", mIfaceMgr=" + mIfaceMgr.toString()); 1111 } 1112 final Iface ifaceWithId = mIfaceMgr.getIface(mInterfaceId); 1113 if (ifaceWithId == null) { 1114 if (mVerboseLoggingEnabled) { 1115 Log.v(TAG, "Received iface link up/down notification on an invalid" 1116 + " iface=" + mInterfaceId); 1117 } 1118 return; 1119 } 1120 final Iface ifaceWithName = mIfaceMgr.getIface(ifaceName); 1121 if (ifaceWithName == null || ifaceWithName != ifaceWithId) { 1122 if (mVerboseLoggingEnabled) { 1123 Log.v(TAG, "Received iface link up/down notification on an invalid" 1124 + " iface=" + ifaceName); 1125 } 1126 return; 1127 } 1128 onInterfaceStateChanged(ifaceWithName, isInterfaceUp(ifaceName)); 1129 } 1130 }); 1131 } 1132 1133 @Override interfaceStatusChanged(String ifaceName, boolean unusedIsLinkUp)1134 public void interfaceStatusChanged(String ifaceName, boolean unusedIsLinkUp) { 1135 // unused currently. Look at note above. 1136 } 1137 1138 @Override interfaceAdded(String iface)1139 public void interfaceAdded(String iface){ 1140 // unused currently. 1141 } 1142 } 1143 1144 /** 1145 * Radio mode change handler for the Vendor HAL daemon. 1146 */ 1147 private class VendorHalRadioModeChangeHandlerInternal 1148 implements VendorHalRadioModeChangeEventHandler { 1149 @Override onMcc(int band)1150 public void onMcc(int band) { 1151 synchronized (mLock) { 1152 Log.i(TAG, "Device is in MCC mode now"); 1153 mWifiMetrics.incrementNumRadioModeChangeToMcc(); 1154 } 1155 } 1156 @Override onScc(int band)1157 public void onScc(int band) { 1158 synchronized (mLock) { 1159 Log.i(TAG, "Device is in SCC mode now"); 1160 mWifiMetrics.incrementNumRadioModeChangeToScc(); 1161 } 1162 } 1163 @Override onSbs(int band)1164 public void onSbs(int band) { 1165 synchronized (mLock) { 1166 Log.i(TAG, "Device is in SBS mode now"); 1167 mWifiMetrics.incrementNumRadioModeChangeToSbs(); 1168 } 1169 } 1170 @Override onDbs()1171 public void onDbs() { 1172 synchronized (mLock) { 1173 Log.i(TAG, "Device is in DBS mode now"); 1174 mWifiMetrics.incrementNumRadioModeChangeToDbs(); 1175 } 1176 } 1177 } 1178 1179 // For devices that don't support the vendor HAL, we will not support any concurrency. 1180 // So simulate the HalDeviceManager behavior by triggering the destroy listener for 1181 // any active interface. handleIfaceCreationWhenVendorHalNotSupported(@onNull Iface newIface)1182 private String handleIfaceCreationWhenVendorHalNotSupported(@NonNull Iface newIface) { 1183 synchronized (mLock) { 1184 Iface existingIface = mIfaceMgr.removeExistingIface(newIface.id); 1185 if (existingIface != null) { 1186 onInterfaceDestroyed(existingIface); 1187 Log.i(TAG, "Successfully torn down " + existingIface); 1188 } 1189 // Return the interface name directly from the system property. 1190 return mPropertyService.getString("wifi.interface", "wlan0"); 1191 } 1192 } 1193 1194 /** 1195 * Helper function to handle creation of STA iface. 1196 * For devices which do not the support the HAL, this will bypass HalDeviceManager & 1197 * teardown any existing iface. 1198 */ createStaIface(@onNull Iface iface, @NonNull WorkSource requestorWs, @NonNull ConcreteClientModeManager concreteClientModeManager)1199 private String createStaIface(@NonNull Iface iface, @NonNull WorkSource requestorWs, 1200 @NonNull ConcreteClientModeManager concreteClientModeManager) { 1201 synchronized (mLock) { 1202 if (mWifiVendorHal.isVendorHalSupported()) { 1203 return mWifiVendorHal.createStaIface( 1204 new InterfaceDestoyedListenerInternal(iface.id), requestorWs, 1205 concreteClientModeManager); 1206 } else { 1207 Log.i(TAG, "Vendor Hal not supported, ignoring createStaIface."); 1208 return handleIfaceCreationWhenVendorHalNotSupported(iface); 1209 } 1210 } 1211 } 1212 1213 /** 1214 * Helper function to handle creation of AP iface. 1215 * For devices which do not the support the HAL, this will bypass HalDeviceManager & 1216 * teardown any existing iface. 1217 */ createApIface(@onNull Iface iface, @NonNull WorkSource requestorWs, @SoftApConfiguration.BandType int band, boolean isBridged, @NonNull SoftApManager softApManager, @NonNull List<OuiKeyedData> vendorData)1218 private String createApIface(@NonNull Iface iface, @NonNull WorkSource requestorWs, 1219 @SoftApConfiguration.BandType int band, boolean isBridged, 1220 @NonNull SoftApManager softApManager, @NonNull List<OuiKeyedData> vendorData) { 1221 synchronized (mLock) { 1222 if (mWifiVendorHal.isVendorHalSupported()) { 1223 return mWifiVendorHal.createApIface( 1224 new InterfaceDestoyedListenerInternal(iface.id), requestorWs, 1225 band, isBridged, softApManager, vendorData); 1226 } else { 1227 Log.i(TAG, "Vendor Hal not supported, ignoring createApIface."); 1228 return handleIfaceCreationWhenVendorHalNotSupported(iface); 1229 } 1230 } 1231 } 1232 createP2pIfaceFromHalOrGetNameFromProperty( HalDeviceManager.InterfaceDestroyedListener p2pInterfaceDestroyedListener, Handler handler, WorkSource requestorWs)1233 private String createP2pIfaceFromHalOrGetNameFromProperty( 1234 HalDeviceManager.InterfaceDestroyedListener p2pInterfaceDestroyedListener, 1235 Handler handler, WorkSource requestorWs) { 1236 synchronized (mLock) { 1237 if (mWifiVendorHal.isVendorHalSupported()) { 1238 return mWifiInjector.getHalDeviceManager().createP2pIface( 1239 p2pInterfaceDestroyedListener, handler, requestorWs); 1240 } else { 1241 Log.i(TAG, "Vendor Hal not supported, ignoring createStaIface."); 1242 return mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); 1243 } 1244 } 1245 } 1246 1247 /** 1248 * Helper function to handle creation of P2P iface. 1249 * For devices which do not the support the HAL, this will bypass HalDeviceManager & 1250 * teardown any existing iface. 1251 */ createP2pIface( HalDeviceManager.InterfaceDestroyedListener p2pInterfaceDestroyedListener, Handler handler, WorkSource requestorWs)1252 public Iface createP2pIface( 1253 HalDeviceManager.InterfaceDestroyedListener p2pInterfaceDestroyedListener, 1254 Handler handler, WorkSource requestorWs) { 1255 synchronized (mLock) { 1256 // Make sure HAL is started for p2p 1257 if (!startHal()) { 1258 Log.e(TAG, "Failed to start Hal"); 1259 mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToHal(); 1260 return null; 1261 } 1262 // maintain iface status in WifiNative 1263 Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_P2P); 1264 if (iface == null) { 1265 Log.e(TAG, "Failed to allocate new P2P iface"); 1266 stopHalAndWificondIfNecessary(); 1267 return null; 1268 } 1269 iface.name = createP2pIfaceFromHalOrGetNameFromProperty( 1270 p2pInterfaceDestroyedListener, handler, requestorWs); 1271 if (TextUtils.isEmpty(iface.name)) { 1272 Log.e(TAG, "Failed to create P2p iface in HalDeviceManager"); 1273 mIfaceMgr.removeIface(iface.id); 1274 mWifiMetrics.incrementNumSetupP2pInterfaceFailureDueToHal(); 1275 stopHalAndWificondIfNecessary(); 1276 return null; 1277 } 1278 return iface; 1279 } 1280 } 1281 1282 /** 1283 * Teardown P2p iface with input interface Id which was returned by createP2pIface. 1284 * 1285 * @param interfaceId the interface identify which was gerenated when creating P2p iface. 1286 */ teardownP2pIface(int interfaceId)1287 public void teardownP2pIface(int interfaceId) { 1288 synchronized (mLock) { 1289 mIfaceMgr.removeIface(interfaceId); 1290 stopHalAndWificondIfNecessary(); 1291 stopSupplicantIfNecessary(); 1292 } 1293 } 1294 1295 /** 1296 * Helper function to handle creation of Nan iface. 1297 */ createNanIface( HalDeviceManager.InterfaceDestroyedListener nanInterfaceDestroyedListener, Handler handler, WorkSource requestorWs)1298 public Iface createNanIface( 1299 HalDeviceManager.InterfaceDestroyedListener nanInterfaceDestroyedListener, 1300 Handler handler, WorkSource requestorWs) { 1301 synchronized (mLock) { 1302 // Make sure HAL is started for Nan 1303 if (!startHal()) { 1304 Log.e(TAG, "Failed to start Hal"); 1305 return null; 1306 } 1307 // maintain iface status in WifiNative 1308 Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_NAN); 1309 if (iface != null) { 1310 WifiNanIface nanIface = mWifiInjector.getHalDeviceManager().createNanIface( 1311 nanInterfaceDestroyedListener, handler, requestorWs); 1312 if (nanIface != null) { 1313 iface.iface = nanIface; 1314 return iface; 1315 } 1316 } 1317 Log.e(TAG, "Failed to allocate new Nan iface"); 1318 stopHalAndWificondIfNecessary(); 1319 return null; 1320 } 1321 } 1322 1323 /** 1324 * Teardown Nan iface with input interface Id which was returned by createP2pIface. 1325 * 1326 * @param interfaceId the interface identify which was gerenated when creating P2p iface. 1327 */ teardownNanIface(int interfaceId)1328 public void teardownNanIface(int interfaceId) { 1329 synchronized (mLock) { 1330 mIfaceMgr.removeIface(interfaceId); 1331 stopHalAndWificondIfNecessary(); 1332 } 1333 } 1334 1335 /** 1336 * Get list of instance name from this bridged AP iface. 1337 * 1338 * @param ifaceName Name of the bridged interface. 1339 * @return list of instance name when succeed, otherwise null. 1340 */ 1341 @Nullable getBridgedApInstances(@onNull String ifaceName)1342 public List<String> getBridgedApInstances(@NonNull String ifaceName) { 1343 synchronized (mLock) { 1344 if (mWifiVendorHal.isVendorHalSupported()) { 1345 return mWifiVendorHal.getBridgedApInstances(ifaceName); 1346 } else { 1347 Log.i(TAG, "Vendor Hal not supported, ignoring getBridgedApInstances."); 1348 return null; 1349 } 1350 } 1351 } 1352 1353 // For devices that don't support the vendor HAL, we will not support any concurrency. 1354 // So simulate the HalDeviceManager behavior by triggering the destroy listener for 1355 // the interface. handleIfaceRemovalWhenVendorHalNotSupported(@onNull Iface iface)1356 private boolean handleIfaceRemovalWhenVendorHalNotSupported(@NonNull Iface iface) { 1357 synchronized (mLock) { 1358 mIfaceMgr.removeIface(iface.id); 1359 onInterfaceDestroyed(iface); 1360 Log.i(TAG, "Successfully torn down " + iface); 1361 return true; 1362 } 1363 } 1364 1365 /** 1366 * Helper function to handle removal of STA iface. 1367 * For devices which do not the support the HAL, this will bypass HalDeviceManager & 1368 * teardown any existing iface. 1369 */ removeStaIface(@onNull Iface iface)1370 private boolean removeStaIface(@NonNull Iface iface) { 1371 synchronized (mLock) { 1372 if (mWifiVendorHal.isVendorHalSupported()) { 1373 return mWifiVendorHal.removeStaIface(iface.name); 1374 } else { 1375 Log.i(TAG, "Vendor Hal not supported, ignoring removeStaIface."); 1376 return handleIfaceRemovalWhenVendorHalNotSupported(iface); 1377 } 1378 } 1379 } 1380 1381 /** 1382 * Helper function to handle removal of STA iface. 1383 */ removeApIface(@onNull Iface iface)1384 private boolean removeApIface(@NonNull Iface iface) { 1385 synchronized (mLock) { 1386 if (mWifiVendorHal.isVendorHalSupported()) { 1387 return mWifiVendorHal.removeApIface(iface.name); 1388 } else { 1389 Log.i(TAG, "Vendor Hal not supported, ignoring removeApIface."); 1390 return handleIfaceRemovalWhenVendorHalNotSupported(iface); 1391 } 1392 } 1393 } 1394 1395 /** 1396 * Helper function to remove specific instance in bridged AP iface. 1397 * 1398 * @param ifaceName Name of the iface. 1399 * @param apIfaceInstance The identity of the ap instance. 1400 * @return true if the operation succeeded, false if there is an error in Hal. 1401 */ removeIfaceInstanceFromBridgedApIface(@onNull String ifaceName, @NonNull String apIfaceInstance)1402 public boolean removeIfaceInstanceFromBridgedApIface(@NonNull String ifaceName, 1403 @NonNull String apIfaceInstance) { 1404 synchronized (mLock) { 1405 if (mWifiVendorHal.isVendorHalSupported()) { 1406 return mWifiVendorHal.removeIfaceInstanceFromBridgedApIface(ifaceName, 1407 apIfaceInstance); 1408 } else { 1409 return false; 1410 } 1411 } 1412 } 1413 1414 /** 1415 * Register listener for subsystem restart event 1416 * 1417 * @param listener SubsystemRestartListener listener object. 1418 */ registerSubsystemRestartListener( HalDeviceManager.SubsystemRestartListener listener)1419 public void registerSubsystemRestartListener( 1420 HalDeviceManager.SubsystemRestartListener listener) { 1421 if (listener != null) { 1422 mWifiVendorHal.registerSubsystemRestartListener(listener); 1423 } 1424 } 1425 1426 /** 1427 * Initialize the native modules. 1428 * 1429 * @return true on success, false otherwise. 1430 */ initialize()1431 public boolean initialize() { 1432 synchronized (mLock) { 1433 if (!mWifiVendorHal.initialize(new VendorHalDeathHandlerInternal())) { 1434 Log.e(TAG, "Failed to initialize vendor HAL"); 1435 return false; 1436 } 1437 mWifiCondManager.setOnServiceDeadCallback(new WificondDeathHandlerInternal()); 1438 mWifiCondManager.tearDownInterfaces(); 1439 mWifiVendorHal.registerRadioModeChangeHandler( 1440 new VendorHalRadioModeChangeHandlerInternal()); 1441 mNetdWrapper = mWifiInjector.makeNetdWrapper(); 1442 return true; 1443 } 1444 } 1445 1446 /** 1447 * Callback to notify when the status of one of the native daemons 1448 * (wificond, wpa_supplicant & vendor HAL) changes. 1449 */ 1450 public interface StatusListener { 1451 /** 1452 * @param allReady Indicates if all the native daemons are ready for operation or not. 1453 */ onStatusChanged(boolean allReady)1454 void onStatusChanged(boolean allReady); 1455 } 1456 1457 /** 1458 * Register a StatusListener to get notified about any status changes from the native daemons. 1459 * 1460 * It is safe to re-register the same callback object - duplicates are detected and only a 1461 * single copy kept. 1462 * 1463 * @param listener StatusListener listener object. 1464 */ registerStatusListener(@onNull StatusListener listener)1465 public void registerStatusListener(@NonNull StatusListener listener) { 1466 synchronized (mLock) { 1467 mStatusListeners.add(listener); 1468 } 1469 } 1470 1471 /** 1472 * Callback to notify when the associated interface is destroyed, up or down. 1473 */ 1474 public interface InterfaceCallback { 1475 /** 1476 * Interface destroyed by HalDeviceManager. 1477 * 1478 * @param ifaceName Name of the iface. 1479 */ onDestroyed(String ifaceName)1480 void onDestroyed(String ifaceName); 1481 1482 /** 1483 * Interface is up. 1484 * 1485 * @param ifaceName Name of the iface. 1486 */ onUp(String ifaceName)1487 void onUp(String ifaceName); 1488 1489 /** 1490 * Interface is down. 1491 * 1492 * @param ifaceName Name of the iface. 1493 */ onDown(String ifaceName)1494 void onDown(String ifaceName); 1495 } 1496 takeBugReportInterfaceFailureIfNeeded(String bugTitle, String bugDetail)1497 private void takeBugReportInterfaceFailureIfNeeded(String bugTitle, String bugDetail) { 1498 if (mWifiInjector.getDeviceConfigFacade().isInterfaceFailureBugreportEnabled()) { 1499 mWifiInjector.getWifiDiagnostics().takeBugReport(bugTitle, bugDetail); 1500 } 1501 } 1502 1503 /** 1504 * Setup an interface for client mode (for scan) operations. 1505 * 1506 * This method configures an interface in STA mode in the native daemons 1507 * (wificond, vendor HAL). 1508 * 1509 * @param interfaceCallback Associated callback for notifying status changes for the iface. 1510 * @param requestorWs Requestor worksource. 1511 * @param concreteClientModeManager ConcreteClientModeManager requesting the interface. 1512 * @return Returns the name of the allocated interface, will be null on failure. 1513 */ setupInterfaceForClientInScanMode( @onNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs, @NonNull ConcreteClientModeManager concreteClientModeManager)1514 public String setupInterfaceForClientInScanMode( 1515 @NonNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs, 1516 @NonNull ConcreteClientModeManager concreteClientModeManager) { 1517 synchronized (mLock) { 1518 if (!startHal()) { 1519 Log.e(TAG, "Failed to start Hal"); 1520 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); 1521 return null; 1522 } 1523 Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_SCAN); 1524 if (iface == null) { 1525 Log.e(TAG, "Failed to allocate new STA iface"); 1526 return null; 1527 } 1528 iface.externalListener = interfaceCallback; 1529 iface.name = createStaIface(iface, requestorWs, concreteClientModeManager); 1530 if (TextUtils.isEmpty(iface.name)) { 1531 Log.e(TAG, "Failed to create iface in vendor HAL"); 1532 mIfaceMgr.removeIface(iface.id); 1533 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); 1534 return null; 1535 } 1536 if (!mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run, 1537 new NormalScanEventCallback(iface.name), 1538 new PnoScanEventCallback(iface.name))) { 1539 Log.e(TAG, "Failed to setup iface in wificond=" + iface.name); 1540 teardownInterface(iface.name); 1541 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond(); 1542 return null; 1543 } 1544 registerInterfaceObserver(); 1545 iface.networkObserver = new NetworkObserverInternal(iface.id); 1546 if (!registerNetworkObserver(iface.networkObserver)) { 1547 Log.e(TAG, "Failed to register network observer for iface=" + iface.name); 1548 teardownInterface(iface.name); 1549 return null; 1550 } 1551 mWifiMonitor.startMonitoring(iface.name); 1552 // Just to avoid any race conditions with interface state change callbacks, 1553 // update the interface state before we exit. 1554 onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); 1555 mWifiVendorHal.enableLinkLayerStats(iface.name); 1556 Log.i(TAG, "Successfully setup " + iface); 1557 1558 iface.featureSet = getSupportedFeatureSetInternal(iface.name); 1559 updateSupportedBandForStaInternal(iface); 1560 1561 mWifiVendorHal.enableStaChannelForPeerNetwork(mContext.getResources().getBoolean( 1562 R.bool.config_wifiEnableStaIndoorChannelForPeerNetwork), 1563 mContext.getResources().getBoolean( 1564 R.bool.config_wifiEnableStaDfsChannelForPeerNetwork)); 1565 return iface.name; 1566 } 1567 } 1568 1569 /** 1570 * Setup an interface for Soft AP mode operations. 1571 * 1572 * This method configures an interface in AP mode in all the native daemons 1573 * (wificond, wpa_supplicant & vendor HAL). 1574 * 1575 * @param interfaceCallback Associated callback for notifying status changes for the iface. 1576 * @param requestorWs Requestor worksource. 1577 * @param isBridged Whether or not AP interface is a bridge interface. 1578 * @param softApManager SoftApManager of the request. 1579 * @param vendorData List of {@link OuiKeyedData} containing vendor-provided 1580 * configuration data. Empty list indicates no vendor data. 1581 * @return Returns the name of the allocated interface, will be null on failure. 1582 */ setupInterfaceForSoftApMode( @onNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs, @SoftApConfiguration.BandType int band, boolean isBridged, @NonNull SoftApManager softApManager, @NonNull List<OuiKeyedData> vendorData)1583 public String setupInterfaceForSoftApMode( 1584 @NonNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs, 1585 @SoftApConfiguration.BandType int band, boolean isBridged, 1586 @NonNull SoftApManager softApManager, @NonNull List<OuiKeyedData> vendorData) { 1587 synchronized (mLock) { 1588 String bugTitle = "Wi-Fi BugReport (softAp interface failure)"; 1589 String errorMsg = ""; 1590 if (!startHal()) { 1591 errorMsg = "Failed to start softAp Hal"; 1592 Log.e(TAG, errorMsg); 1593 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); 1594 takeBugReportInterfaceFailureIfNeeded(bugTitle, errorMsg); 1595 softApManager.writeSoftApStartedEvent(SoftApManager.START_RESULT_FAILURE_START_HAL); 1596 return null; 1597 } 1598 if (!startHostapd()) { 1599 errorMsg = "Failed to start softAp hostapd"; 1600 Log.e(TAG, errorMsg); 1601 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd(); 1602 takeBugReportInterfaceFailureIfNeeded(bugTitle, errorMsg); 1603 softApManager.writeSoftApStartedEvent( 1604 SoftApManager.START_RESULT_FAILURE_START_HOSTAPD); 1605 return null; 1606 } 1607 Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_AP); 1608 if (iface == null) { 1609 Log.e(TAG, "Failed to allocate new AP iface"); 1610 return null; 1611 } 1612 iface.externalListener = interfaceCallback; 1613 iface.name = createApIface(iface, requestorWs, band, isBridged, softApManager, 1614 vendorData); 1615 if (TextUtils.isEmpty(iface.name)) { 1616 errorMsg = "Failed to create softAp iface in vendor HAL"; 1617 Log.e(TAG, errorMsg); 1618 mIfaceMgr.removeIface(iface.id); 1619 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); 1620 takeBugReportInterfaceFailureIfNeeded(bugTitle, errorMsg); 1621 return null; 1622 } 1623 String ifaceInstanceName = iface.name; 1624 if (isBridged) { 1625 List<String> instances = getBridgedApInstances(iface.name); 1626 if (instances == null || instances.size() == 0) { 1627 errorMsg = "Failed to get bridged AP instances" + iface.name; 1628 Log.e(TAG, errorMsg); 1629 teardownInterface(iface.name); 1630 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); 1631 takeBugReportInterfaceFailureIfNeeded(bugTitle, errorMsg); 1632 return null; 1633 } 1634 // Always select first instance as wificond interface. 1635 ifaceInstanceName = instances.get(0); 1636 mWifiCondIfacesForBridgedAp.put(iface.name, ifaceInstanceName); 1637 } 1638 if (!mWifiCondManager.setupInterfaceForSoftApMode(ifaceInstanceName)) { 1639 errorMsg = "Failed to setup softAp iface in wifiCond manager on " + iface; 1640 Log.e(TAG, errorMsg); 1641 teardownInterface(iface.name); 1642 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond(); 1643 takeBugReportInterfaceFailureIfNeeded(bugTitle, errorMsg); 1644 return null; 1645 } 1646 iface.networkObserver = new NetworkObserverInternal(iface.id); 1647 if (!registerNetworkObserver(iface.networkObserver)) { 1648 Log.e(TAG, "Failed to register network observer on " + iface); 1649 teardownInterface(iface.name); 1650 return null; 1651 } 1652 // Just to avoid any race conditions with interface state change callbacks, 1653 // update the interface state before we exit. 1654 onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); 1655 Log.i(TAG, "Successfully setup " + iface); 1656 1657 iface.featureSet = getSupportedFeatureSetInternal(iface.name); 1658 updateSupportedBandForStaInternal(iface); 1659 return iface.name; 1660 } 1661 } 1662 1663 /** 1664 * Switches an existing Client mode interface from connectivity 1665 * {@link Iface#IFACE_TYPE_STA_FOR_CONNECTIVITY} to scan mode 1666 * {@link Iface#IFACE_TYPE_STA_FOR_SCAN}. 1667 * 1668 * @param ifaceName Name of the interface. 1669 * @param requestorWs Requestor worksource. 1670 * @return true if the operation succeeded, false if there is an error or the iface is already 1671 * in scan mode. 1672 */ switchClientInterfaceToScanMode(@onNull String ifaceName, @NonNull WorkSource requestorWs)1673 public boolean switchClientInterfaceToScanMode(@NonNull String ifaceName, 1674 @NonNull WorkSource requestorWs) { 1675 synchronized (mLock) { 1676 final Iface iface = mIfaceMgr.getIface(ifaceName); 1677 if (iface == null) { 1678 Log.e(TAG, "Trying to switch to scan mode on an invalid iface=" + ifaceName); 1679 return false; 1680 } 1681 if (iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { 1682 Log.e(TAG, "Already in scan mode on iface=" + ifaceName); 1683 return true; 1684 } 1685 if (mWifiVendorHal.isVendorHalSupported() 1686 && !mWifiVendorHal.replaceStaIfaceRequestorWs(iface.name, requestorWs)) { 1687 Log.e(TAG, "Failed to replace requestor ws on " + iface); 1688 teardownInterface(iface.name); 1689 return false; 1690 } 1691 if (!mSupplicantStaIfaceHal.teardownIface(iface.name)) { 1692 Log.e(TAG, "Failed to teardown iface in supplicant on " + iface); 1693 teardownInterface(iface.name); 1694 return false; 1695 } 1696 iface.type = Iface.IFACE_TYPE_STA_FOR_SCAN; 1697 stopSupplicantIfNecessary(); 1698 iface.featureSet = getSupportedFeatureSetInternal(iface.name); 1699 updateSupportedBandForStaInternal(iface); 1700 iface.phyCapabilities = null; 1701 Log.i(TAG, "Successfully switched to scan mode on iface=" + iface); 1702 return true; 1703 } 1704 } 1705 1706 /** 1707 * Switches an existing Client mode interface from scan mode 1708 * {@link Iface#IFACE_TYPE_STA_FOR_SCAN} to connectivity mode 1709 * {@link Iface#IFACE_TYPE_STA_FOR_CONNECTIVITY}. 1710 * 1711 * @param ifaceName Name of the interface. 1712 * @param requestorWs Requestor worksource. 1713 * @return true if the operation succeeded, false if there is an error or the iface is already 1714 * in scan mode. 1715 */ switchClientInterfaceToConnectivityMode(@onNull String ifaceName, @NonNull WorkSource requestorWs)1716 public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName, 1717 @NonNull WorkSource requestorWs) { 1718 synchronized (mLock) { 1719 final Iface iface = mIfaceMgr.getIface(ifaceName); 1720 if (iface == null) { 1721 Log.e(TAG, "Trying to switch to connectivity mode on an invalid iface=" 1722 + ifaceName); 1723 return false; 1724 } 1725 if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY) { 1726 Log.e(TAG, "Already in connectivity mode on iface=" + ifaceName); 1727 return true; 1728 } 1729 if (mWifiVendorHal.isVendorHalSupported() 1730 && !mWifiVendorHal.replaceStaIfaceRequestorWs(iface.name, requestorWs)) { 1731 Log.e(TAG, "Failed to replace requestor ws on " + iface); 1732 teardownInterface(iface.name); 1733 return false; 1734 } 1735 if (!startSupplicant()) { 1736 Log.e(TAG, "Failed to start supplicant"); 1737 teardownInterface(iface.name); 1738 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); 1739 return false; 1740 } 1741 if (!mSupplicantStaIfaceHal.setupIface(iface.name)) { 1742 Log.e(TAG, "Failed to setup iface in supplicant on " + iface); 1743 teardownInterface(iface.name); 1744 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); 1745 return false; 1746 } 1747 if (mContext.getResources().getBoolean( 1748 R.bool.config_wifiNetworkCentricQosPolicyFeatureEnabled) 1749 && isSupplicantUsingAidlService()) { 1750 mQosPolicyFeatureEnabled = mSupplicantStaIfaceHal 1751 .setNetworkCentricQosPolicyFeatureEnabled(iface.name, true); 1752 if (!mQosPolicyFeatureEnabled) { 1753 Log.e(TAG, "Failed to enable QoS policy feature for iface " + iface.name); 1754 } 1755 } 1756 iface.type = Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY; 1757 iface.featureSet = getSupportedFeatureSetInternal(iface.name); 1758 saveCompleteFeatureSetInConfigStoreIfNecessary(iface.featureSet); 1759 updateSupportedBandForStaInternal(iface); 1760 mIsEnhancedOpenSupported = (iface.featureSet & WIFI_FEATURE_OWE) != 0; 1761 Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface); 1762 return true; 1763 } 1764 } 1765 1766 /** 1767 * Change the requestor WorkSource for a given STA iface. 1768 * @return true if the operation succeeded, false otherwise. 1769 */ replaceStaIfaceRequestorWs(@onNull String ifaceName, WorkSource newWorkSource)1770 public boolean replaceStaIfaceRequestorWs(@NonNull String ifaceName, WorkSource newWorkSource) { 1771 final Iface iface = mIfaceMgr.getIface(ifaceName); 1772 if (iface == null) { 1773 Log.e(TAG, "Called replaceStaIfaceRequestorWs() on an invalid iface=" + ifaceName); 1774 return false; 1775 } 1776 if (!mWifiVendorHal.isVendorHalSupported()) { 1777 // if vendor HAL isn't supported, return true since there's nothing to do. 1778 return true; 1779 } 1780 if (!mWifiVendorHal.replaceStaIfaceRequestorWs(iface.name, newWorkSource)) { 1781 Log.e(TAG, "Failed to replace requestor ws on " + iface); 1782 teardownInterface(iface.name); 1783 return false; 1784 } 1785 return true; 1786 } 1787 1788 /** 1789 * 1790 * Check if the interface is up or down. 1791 * 1792 * @param ifaceName Name of the interface. 1793 * @return true if iface is up, false if it's down or on error. 1794 */ isInterfaceUp(@onNull String ifaceName)1795 public boolean isInterfaceUp(@NonNull String ifaceName) { 1796 synchronized (mLock) { 1797 final Iface iface = mIfaceMgr.getIface(ifaceName); 1798 if (iface == null) { 1799 Log.e(TAG, "Trying to get iface state on invalid iface=" + ifaceName); 1800 return false; 1801 } 1802 try { 1803 return mNetdWrapper.isInterfaceUp(ifaceName); 1804 } catch (IllegalStateException e) { 1805 Log.e(TAG, "Unable to get interface config", e); 1806 return false; 1807 } 1808 } 1809 } 1810 1811 /** 1812 * Teardown an interface in Client/AP mode. 1813 * 1814 * This method tears down the associated interface from all the native daemons 1815 * (wificond, wpa_supplicant & vendor HAL). 1816 * Also, brings down the HAL, supplicant or hostapd as necessary. 1817 * 1818 * @param ifaceName Name of the interface. 1819 */ teardownInterface(@onNull String ifaceName)1820 public void teardownInterface(@NonNull String ifaceName) { 1821 synchronized (mLock) { 1822 final Iface iface = mIfaceMgr.getIface(ifaceName); 1823 if (iface == null) { 1824 Log.e(TAG, "Trying to teardown an invalid iface=" + ifaceName); 1825 return; 1826 } 1827 // Trigger the iface removal from HAL. The rest of the cleanup will be triggered 1828 // from the interface destroyed callback. 1829 if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY 1830 || iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { 1831 if (!removeStaIface(iface)) { 1832 Log.e(TAG, "Failed to remove iface in vendor HAL=" + ifaceName); 1833 return; 1834 } 1835 } else if (iface.type == Iface.IFACE_TYPE_AP) { 1836 if (!removeApIface(iface)) { 1837 Log.e(TAG, "Failed to remove iface in vendor HAL=" + ifaceName); 1838 return; 1839 } 1840 } 1841 Log.i(TAG, "Successfully initiated teardown for iface=" + ifaceName); 1842 } 1843 } 1844 1845 /** 1846 * Teardown all the active interfaces. 1847 * 1848 * This method tears down the associated interfaces from all the native daemons 1849 * (wificond, wpa_supplicant & vendor HAL). 1850 * Also, brings down the HAL, supplicant or hostapd as necessary. 1851 */ teardownAllInterfaces()1852 public void teardownAllInterfaces() { 1853 synchronized (mLock) { 1854 Iterator<Integer> ifaceIdIter = mIfaceMgr.getIfaceIdIter(); 1855 while (ifaceIdIter.hasNext()) { 1856 Iface iface = mIfaceMgr.getIface(ifaceIdIter.next()); 1857 ifaceIdIter.remove(); 1858 onInterfaceDestroyed(iface); 1859 Log.i(TAG, "Successfully torn down " + iface); 1860 } 1861 Log.i(TAG, "Successfully torn down all ifaces"); 1862 } 1863 } 1864 1865 /** 1866 * Get names of all the client interfaces. 1867 * 1868 * @return List of interface name of all active client interfaces. 1869 */ getClientInterfaceNames()1870 public Set<String> getClientInterfaceNames() { 1871 synchronized (mLock) { 1872 return mIfaceMgr.findAllStaIfaceNames(); 1873 } 1874 } 1875 1876 /** 1877 * Get names of all the client interfaces. 1878 * 1879 * @return List of interface name of all active client interfaces. 1880 */ getSoftApInterfaceNames()1881 public Set<String> getSoftApInterfaceNames() { 1882 synchronized (mLock) { 1883 return mIfaceMgr.findAllApIfaceNames(); 1884 } 1885 } 1886 1887 /******************************************************** 1888 * Wificond operations 1889 ********************************************************/ 1890 1891 /** 1892 * Query the list of valid frequencies for the provided band. 1893 * The result depends on the on the country code that has been set. 1894 * 1895 * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants. 1896 * The following bands are supported {@link WifiAnnotations.WifiBandBasic}: 1897 * WifiScanner.WIFI_BAND_24_GHZ 1898 * WifiScanner.WIFI_BAND_5_GHZ 1899 * WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY 1900 * WifiScanner.WIFI_BAND_6_GHZ 1901 * WifiScanner.WIFI_BAND_60_GHZ 1902 * @return frequencies vector of valid frequencies (MHz), or null for error. 1903 * @throws IllegalArgumentException if band is not recognized. 1904 */ getChannelsForBand(@ifiAnnotations.WifiBandBasic int band)1905 public int [] getChannelsForBand(@WifiAnnotations.WifiBandBasic int band) { 1906 if (!SdkLevel.isAtLeastS() && band == WifiScanner.WIFI_BAND_60_GHZ) { 1907 // 60 GHz band is new in Android S, return empty array on older SDK versions 1908 return new int[0]; 1909 } 1910 return mWifiCondManager.getChannelsMhzForBand(band); 1911 } 1912 1913 /** 1914 * Start a scan using wificond for the given parameters. 1915 * @param ifaceName Name of the interface. 1916 * @param scanType Type of scan to perform. One of {@link WifiScanner#SCAN_TYPE_LOW_LATENCY}, 1917 * {@link WifiScanner#SCAN_TYPE_LOW_POWER} or {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}. 1918 * @param freqs list of frequencies to scan for, if null scan all supported channels. 1919 * @param hiddenNetworkSSIDs List of hidden networks to be scanned for. 1920 * @param enable6GhzRnr whether Reduced Neighbor Report should be enabled for 6Ghz scanning. 1921 * @param vendorIes Byte array of vendor IEs 1922 * @return Returns true on success. 1923 */ scan( @onNull String ifaceName, @WifiAnnotations.ScanType int scanType, Set<Integer> freqs, List<String> hiddenNetworkSSIDs, boolean enable6GhzRnr, byte[] vendorIes)1924 public int scan( 1925 @NonNull String ifaceName, @WifiAnnotations.ScanType int scanType, Set<Integer> freqs, 1926 List<String> hiddenNetworkSSIDs, boolean enable6GhzRnr, byte[] vendorIes) { 1927 int scanRequestStatus = WifiScanner.REASON_SUCCEEDED; 1928 boolean scanStatus = true; 1929 List<byte[]> hiddenNetworkSsidsArrays = new ArrayList<>(); 1930 for (String hiddenNetworkSsid : hiddenNetworkSSIDs) { 1931 try { 1932 hiddenNetworkSsidsArrays.add( 1933 NativeUtil.byteArrayFromArrayList( 1934 NativeUtil.decodeSsid(hiddenNetworkSsid))); 1935 } catch (IllegalArgumentException e) { 1936 Log.e(TAG, "Illegal argument " + hiddenNetworkSsid, e); 1937 continue; 1938 } 1939 } 1940 if (SdkLevel.isAtLeastS()) { 1941 // enable6GhzRnr is a new parameter first introduced in Android S. 1942 Bundle extraScanningParams = new Bundle(); 1943 extraScanningParams.putBoolean(WifiNl80211Manager.SCANNING_PARAM_ENABLE_6GHZ_RNR, 1944 enable6GhzRnr); 1945 if (SdkLevel.isAtLeastU()) { 1946 extraScanningParams.putByteArray(WifiNl80211Manager.EXTRA_SCANNING_PARAM_VENDOR_IES, 1947 vendorIes); 1948 scanRequestStatus = mWifiCondManager.startScan2(ifaceName, scanType, freqs, 1949 hiddenNetworkSsidsArrays, extraScanningParams); 1950 } else { 1951 scanStatus = mWifiCondManager.startScan(ifaceName, scanType, freqs, 1952 hiddenNetworkSsidsArrays, 1953 extraScanningParams); 1954 scanRequestStatus = scanStatus 1955 ? WifiScanner.REASON_SUCCEEDED : WifiScanner.REASON_UNSPECIFIED; 1956 1957 } 1958 } else { 1959 scanStatus = mWifiCondManager.startScan(ifaceName, scanType, freqs, 1960 hiddenNetworkSsidsArrays); 1961 scanRequestStatus = scanStatus 1962 ? WifiScanner.REASON_SUCCEEDED : WifiScanner.REASON_UNSPECIFIED; 1963 } 1964 1965 return scanRequestStatus; 1966 } 1967 1968 /** 1969 * Fetch the latest scan result from kernel via wificond. 1970 * @param ifaceName Name of the interface. 1971 * @return Returns an ArrayList of ScanDetail. 1972 * Returns an empty ArrayList on failure. 1973 */ getScanResults(@onNull String ifaceName)1974 public ArrayList<ScanDetail> getScanResults(@NonNull String ifaceName) { 1975 if (mUseFakeScanDetails) { 1976 synchronized (mFakeScanDetails) { 1977 ArrayList<ScanDetail> copyList = new ArrayList<>(); 1978 for (ScanDetail sd: mFakeScanDetails) { 1979 ScanDetail copy = new ScanDetail(sd); 1980 copy.getScanResult().ifaceName = ifaceName; 1981 // otherwise the fake will be too old 1982 copy.getScanResult().timestamp = SystemClock.elapsedRealtime() * 1000; 1983 copyList.add(copy); 1984 } 1985 return copyList; 1986 } 1987 } 1988 if (mMockWifiModem != null 1989 && mMockWifiModem.isMethodConfigured( 1990 MockWifiServiceUtil.MOCK_NL80211_SERVICE, "getScanResults")) { 1991 Log.i(TAG, "getScanResults was called from mock wificond"); 1992 return convertNativeScanResults(ifaceName, mMockWifiModem.getWifiNl80211Manager() 1993 .getScanResults(ifaceName, WifiNl80211Manager.SCAN_TYPE_SINGLE_SCAN)); 1994 } 1995 return convertNativeScanResults(ifaceName, mWifiCondManager.getScanResults( 1996 ifaceName, WifiNl80211Manager.SCAN_TYPE_SINGLE_SCAN)); 1997 } 1998 1999 /** 2000 * Start faking scan results - using information provided via 2001 * {@link #addFakeScanDetail(ScanDetail)}. Stop with {@link #stopFakingScanDetails()}. 2002 */ startFakingScanDetails()2003 public void startFakingScanDetails() { 2004 if (mBuildProperties.isUserBuild()) { 2005 Log.wtf(TAG, "Can't fake scan results in a user build!"); 2006 return; 2007 } 2008 Log.d(TAG, "Starting faking scan results - " + mFakeScanDetails); 2009 mUseFakeScanDetails = true; 2010 } 2011 2012 /** 2013 * Add fake scan result. Fakes are not used until activated via 2014 * {@link #startFakingScanDetails()}. 2015 * @param fakeScanDetail 2016 */ addFakeScanDetail(@onNull ScanDetail fakeScanDetail)2017 public void addFakeScanDetail(@NonNull ScanDetail fakeScanDetail) { 2018 synchronized (mFakeScanDetails) { 2019 mFakeScanDetails.add(fakeScanDetail); 2020 } 2021 } 2022 2023 /** 2024 * Reset the fake scan result list updated via {@link #addFakeScanDetail(ScanDetail)} .} 2025 */ resetFakeScanDetails()2026 public void resetFakeScanDetails() { 2027 synchronized (mFakeScanDetails) { 2028 mFakeScanDetails.clear(); 2029 } 2030 } 2031 2032 /** 2033 * Stop faking scan results. Started with {@link #startFakingScanDetails()}. 2034 */ stopFakingScanDetails()2035 public void stopFakingScanDetails() { 2036 mUseFakeScanDetails = false; 2037 } 2038 2039 /** 2040 * Fetch the latest scan result from kernel via wificond. 2041 * @param ifaceName Name of the interface. 2042 * @return Returns an ArrayList of ScanDetail. 2043 * Returns an empty ArrayList on failure. 2044 */ getPnoScanResults(@onNull String ifaceName)2045 public ArrayList<ScanDetail> getPnoScanResults(@NonNull String ifaceName) { 2046 if (mMockWifiModem != null 2047 && mMockWifiModem.isMethodConfigured( 2048 MockWifiServiceUtil.MOCK_NL80211_SERVICE, "getPnoScanResults")) { 2049 Log.i(TAG, "getPnoScanResults was called from mock wificond"); 2050 return convertNativeScanResults(ifaceName, mMockWifiModem.getWifiNl80211Manager() 2051 .getScanResults(ifaceName, WifiNl80211Manager.SCAN_TYPE_PNO_SCAN)); 2052 } 2053 return convertNativeScanResults(ifaceName, mWifiCondManager.getScanResults(ifaceName, 2054 WifiNl80211Manager.SCAN_TYPE_PNO_SCAN)); 2055 } 2056 2057 /** 2058 * Get the max number of SSIDs that the driver supports per scan. 2059 * @param ifaceName Name of the interface. 2060 */ getMaxSsidsPerScan(@onNull String ifaceName)2061 public int getMaxSsidsPerScan(@NonNull String ifaceName) { 2062 if (SdkLevel.isAtLeastT()) { 2063 return mWifiCondManager.getMaxSsidsPerScan(ifaceName); 2064 } else { 2065 return -1; 2066 } 2067 } 2068 convertNativeScanResults(@onNull String ifaceName, List<NativeScanResult> nativeResults)2069 private ArrayList<ScanDetail> convertNativeScanResults(@NonNull String ifaceName, 2070 List<NativeScanResult> nativeResults) { 2071 ArrayList<ScanDetail> results = new ArrayList<>(); 2072 for (NativeScanResult result : nativeResults) { 2073 if (result.getSsid().length > 32) { 2074 Log.e(TAG, "Invalid SSID length (> 32 bytes): " 2075 + Arrays.toString(result.getSsid())); 2076 continue; 2077 } 2078 WifiSsid originalSsid = WifiSsid.fromBytes(result.getSsid()); 2079 MacAddress bssidMac = result.getBssid(); 2080 if (bssidMac == null) { 2081 Log.e(TAG, "Invalid MAC (BSSID) for SSID " + originalSsid); 2082 continue; 2083 } 2084 String bssid = bssidMac.toString(); 2085 ScanResult.InformationElement[] ies = 2086 InformationElementUtil.parseInformationElements(result.getInformationElements()); 2087 InformationElementUtil.Capabilities capabilities = 2088 new InformationElementUtil.Capabilities(); 2089 capabilities.from( 2090 ies, 2091 result.getCapabilities(), 2092 mIsEnhancedOpenSupported, 2093 result.getFrequencyMhz(), 2094 mUnknownAkmMap); 2095 String flags = capabilities.generateCapabilitiesString(); 2096 NetworkDetail networkDetail; 2097 try { 2098 networkDetail = new NetworkDetail(bssid, ies, null, result.getFrequencyMhz()); 2099 } catch (IllegalArgumentException e) { 2100 Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e); 2101 continue; 2102 } 2103 2104 WifiSsid translatedSsid = mWifiInjector.getSsidTranslator() 2105 .getTranslatedSsidAndRecordBssidCharset(originalSsid, bssidMac); 2106 ScanDetail scanDetail = new ScanDetail(networkDetail, translatedSsid, bssid, flags, 2107 result.getSignalMbm() / 100, result.getFrequencyMhz(), result.getTsf(), ies, 2108 null, result.getInformationElements()); 2109 ScanResult scanResult = scanDetail.getScanResult(); 2110 scanResult.setWifiStandard(wifiModeToWifiStandard(networkDetail.getWifiMode())); 2111 scanResult.ifaceName = ifaceName; 2112 2113 // Fill up the radio chain info. 2114 scanResult.radioChainInfos = 2115 new ScanResult.RadioChainInfo[result.getRadioChainInfos().size()]; 2116 int idx = 0; 2117 for (RadioChainInfo nativeRadioChainInfo : result.getRadioChainInfos()) { 2118 scanResult.radioChainInfos[idx] = new ScanResult.RadioChainInfo(); 2119 scanResult.radioChainInfos[idx].id = nativeRadioChainInfo.getChainId(); 2120 scanResult.radioChainInfos[idx].level = nativeRadioChainInfo.getLevelDbm(); 2121 idx++; 2122 } 2123 2124 // Fill MLO Attributes 2125 scanResult.setApMldMacAddress(networkDetail.getMldMacAddress()); 2126 scanResult.setApMloLinkId(networkDetail.getMloLinkId()); 2127 scanResult.setAffiliatedMloLinks(networkDetail.getAffiliatedMloLinks()); 2128 2129 results.add(scanDetail); 2130 } 2131 if (mVerboseLoggingEnabled) { 2132 Log.d(TAG, "get " + results.size() + " scan results from wificond"); 2133 } 2134 2135 return results; 2136 } 2137 2138 @WifiAnnotations.WifiStandard wifiModeToWifiStandard(int wifiMode)2139 private static int wifiModeToWifiStandard(int wifiMode) { 2140 switch (wifiMode) { 2141 case InformationElementUtil.WifiMode.MODE_11A: 2142 case InformationElementUtil.WifiMode.MODE_11B: 2143 case InformationElementUtil.WifiMode.MODE_11G: 2144 return ScanResult.WIFI_STANDARD_LEGACY; 2145 case InformationElementUtil.WifiMode.MODE_11N: 2146 return ScanResult.WIFI_STANDARD_11N; 2147 case InformationElementUtil.WifiMode.MODE_11AC: 2148 return ScanResult.WIFI_STANDARD_11AC; 2149 case InformationElementUtil.WifiMode.MODE_11AX: 2150 return ScanResult.WIFI_STANDARD_11AX; 2151 case InformationElementUtil.WifiMode.MODE_11BE: 2152 return ScanResult.WIFI_STANDARD_11BE; 2153 case InformationElementUtil.WifiMode.MODE_UNDEFINED: 2154 default: 2155 return ScanResult.WIFI_STANDARD_UNKNOWN; 2156 } 2157 } 2158 2159 /** 2160 * Start PNO scan. 2161 * @param ifaceName Name of the interface. 2162 * @param pnoSettings Pno scan configuration. 2163 * @return true on success. 2164 */ startPnoScan(@onNull String ifaceName, PnoSettings pnoSettings)2165 public boolean startPnoScan(@NonNull String ifaceName, PnoSettings pnoSettings) { 2166 if (mMockWifiModem != null 2167 && mMockWifiModem.isMethodConfigured( 2168 MockWifiServiceUtil.MOCK_NL80211_SERVICE, "startPnoScan")) { 2169 Log.i(TAG, "startPnoScan was called from mock wificond"); 2170 return mMockWifiModem.getWifiNl80211Manager() 2171 .startPnoScan(ifaceName, pnoSettings.toNativePnoSettings(), 2172 Runnable::run, 2173 new WifiNl80211Manager.PnoScanRequestCallback() { 2174 @Override 2175 public void onPnoRequestSucceeded() { 2176 } 2177 2178 @Override 2179 public void onPnoRequestFailed() { 2180 } 2181 }); 2182 } 2183 return mWifiCondManager.startPnoScan(ifaceName, pnoSettings.toNativePnoSettings(), 2184 Runnable::run, 2185 new WifiNl80211Manager.PnoScanRequestCallback() { 2186 @Override 2187 public void onPnoRequestSucceeded() { 2188 mWifiMetrics.incrementPnoScanStartAttemptCount(); 2189 } 2190 2191 @Override 2192 public void onPnoRequestFailed() { 2193 WifiStatsLog.write(WifiStatsLog.PNO_SCAN_STOPPED, 2194 WifiStatsLog.PNO_SCAN_STOPPED__STOP_REASON__SCAN_FAILED, 2195 0, false, false, false, false, // default values 2196 WifiStatsLog 2197 .PNO_SCAN_STOPPED__FAILURE_CODE__WIFICOND_REQUEST_FAILURE); 2198 } 2199 }); 2200 } 2201 2202 /** 2203 * Stop PNO scan. 2204 * @param ifaceName Name of the interface. 2205 * @return true on success. 2206 */ 2207 public boolean stopPnoScan(@NonNull String ifaceName) { 2208 return mWifiCondManager.stopPnoScan(ifaceName); 2209 } 2210 2211 /** 2212 * Sends an arbitrary 802.11 management frame on the current channel. 2213 * 2214 * @param ifaceName Name of the interface. 2215 * @param frame Bytes of the 802.11 management frame to be sent, including the header, but not 2216 * including the frame check sequence (FCS). 2217 * @param callback A callback triggered when the transmitted frame is ACKed or the transmission 2218 * fails. 2219 * @param mcs The MCS index that the frame will be sent at. If mcs < 0, the driver will select 2220 * the rate automatically. If the device does not support sending the frame at a 2221 * specified MCS rate, the transmission will be aborted and 2222 * {@link WifiNl80211Manager.SendMgmtFrameCallback#onFailure(int)} will be called 2223 * with reason {@link WifiNl80211Manager#SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED}. 2224 */ 2225 public void sendMgmtFrame(@NonNull String ifaceName, @NonNull byte[] frame, 2226 @NonNull WifiNl80211Manager.SendMgmtFrameCallback callback, int mcs) { 2227 mWifiCondManager.sendMgmtFrame(ifaceName, frame, mcs, Runnable::run, callback); 2228 } 2229 2230 /** 2231 * Sends a probe request to the AP and waits for a response in order to determine whether 2232 * there is connectivity between the device and AP. 2233 * 2234 * @param ifaceName Name of the interface. 2235 * @param receiverMac the MAC address of the AP that the probe request will be sent to. 2236 * @param callback callback triggered when the probe was ACKed by the AP, or when 2237 * an error occurs after the link probe was started. 2238 * @param mcs The MCS index that this probe will be sent at. If mcs < 0, the driver will select 2239 * the rate automatically. If the device does not support sending the frame at a 2240 * specified MCS rate, the transmission will be aborted and 2241 * {@link WifiNl80211Manager.SendMgmtFrameCallback#onFailure(int)} will be called 2242 * with reason {@link WifiNl80211Manager#SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED}. 2243 */ 2244 public void probeLink(@NonNull String ifaceName, @NonNull MacAddress receiverMac, 2245 @NonNull WifiNl80211Manager.SendMgmtFrameCallback callback, int mcs) { 2246 if (callback == null) { 2247 Log.e(TAG, "callback cannot be null!"); 2248 return; 2249 } 2250 2251 if (receiverMac == null) { 2252 Log.e(TAG, "Receiver MAC address cannot be null!"); 2253 callback.onFailure(WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN); 2254 return; 2255 } 2256 2257 String senderMacStr = getMacAddress(ifaceName); 2258 if (senderMacStr == null) { 2259 Log.e(TAG, "Failed to get this device's MAC Address"); 2260 callback.onFailure(WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN); 2261 return; 2262 } 2263 2264 byte[] frame = buildProbeRequestFrame( 2265 receiverMac.toByteArray(), 2266 NativeUtil.macAddressToByteArray(senderMacStr)); 2267 sendMgmtFrame(ifaceName, frame, callback, mcs); 2268 } 2269 2270 // header = 24 bytes, minimal body = 2 bytes, no FCS (will be added by driver) 2271 private static final int BASIC_PROBE_REQUEST_FRAME_SIZE = 24 + 2; 2272 2273 private byte[] buildProbeRequestFrame(byte[] receiverMac, byte[] transmitterMac) { 2274 ByteBuffer frame = ByteBuffer.allocate(BASIC_PROBE_REQUEST_FRAME_SIZE); 2275 // ByteBuffer is big endian by default, switch to little endian 2276 frame.order(ByteOrder.LITTLE_ENDIAN); 2277 2278 // Protocol version = 0, Type = management, Subtype = Probe Request 2279 frame.put((byte) 0x40); 2280 2281 // no flags set 2282 frame.put((byte) 0x00); 2283 2284 // duration = 60 microseconds. Note: this is little endian 2285 // Note: driver should calculate the duration and replace it before sending, putting a 2286 // reasonable default value here just in case. 2287 frame.putShort((short) 0x3c); 2288 2289 // receiver/destination MAC address byte array 2290 frame.put(receiverMac); 2291 // sender MAC address byte array 2292 frame.put(transmitterMac); 2293 // BSSID (same as receiver address since we are sending to the AP) 2294 frame.put(receiverMac); 2295 2296 // Generate random sequence number, fragment number = 0 2297 // Note: driver should replace the sequence number with the correct number that is 2298 // incremented from the last used sequence number. Putting a random sequence number as a 2299 // default here just in case. 2300 // bit 0 is least significant bit, bit 15 is most significant bit 2301 // bits [0, 7] go in byte 0 2302 // bits [8, 15] go in byte 1 2303 // bits [0, 3] represent the fragment number (which is 0) 2304 // bits [4, 15] represent the sequence number (which is random) 2305 // clear bits [0, 3] to set fragment number = 0 2306 short sequenceAndFragmentNumber = (short) (mRandom.nextInt() & 0xfff0); 2307 frame.putShort(sequenceAndFragmentNumber); 2308 2309 // NL80211 rejects frames with an empty body, so we just need to put a placeholder 2310 // information element. 2311 // Tag for SSID 2312 frame.put((byte) 0x00); 2313 // Represents broadcast SSID. Not accurate, but works as placeholder. 2314 frame.put((byte) 0x00); 2315 2316 return frame.array(); 2317 } 2318 2319 private static final int CONNECT_TO_HOSTAPD_RETRY_INTERVAL_MS = 100; 2320 private static final int CONNECT_TO_HOSTAPD_RETRY_TIMES = 50; 2321 /** 2322 * This method is called to wait for establishing connection to hostapd. 2323 * 2324 * @return true if connection is established, false otherwise. 2325 */ 2326 private boolean startAndWaitForHostapdConnection() { 2327 // Start initialization if not already started. 2328 if (!mHostapdHal.isInitializationStarted() 2329 && !mHostapdHal.initialize()) { 2330 return false; 2331 } 2332 if (!mHostapdHal.startDaemon()) { 2333 Log.e(TAG, "Failed to startup hostapd"); 2334 return false; 2335 } 2336 boolean connected = false; 2337 int connectTries = 0; 2338 while (!connected && connectTries++ < CONNECT_TO_HOSTAPD_RETRY_TIMES) { 2339 // Check if the initialization is complete. 2340 connected = mHostapdHal.isInitializationComplete(); 2341 if (connected) { 2342 break; 2343 } 2344 try { 2345 Thread.sleep(CONNECT_TO_HOSTAPD_RETRY_INTERVAL_MS); 2346 } catch (InterruptedException ignore) { 2347 } 2348 } 2349 return connected; 2350 } 2351 2352 /** 2353 * Start Soft AP operation using the provided configuration. 2354 * 2355 * @param ifaceName Name of the interface. 2356 * @param config Configuration to use for the soft ap created. 2357 * @param isMetered Indicates the network is metered or not. 2358 * @param callback Callback for AP events. 2359 * @return one of {@link SoftApManager.StartResult} 2360 */ 2361 public @SoftApManager.StartResult int startSoftAp( 2362 @NonNull String ifaceName, SoftApConfiguration config, boolean isMetered, 2363 SoftApHalCallback callback) { 2364 if (mHostapdHal.isApInfoCallbackSupported()) { 2365 if (!mHostapdHal.registerApCallback(ifaceName, callback)) { 2366 Log.e(TAG, "Failed to register ap hal event callback"); 2367 return SoftApManager.START_RESULT_FAILURE_REGISTER_AP_CALLBACK_HOSTAPD; 2368 } 2369 } else { 2370 SoftApHalCallbackFromWificond softApHalCallbackFromWificond = 2371 new SoftApHalCallbackFromWificond(ifaceName, callback); 2372 if (!mWifiCondManager.registerApCallback(ifaceName, 2373 Runnable::run, softApHalCallbackFromWificond)) { 2374 Log.e(TAG, "Failed to register ap hal event callback from wificond"); 2375 return SoftApManager.START_RESULT_FAILURE_REGISTER_AP_CALLBACK_WIFICOND; 2376 } 2377 } 2378 2379 if (!mHostapdHal.addAccessPoint(ifaceName, config, isMetered, callback::onFailure)) { 2380 String errorMsg = "Failed to add softAp"; 2381 Log.e(TAG, errorMsg); 2382 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd(); 2383 takeBugReportInterfaceFailureIfNeeded("Wi-Fi BugReport (softap interface failure)", 2384 errorMsg); 2385 return SoftApManager.START_RESULT_FAILURE_ADD_AP_HOSTAPD; 2386 } 2387 2388 return SoftApManager.START_RESULT_SUCCESS; 2389 } 2390 2391 /** 2392 * Force a softap client disconnect with specific reason code. 2393 * 2394 * @param ifaceName Name of the interface. 2395 * @param client Mac address to force disconnect in clients of the SoftAp. 2396 * @param reasonCode One of disconnect reason code which defined in {@link ApConfigUtil}. 2397 * @return true on success, false otherwise. 2398 */ 2399 public boolean forceClientDisconnect(@NonNull String ifaceName, 2400 @NonNull MacAddress client, int reasonCode) { 2401 return mHostapdHal.forceClientDisconnect(ifaceName, client, reasonCode); 2402 } 2403 2404 /** 2405 * Set MAC address of the given interface 2406 * @param interfaceName Name of the interface 2407 * @param mac Mac address to change into 2408 * @return true on success 2409 */ 2410 public boolean setStaMacAddress(String interfaceName, MacAddress mac) { 2411 // TODO(b/72459123): Suppress interface down/up events from this call 2412 // Trigger an explicit disconnect to avoid losing the disconnect event reason (if currently 2413 // connected) from supplicant if the interface is brought down for MAC address change. 2414 disconnect(interfaceName); 2415 return mWifiVendorHal.setStaMacAddress(interfaceName, mac); 2416 } 2417 2418 /** 2419 * Set MAC address of the given interface 2420 * @param interfaceName Name of the interface 2421 * @param mac Mac address to change into 2422 * @return true on success 2423 */ 2424 public boolean setApMacAddress(String interfaceName, MacAddress mac) { 2425 return mWifiVendorHal.setApMacAddress(interfaceName, mac); 2426 } 2427 2428 /** 2429 * Returns true if Hal version supports setMacAddress, otherwise false. 2430 * 2431 * @param interfaceName Name of the interface 2432 */ 2433 public boolean isApSetMacAddressSupported(@NonNull String interfaceName) { 2434 return mWifiVendorHal.isApSetMacAddressSupported(interfaceName); 2435 } 2436 2437 /** 2438 * Get the factory MAC address of the given interface 2439 * @param interfaceName Name of the interface. 2440 * @return factory MAC address, or null on a failed call or if feature is unavailable. 2441 */ 2442 public MacAddress getStaFactoryMacAddress(@NonNull String interfaceName) { 2443 return mWifiVendorHal.getStaFactoryMacAddress(interfaceName); 2444 } 2445 2446 /** 2447 * Get the factory MAC address of the given interface 2448 * @param interfaceName Name of the interface. 2449 * @return factory MAC address, or null on a failed call or if feature is unavailable. 2450 */ 2451 public MacAddress getApFactoryMacAddress(@NonNull String interfaceName) { 2452 return mWifiVendorHal.getApFactoryMacAddress(interfaceName); 2453 } 2454 2455 /** 2456 * Reset MAC address to factory MAC address on the given interface 2457 * 2458 * @param interfaceName Name of the interface 2459 * @return true for success 2460 */ 2461 public boolean resetApMacToFactoryMacAddress(@NonNull String interfaceName) { 2462 return mWifiVendorHal.resetApMacToFactoryMacAddress(interfaceName); 2463 } 2464 2465 /** 2466 * Set the unsafe channels and restrictions to avoid for coex. 2467 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid 2468 * @param restrictions Bitmask of WifiManager.COEX_RESTRICTION_ flags 2469 */ 2470 public void setCoexUnsafeChannels( 2471 @NonNull List<CoexUnsafeChannel> unsafeChannels, int restrictions) { 2472 mCachedCoexUnsafeChannels.clear(); 2473 mCachedCoexUnsafeChannels.addAll(unsafeChannels); 2474 mCachedCoexRestrictions = restrictions; 2475 mWifiVendorHal.setCoexUnsafeChannels(mCachedCoexUnsafeChannels, mCachedCoexRestrictions); 2476 } 2477 2478 /******************************************************** 2479 * Hostapd operations 2480 ********************************************************/ 2481 2482 /** 2483 * Callback to notify hostapd death. 2484 */ 2485 public interface HostapdDeathEventHandler { 2486 /** 2487 * Invoked when the supplicant dies. 2488 */ 2489 void onDeath(); 2490 } 2491 2492 /******************************************************** 2493 * Supplicant operations 2494 ********************************************************/ 2495 2496 /** 2497 * Callback to notify supplicant death. 2498 */ 2499 public interface SupplicantDeathEventHandler { 2500 /** 2501 * Invoked when the supplicant dies. 2502 */ 2503 void onDeath(); 2504 } 2505 2506 /** 2507 * Set supplicant log level 2508 * 2509 * @param turnOnVerbose Whether to turn on verbose logging or not. 2510 */ 2511 public void setSupplicantLogLevel(boolean turnOnVerbose) { 2512 mSupplicantStaIfaceHal.setLogLevel(turnOnVerbose); 2513 } 2514 2515 /** 2516 * Trigger a reconnection if the iface is disconnected. 2517 * 2518 * @param ifaceName Name of the interface. 2519 * @return true if request is sent successfully, false otherwise. 2520 */ 2521 public boolean reconnect(@NonNull String ifaceName) { 2522 return mSupplicantStaIfaceHal.reconnect(ifaceName); 2523 } 2524 2525 /** 2526 * Trigger a reassociation even if the iface is currently connected. 2527 * 2528 * @param ifaceName Name of the interface. 2529 * @return true if request is sent successfully, false otherwise. 2530 */ 2531 public boolean reassociate(@NonNull String ifaceName) { 2532 return mSupplicantStaIfaceHal.reassociate(ifaceName); 2533 } 2534 2535 /** 2536 * Trigger a disconnection from the currently connected network. 2537 * 2538 * @param ifaceName Name of the interface. 2539 * @return true if request is sent successfully, false otherwise. 2540 */ 2541 public boolean disconnect(@NonNull String ifaceName) { 2542 return mSupplicantStaIfaceHal.disconnect(ifaceName); 2543 } 2544 2545 /** 2546 * Makes a callback to HIDL to getMacAddress from supplicant 2547 * 2548 * @param ifaceName Name of the interface. 2549 * @return string containing the MAC address, or null on a failed call 2550 */ 2551 public String getMacAddress(@NonNull String ifaceName) { 2552 return mSupplicantStaIfaceHal.getMacAddress(ifaceName); 2553 } 2554 2555 public static final int RX_FILTER_TYPE_V4_MULTICAST = 0; 2556 public static final int RX_FILTER_TYPE_V6_MULTICAST = 1; 2557 /** 2558 * Start filtering out Multicast V4 packets 2559 * @param ifaceName Name of the interface. 2560 * @return {@code true} if the operation succeeded, {@code false} otherwise 2561 * 2562 * Multicast filtering rules work as follows: 2563 * 2564 * The driver can filter multicast (v4 and/or v6) and broadcast packets when in 2565 * a power optimized mode (typically when screen goes off). 2566 * 2567 * In order to prevent the driver from filtering the multicast/broadcast packets, we have to 2568 * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective 2569 * 2570 * DRIVER RXFILTER-ADD Num 2571 * where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6 2572 * 2573 * and DRIVER RXFILTER-START 2574 * In order to stop the usage of these rules, we do 2575 * 2576 * DRIVER RXFILTER-STOP 2577 * DRIVER RXFILTER-REMOVE Num 2578 * where Num is as described for RXFILTER-ADD 2579 * 2580 * The SETSUSPENDOPT driver command overrides the filtering rules 2581 */ 2582 public boolean startFilteringMulticastV4Packets(@NonNull String ifaceName) { 2583 return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) 2584 && mSupplicantStaIfaceHal.removeRxFilter( 2585 ifaceName, RX_FILTER_TYPE_V4_MULTICAST) 2586 && mSupplicantStaIfaceHal.startRxFilter(ifaceName); 2587 } 2588 2589 /** 2590 * Stop filtering out Multicast V4 packets. 2591 * @param ifaceName Name of the interface. 2592 * @return {@code true} if the operation succeeded, {@code false} otherwise 2593 */ 2594 public boolean stopFilteringMulticastV4Packets(@NonNull String ifaceName) { 2595 return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) 2596 && mSupplicantStaIfaceHal.addRxFilter( 2597 ifaceName, RX_FILTER_TYPE_V4_MULTICAST) 2598 && mSupplicantStaIfaceHal.startRxFilter(ifaceName); 2599 } 2600 2601 /** 2602 * Start filtering out Multicast V6 packets 2603 * @param ifaceName Name of the interface. 2604 * @return {@code true} if the operation succeeded, {@code false} otherwise 2605 */ 2606 public boolean startFilteringMulticastV6Packets(@NonNull String ifaceName) { 2607 return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) 2608 && mSupplicantStaIfaceHal.removeRxFilter( 2609 ifaceName, RX_FILTER_TYPE_V6_MULTICAST) 2610 && mSupplicantStaIfaceHal.startRxFilter(ifaceName); 2611 } 2612 2613 /** 2614 * Stop filtering out Multicast V6 packets. 2615 * @param ifaceName Name of the interface. 2616 * @return {@code true} if the operation succeeded, {@code false} otherwise 2617 */ 2618 public boolean stopFilteringMulticastV6Packets(@NonNull String ifaceName) { 2619 return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) 2620 && mSupplicantStaIfaceHal.addRxFilter( 2621 ifaceName, RX_FILTER_TYPE_V6_MULTICAST) 2622 && mSupplicantStaIfaceHal.startRxFilter(ifaceName); 2623 } 2624 2625 public static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0; 2626 public static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1; 2627 public static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2; 2628 /** 2629 * Sets the bluetooth coexistence mode. 2630 * 2631 * @param ifaceName Name of the interface. 2632 * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED}, 2633 * {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or 2634 * {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}. 2635 * @return Whether the mode was successfully set. 2636 */ 2637 public boolean setBluetoothCoexistenceMode(@NonNull String ifaceName, int mode) { 2638 return mSupplicantStaIfaceHal.setBtCoexistenceMode(ifaceName, mode); 2639 } 2640 2641 /** 2642 * Enable or disable Bluetooth coexistence scan mode. When this mode is on, 2643 * some of the low-level scan parameters used by the driver are changed to 2644 * reduce interference with A2DP streaming. 2645 * 2646 * @param ifaceName Name of the interface. 2647 * @param setCoexScanMode whether to enable or disable this mode 2648 * @return {@code true} if the command succeeded, {@code false} otherwise. 2649 */ 2650 public boolean setBluetoothCoexistenceScanMode( 2651 @NonNull String ifaceName, boolean setCoexScanMode) { 2652 return mSupplicantStaIfaceHal.setBtCoexistenceScanModeEnabled( 2653 ifaceName, setCoexScanMode); 2654 } 2655 2656 /** 2657 * Enable or disable suspend mode optimizations. 2658 * 2659 * @param ifaceName Name of the interface. 2660 * @param enabled true to enable, false otherwise. 2661 * @return true if request is sent successfully, false otherwise. 2662 */ 2663 public boolean setSuspendOptimizations(@NonNull String ifaceName, boolean enabled) { 2664 return mSupplicantStaIfaceHal.setSuspendModeEnabled(ifaceName, enabled); 2665 } 2666 2667 /** 2668 * Set country code for STA interface 2669 * 2670 * @param ifaceName Name of the STA interface. 2671 * @param countryCode 2 byte ASCII string. For ex: US, CA. 2672 * @return true if request is sent successfully, false otherwise. 2673 */ 2674 public boolean setStaCountryCode(@NonNull String ifaceName, String countryCode) { 2675 if (mSupplicantStaIfaceHal.setCountryCode(ifaceName, countryCode)) { 2676 if (mCountryCodeChangeListener != null) { 2677 mCountryCodeChangeListener.onSetCountryCodeSucceeded(countryCode); 2678 } 2679 return true; 2680 } 2681 return false; 2682 } 2683 2684 /** 2685 * Flush all previously configured HLPs. 2686 * 2687 * @return true if request is sent successfully, false otherwise. 2688 */ 2689 public boolean flushAllHlp(@NonNull String ifaceName) { 2690 return mSupplicantStaIfaceHal.flushAllHlp(ifaceName); 2691 } 2692 2693 /** 2694 * Set FILS HLP packet. 2695 * 2696 * @param dst Destination MAC address. 2697 * @param hlpPacket Hlp Packet data in hex. 2698 * @return true if request is sent successfully, false otherwise. 2699 */ 2700 public boolean addHlpReq(@NonNull String ifaceName, MacAddress dst, byte [] hlpPacket) { 2701 return mSupplicantStaIfaceHal.addHlpReq(ifaceName, dst.toByteArray(), hlpPacket); 2702 } 2703 2704 /** 2705 * Initiate TDLS discover and setup or teardown with the specified peer. 2706 * 2707 * @param ifaceName Name of the interface. 2708 * @param macAddr MAC Address of the peer. 2709 * @param enable true to start discovery and setup, false to teardown. 2710 * @return true if request is sent successfully, false otherwise. 2711 */ 2712 public boolean startTdls(@NonNull String ifaceName, String macAddr, boolean enable) { 2713 boolean ret = true; 2714 if (enable) { 2715 mSupplicantStaIfaceHal.initiateTdlsDiscover(ifaceName, macAddr); 2716 ret = mSupplicantStaIfaceHal.initiateTdlsSetup(ifaceName, macAddr); 2717 } else { 2718 ret = mSupplicantStaIfaceHal.initiateTdlsTeardown(ifaceName, macAddr); 2719 } 2720 return ret; 2721 } 2722 2723 /** 2724 * Start WPS pin display operation with the specified peer. 2725 * 2726 * @param ifaceName Name of the interface. 2727 * @param bssid BSSID of the peer. 2728 * @return true if request is sent successfully, false otherwise. 2729 */ 2730 public boolean startWpsPbc(@NonNull String ifaceName, String bssid) { 2731 return mSupplicantStaIfaceHal.startWpsPbc(ifaceName, bssid); 2732 } 2733 2734 /** 2735 * Start WPS pin keypad operation with the specified pin. 2736 * 2737 * @param ifaceName Name of the interface. 2738 * @param pin Pin to be used. 2739 * @return true if request is sent successfully, false otherwise. 2740 */ 2741 public boolean startWpsPinKeypad(@NonNull String ifaceName, String pin) { 2742 return mSupplicantStaIfaceHal.startWpsPinKeypad(ifaceName, pin); 2743 } 2744 2745 /** 2746 * Start WPS pin display operation with the specified peer. 2747 * 2748 * @param ifaceName Name of the interface. 2749 * @param bssid BSSID of the peer. 2750 * @return new pin generated on success, null otherwise. 2751 */ 2752 public String startWpsPinDisplay(@NonNull String ifaceName, String bssid) { 2753 return mSupplicantStaIfaceHal.startWpsPinDisplay(ifaceName, bssid); 2754 } 2755 2756 /** 2757 * Sets whether to use external sim for SIM/USIM processing. 2758 * 2759 * @param ifaceName Name of the interface. 2760 * @param external true to enable, false otherwise. 2761 * @return true if request is sent successfully, false otherwise. 2762 */ 2763 public boolean setExternalSim(@NonNull String ifaceName, boolean external) { 2764 return mSupplicantStaIfaceHal.setExternalSim(ifaceName, external); 2765 } 2766 2767 /** 2768 * Sim auth response types. 2769 */ 2770 public static final String SIM_AUTH_RESP_TYPE_GSM_AUTH = "GSM-AUTH"; 2771 public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTH = "UMTS-AUTH"; 2772 public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTS = "UMTS-AUTS"; 2773 2774 /** 2775 * EAP-SIM Error Codes 2776 */ 2777 public static final int EAP_SIM_NOT_SUBSCRIBED = 1031; 2778 public static final int EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED = 16385; 2779 2780 /** 2781 * Send the sim auth response for the currently configured network. 2782 * 2783 * @param ifaceName Name of the interface. 2784 * @param type |GSM-AUTH|, |UMTS-AUTH| or |UMTS-AUTS|. 2785 * @param response Response params. 2786 * @return true if succeeds, false otherwise. 2787 */ 2788 public boolean simAuthResponse( 2789 @NonNull String ifaceName, String type, String response) { 2790 if (SIM_AUTH_RESP_TYPE_GSM_AUTH.equals(type)) { 2791 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthResponse( 2792 ifaceName, response); 2793 } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTH.equals(type)) { 2794 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthResponse( 2795 ifaceName, response); 2796 } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTS.equals(type)) { 2797 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAutsResponse( 2798 ifaceName, response); 2799 } else { 2800 return false; 2801 } 2802 } 2803 2804 /** 2805 * Send the eap sim gsm auth failure for the currently configured network. 2806 * 2807 * @param ifaceName Name of the interface. 2808 * @return true if succeeds, false otherwise. 2809 */ 2810 public boolean simAuthFailedResponse(@NonNull String ifaceName) { 2811 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthFailure(ifaceName); 2812 } 2813 2814 /** 2815 * Send the eap sim umts auth failure for the currently configured network. 2816 * 2817 * @param ifaceName Name of the interface. 2818 * @return true if succeeds, false otherwise. 2819 */ 2820 public boolean umtsAuthFailedResponse(@NonNull String ifaceName) { 2821 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthFailure(ifaceName); 2822 } 2823 2824 /** 2825 * Send the eap identity response for the currently configured network. 2826 * 2827 * @param ifaceName Name of the interface. 2828 * @param unencryptedResponse String to send. 2829 * @param encryptedResponse String to send. 2830 * @return true if succeeds, false otherwise. 2831 */ 2832 public boolean simIdentityResponse(@NonNull String ifaceName, String unencryptedResponse, 2833 String encryptedResponse) { 2834 return mSupplicantStaIfaceHal.sendCurrentNetworkEapIdentityResponse(ifaceName, 2835 unencryptedResponse, encryptedResponse); 2836 } 2837 2838 /** 2839 * This get anonymous identity from supplicant and returns it as a string. 2840 * 2841 * @param ifaceName Name of the interface. 2842 * @return anonymous identity string if succeeds, null otherwise. 2843 */ 2844 public String getEapAnonymousIdentity(@NonNull String ifaceName) { 2845 String anonymousIdentity = mSupplicantStaIfaceHal 2846 .getCurrentNetworkEapAnonymousIdentity(ifaceName); 2847 2848 if (TextUtils.isEmpty(anonymousIdentity)) { 2849 return anonymousIdentity; 2850 } 2851 2852 int indexOfDecoration = anonymousIdentity.lastIndexOf('!'); 2853 if (indexOfDecoration >= 0) { 2854 if (anonymousIdentity.substring(indexOfDecoration).length() < 2) { 2855 // Invalid identity, shouldn't happen 2856 Log.e(TAG, "Unexpected anonymous identity: " + anonymousIdentity); 2857 return null; 2858 } 2859 // Truncate RFC 7542 decorated prefix, if exists. Keep only the anonymous identity or 2860 // pseudonym. 2861 anonymousIdentity = anonymousIdentity.substring(indexOfDecoration + 1); 2862 } 2863 2864 return anonymousIdentity; 2865 } 2866 2867 /** 2868 * Start WPS pin registrar operation with the specified peer and pin. 2869 * 2870 * @param ifaceName Name of the interface. 2871 * @param bssid BSSID of the peer. 2872 * @param pin Pin to be used. 2873 * @return true if request is sent successfully, false otherwise. 2874 */ 2875 public boolean startWpsRegistrar(@NonNull String ifaceName, String bssid, String pin) { 2876 return mSupplicantStaIfaceHal.startWpsRegistrar(ifaceName, bssid, pin); 2877 } 2878 2879 /** 2880 * Cancels any ongoing WPS requests. 2881 * 2882 * @param ifaceName Name of the interface. 2883 * @return true if request is sent successfully, false otherwise. 2884 */ 2885 public boolean cancelWps(@NonNull String ifaceName) { 2886 return mSupplicantStaIfaceHal.cancelWps(ifaceName); 2887 } 2888 2889 /** 2890 * Set WPS device name. 2891 * 2892 * @param ifaceName Name of the interface. 2893 * @param name String to be set. 2894 * @return true if request is sent successfully, false otherwise. 2895 */ 2896 public boolean setDeviceName(@NonNull String ifaceName, String name) { 2897 return mSupplicantStaIfaceHal.setWpsDeviceName(ifaceName, name); 2898 } 2899 2900 /** 2901 * Set WPS device type. 2902 * 2903 * @param ifaceName Name of the interface. 2904 * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg> 2905 * @return true if request is sent successfully, false otherwise. 2906 */ 2907 public boolean setDeviceType(@NonNull String ifaceName, String type) { 2908 return mSupplicantStaIfaceHal.setWpsDeviceType(ifaceName, type); 2909 } 2910 2911 /** 2912 * Set WPS config methods 2913 * 2914 * @param cfg List of config methods. 2915 * @return true if request is sent successfully, false otherwise. 2916 */ 2917 public boolean setConfigMethods(@NonNull String ifaceName, String cfg) { 2918 return mSupplicantStaIfaceHal.setWpsConfigMethods(ifaceName, cfg); 2919 } 2920 2921 /** 2922 * Set WPS manufacturer. 2923 * 2924 * @param ifaceName Name of the interface. 2925 * @param value String to be set. 2926 * @return true if request is sent successfully, false otherwise. 2927 */ 2928 public boolean setManufacturer(@NonNull String ifaceName, String value) { 2929 return mSupplicantStaIfaceHal.setWpsManufacturer(ifaceName, value); 2930 } 2931 2932 /** 2933 * Set WPS model name. 2934 * 2935 * @param ifaceName Name of the interface. 2936 * @param value String to be set. 2937 * @return true if request is sent successfully, false otherwise. 2938 */ 2939 public boolean setModelName(@NonNull String ifaceName, String value) { 2940 return mSupplicantStaIfaceHal.setWpsModelName(ifaceName, value); 2941 } 2942 2943 /** 2944 * Set WPS model number. 2945 * 2946 * @param ifaceName Name of the interface. 2947 * @param value String to be set. 2948 * @return true if request is sent successfully, false otherwise. 2949 */ 2950 public boolean setModelNumber(@NonNull String ifaceName, String value) { 2951 return mSupplicantStaIfaceHal.setWpsModelNumber(ifaceName, value); 2952 } 2953 2954 /** 2955 * Set WPS serial number. 2956 * 2957 * @param ifaceName Name of the interface. 2958 * @param value String to be set. 2959 * @return true if request is sent successfully, false otherwise. 2960 */ 2961 public boolean setSerialNumber(@NonNull String ifaceName, String value) { 2962 return mSupplicantStaIfaceHal.setWpsSerialNumber(ifaceName, value); 2963 } 2964 2965 /** 2966 * Enable or disable power save mode. 2967 * 2968 * @param ifaceName Name of the interface. 2969 * @param enabled true to enable, false to disable. 2970 */ 2971 public void setPowerSave(@NonNull String ifaceName, boolean enabled) { 2972 mSupplicantStaIfaceHal.setPowerSave(ifaceName, enabled); 2973 } 2974 2975 /** 2976 * Enable or disable low latency mode. 2977 * 2978 * @param enabled true to enable, false to disable. 2979 * @return true on success, false on failure 2980 */ 2981 public boolean setLowLatencyMode(boolean enabled) { 2982 return mWifiVendorHal.setLowLatencyMode(enabled); 2983 } 2984 2985 /** 2986 * Set concurrency priority between P2P & STA operations. 2987 * 2988 * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations, 2989 * false otherwise. 2990 * @return true if request is sent successfully, false otherwise. 2991 */ 2992 public boolean setConcurrencyPriority(boolean isStaHigherPriority) { 2993 return mSupplicantStaIfaceHal.setConcurrencyPriority(isStaHigherPriority); 2994 } 2995 2996 /** 2997 * Enable/Disable auto reconnect functionality in wpa_supplicant. 2998 * 2999 * @param ifaceName Name of the interface. 3000 * @param enable true to enable auto reconnecting, false to disable. 3001 * @return true if request is sent successfully, false otherwise. 3002 */ 3003 public boolean enableStaAutoReconnect(@NonNull String ifaceName, boolean enable) { 3004 return mSupplicantStaIfaceHal.enableAutoReconnect(ifaceName, enable); 3005 } 3006 3007 /** 3008 * Add the provided network configuration to wpa_supplicant and initiate connection to it. 3009 * This method does the following: 3010 * 1. Abort any ongoing scan to unblock the connection request. 3011 * 2. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect). 3012 * 3. Add a new network to wpa_supplicant. 3013 * 4. Save the provided configuration to wpa_supplicant. 3014 * 5. Select the new network in wpa_supplicant. 3015 * 6. Triggers reconnect command to wpa_supplicant. 3016 * 3017 * @param ifaceName Name of the interface. 3018 * @param configuration WifiConfiguration parameters for the provided network. 3019 * @return {@code true} if it succeeds, {@code false} otherwise 3020 */ 3021 public boolean connectToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) { 3022 // Abort ongoing scan before connect() to unblock connection request. 3023 mWifiCondManager.abortScan(ifaceName); 3024 return mSupplicantStaIfaceHal.connectToNetwork(ifaceName, configuration); 3025 } 3026 3027 /** 3028 * Initiates roaming to the already configured network in wpa_supplicant. If the network 3029 * configuration provided does not match the already configured network, then this triggers 3030 * a new connection attempt (instead of roam). 3031 * 1. Abort any ongoing scan to unblock the roam request. 3032 * 2. First check if we're attempting to connect to the same network as we currently have 3033 * configured. 3034 * 3. Set the new bssid for the network in wpa_supplicant. 3035 * 4. Triggers reassociate command to wpa_supplicant. 3036 * 3037 * @param ifaceName Name of the interface. 3038 * @param configuration WifiConfiguration parameters for the provided network. 3039 * @return {@code true} if it succeeds, {@code false} otherwise 3040 */ 3041 public boolean roamToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) { 3042 // Abort ongoing scan before connect() to unblock roaming request. 3043 mWifiCondManager.abortScan(ifaceName); 3044 return mSupplicantStaIfaceHal.roamToNetwork(ifaceName, configuration); 3045 } 3046 3047 /** 3048 * Remove all the networks. 3049 * 3050 * @param ifaceName Name of the interface. 3051 * @return {@code true} if it succeeds, {@code false} otherwise 3052 */ 3053 public boolean removeAllNetworks(@NonNull String ifaceName) { 3054 return mSupplicantStaIfaceHal.removeAllNetworks(ifaceName); 3055 } 3056 3057 /** 3058 * Disable the currently configured network in supplicant 3059 * 3060 * @param ifaceName Name of the interface. 3061 */ 3062 public boolean disableNetwork(@NonNull String ifaceName) { 3063 return mSupplicantStaIfaceHal.disableCurrentNetwork(ifaceName); 3064 } 3065 3066 /** 3067 * Set the BSSID for the currently configured network in wpa_supplicant. 3068 * 3069 * @param ifaceName Name of the interface. 3070 * @return true if successful, false otherwise. 3071 */ 3072 public boolean setNetworkBSSID(@NonNull String ifaceName, String bssid) { 3073 return mSupplicantStaIfaceHal.setCurrentNetworkBssid(ifaceName, bssid); 3074 } 3075 3076 /** 3077 * Initiate ANQP query. 3078 * 3079 * @param ifaceName Name of the interface. 3080 * @param bssid BSSID of the AP to be queried 3081 * @param anqpIds Set of anqp IDs. 3082 * @param hs20Subtypes Set of HS20 subtypes. 3083 * @return true on success, false otherwise. 3084 */ 3085 public boolean requestAnqp( 3086 @NonNull String ifaceName, String bssid, Set<Integer> anqpIds, 3087 Set<Integer> hs20Subtypes) { 3088 if (bssid == null || ((anqpIds == null || anqpIds.isEmpty()) 3089 && (hs20Subtypes == null || hs20Subtypes.isEmpty()))) { 3090 Log.e(TAG, "Invalid arguments for ANQP request."); 3091 return false; 3092 } 3093 ArrayList<Short> anqpIdList = new ArrayList<>(); 3094 for (Integer anqpId : anqpIds) { 3095 anqpIdList.add(anqpId.shortValue()); 3096 } 3097 ArrayList<Integer> hs20SubtypeList = new ArrayList<>(); 3098 hs20SubtypeList.addAll(hs20Subtypes); 3099 return mSupplicantStaIfaceHal.initiateAnqpQuery( 3100 ifaceName, bssid, anqpIdList, hs20SubtypeList); 3101 } 3102 3103 /** 3104 * Request a passpoint icon file |filename| from the specified AP |bssid|. 3105 * 3106 * @param ifaceName Name of the interface. 3107 * @param bssid BSSID of the AP 3108 * @param fileName name of the icon file 3109 * @return true if request is sent successfully, false otherwise 3110 */ 3111 public boolean requestIcon(@NonNull String ifaceName, String bssid, String fileName) { 3112 if (bssid == null || fileName == null) { 3113 Log.e(TAG, "Invalid arguments for Icon request."); 3114 return false; 3115 } 3116 return mSupplicantStaIfaceHal.initiateHs20IconQuery(ifaceName, bssid, fileName); 3117 } 3118 3119 /** 3120 * Initiate Venue URL ANQP query. 3121 * 3122 * @param ifaceName Name of the interface. 3123 * @param bssid BSSID of the AP to be queried 3124 * @return true on success, false otherwise. 3125 */ 3126 public boolean requestVenueUrlAnqp( 3127 @NonNull String ifaceName, String bssid) { 3128 if (bssid == null) { 3129 Log.e(TAG, "Invalid arguments for Venue URL ANQP request."); 3130 return false; 3131 } 3132 return mSupplicantStaIfaceHal.initiateVenueUrlAnqpQuery(ifaceName, bssid); 3133 } 3134 3135 /** 3136 * Get the currently configured network's WPS NFC token. 3137 * 3138 * @param ifaceName Name of the interface. 3139 * @return Hex string corresponding to the WPS NFC token. 3140 */ 3141 public String getCurrentNetworkWpsNfcConfigurationToken(@NonNull String ifaceName) { 3142 return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken(ifaceName); 3143 } 3144 3145 /** 3146 * Clean HAL cached data for |networkId|. 3147 * 3148 * @param networkId network id of the network to be removed from supplicant. 3149 */ 3150 public void removeNetworkCachedData(int networkId) { 3151 mSupplicantStaIfaceHal.removeNetworkCachedData(networkId); 3152 } 3153 3154 /** Clear HAL cached data for |networkId| if MAC address is changed. 3155 * 3156 * @param networkId network id of the network to be checked. 3157 * @param curMacAddress current MAC address 3158 */ 3159 public void removeNetworkCachedDataIfNeeded(int networkId, MacAddress curMacAddress) { 3160 mSupplicantStaIfaceHal.removeNetworkCachedDataIfNeeded(networkId, curMacAddress); 3161 } 3162 3163 /* 3164 * DPP 3165 */ 3166 3167 /** 3168 * Adds a DPP peer URI to the URI list. 3169 * 3170 * @param ifaceName Interface name 3171 * @param uri Bootstrap (URI) string (e.g. DPP:....) 3172 * @return ID, or -1 for failure 3173 */ 3174 public int addDppPeerUri(@NonNull String ifaceName, @NonNull String uri) { 3175 return mSupplicantStaIfaceHal.addDppPeerUri(ifaceName, uri); 3176 } 3177 3178 /** 3179 * Removes a DPP URI to the URI list given an ID. 3180 * 3181 * @param ifaceName Interface name 3182 * @param bootstrapId Bootstrap (URI) ID 3183 * @return true when operation is successful, or false for failure 3184 */ 3185 public boolean removeDppUri(@NonNull String ifaceName, int bootstrapId) { 3186 return mSupplicantStaIfaceHal.removeDppUri(ifaceName, bootstrapId); 3187 } 3188 3189 /** 3190 * Stops/aborts DPP Initiator request 3191 * 3192 * @param ifaceName Interface name 3193 * @return true when operation is successful, or false for failure 3194 */ 3195 public boolean stopDppInitiator(@NonNull String ifaceName) { 3196 return mSupplicantStaIfaceHal.stopDppInitiator(ifaceName); 3197 } 3198 3199 /** 3200 * Starts DPP Configurator-Initiator request 3201 * 3202 * @param ifaceName Interface name 3203 * @param peerBootstrapId Peer's bootstrap (URI) ID 3204 * @param ownBootstrapId Own bootstrap (URI) ID - Optional, 0 for none 3205 * @param ssid SSID of the selected network 3206 * @param password Password of the selected network, or 3207 * @param psk PSK of the selected network in hexadecimal representation 3208 * @param netRole The network role of the enrollee (STA or AP) 3209 * @param securityAkm Security AKM to use: PSK, SAE 3210 * @return true when operation is successful, or false for failure 3211 */ 3212 public boolean startDppConfiguratorInitiator(@NonNull String ifaceName, int peerBootstrapId, 3213 int ownBootstrapId, @NonNull String ssid, String password, String psk, 3214 int netRole, int securityAkm, byte[] privEcKey) { 3215 return mSupplicantStaIfaceHal.startDppConfiguratorInitiator(ifaceName, peerBootstrapId, 3216 ownBootstrapId, ssid, password, psk, netRole, securityAkm, privEcKey); 3217 } 3218 3219 /** 3220 * Starts DPP Enrollee-Initiator request 3221 * 3222 * @param ifaceName Interface name 3223 * @param peerBootstrapId Peer's bootstrap (URI) ID 3224 * @param ownBootstrapId Own bootstrap (URI) ID - Optional, 0 for none 3225 * @return true when operation is successful, or false for failure 3226 */ 3227 public boolean startDppEnrolleeInitiator(@NonNull String ifaceName, int peerBootstrapId, 3228 int ownBootstrapId) { 3229 return mSupplicantStaIfaceHal.startDppEnrolleeInitiator(ifaceName, peerBootstrapId, 3230 ownBootstrapId); 3231 } 3232 3233 /** 3234 * Callback to notify about DPP success, failure and progress events. 3235 */ 3236 public interface DppEventCallback { 3237 /** 3238 * Called when local DPP Enrollee successfully receives a new Wi-Fi configuration from the 3239 * peer DPP configurator. 3240 * 3241 * @param newWifiConfiguration New Wi-Fi configuration received from the configurator 3242 * @param connStatusRequested Flag to indicate that the configurator requested 3243 * connection status 3244 */ 3245 void onSuccessConfigReceived(WifiConfiguration newWifiConfiguration, 3246 boolean connStatusRequested); 3247 3248 /** 3249 * DPP Success event. 3250 * 3251 * @param dppStatusCode Status code of the success event. 3252 */ 3253 void onSuccess(int dppStatusCode); 3254 3255 /** 3256 * DPP Progress event. 3257 * 3258 * @param dppStatusCode Status code of the progress event. 3259 */ 3260 void onProgress(int dppStatusCode); 3261 3262 /** 3263 * DPP Failure event. 3264 * 3265 * @param dppStatusCode Status code of the failure event. 3266 * @param ssid SSID of the network the Enrollee tried to connect to. 3267 * @param channelList List of channels the Enrollee scanned for the network. 3268 * @param bandList List of bands the Enrollee supports. 3269 */ 3270 void onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList); 3271 3272 /** 3273 * DPP Configurator Private keys update. 3274 * 3275 * @param key Configurator's private EC key. 3276 */ 3277 void onDppConfiguratorKeyUpdate(byte[] key); 3278 3279 /** 3280 * Indicates that DPP connection status result frame is sent 3281 * 3282 * @param result DPP Status value indicating the result of a connection attempt. 3283 */ 3284 void onConnectionStatusResultSent(int result); 3285 } 3286 3287 /** 3288 * Class to get generated bootstrap info for DPP responder operation. 3289 */ 3290 public static class DppBootstrapQrCodeInfo { 3291 public int bootstrapId; 3292 public int listenChannel; 3293 public String uri = new String(); 3294 DppBootstrapQrCodeInfo() { 3295 bootstrapId = -1; 3296 listenChannel = -1; 3297 } 3298 } 3299 3300 /** 3301 * Generate DPP bootstrap Information:Bootstrap ID, DPP URI and the listen channel. 3302 * 3303 * @param ifaceName Interface name 3304 * @param deviceInfo Device specific info to attach in DPP URI. 3305 * @param dppCurve Elliptic curve cryptography type used to generate DPP 3306 * public/private key pair. 3307 * @return ID, or -1 for failure 3308 */ 3309 public DppBootstrapQrCodeInfo generateDppBootstrapInfoForResponder(@NonNull String ifaceName, 3310 String deviceInfo, int dppCurve) { 3311 return mSupplicantStaIfaceHal.generateDppBootstrapInfoForResponder(ifaceName, 3312 getMacAddress(ifaceName), deviceInfo, dppCurve); 3313 } 3314 3315 /** 3316 * start DPP Enrollee responder mode. 3317 * 3318 * @param ifaceName Interface name 3319 * @param listenChannel Listen channel to wait for DPP authentication request. 3320 * @return ID, or -1 for failure 3321 */ 3322 public boolean startDppEnrolleeResponder(@NonNull String ifaceName, int listenChannel) { 3323 return mSupplicantStaIfaceHal.startDppEnrolleeResponder(ifaceName, listenChannel); 3324 } 3325 3326 /** 3327 * Stops/aborts DPP Responder request 3328 * 3329 * @param ifaceName Interface name 3330 * @param ownBootstrapId Bootstrap (URI) ID 3331 * @return true when operation is successful, or false for failure 3332 */ 3333 public boolean stopDppResponder(@NonNull String ifaceName, int ownBootstrapId) { 3334 return mSupplicantStaIfaceHal.stopDppResponder(ifaceName, ownBootstrapId); 3335 } 3336 3337 3338 /** 3339 * Registers DPP event callbacks. 3340 * 3341 * @param dppEventCallback Callback object. 3342 */ 3343 public void registerDppEventCallback(DppEventCallback dppEventCallback) { 3344 mSupplicantStaIfaceHal.registerDppCallback(dppEventCallback); 3345 } 3346 3347 /** 3348 * Check whether Supplicant is using the AIDL HAL service. 3349 * 3350 * @return true if the Supplicant is using the AIDL service, false otherwise. 3351 */ 3352 public boolean isSupplicantUsingAidlService() { 3353 return mSupplicantStaIfaceHal.isAidlService(); 3354 } 3355 3356 /** 3357 * Check whether the Supplicant AIDL service is running at least the expected version. 3358 * 3359 * @param expectedVersion Version number to check. 3360 * @return true if the AIDL service is available and >= the expected version, false otherwise. 3361 */ 3362 public boolean isSupplicantAidlServiceVersionAtLeast(int expectedVersion) { 3363 return mSupplicantStaIfaceHal.isAidlServiceVersionAtLeast(expectedVersion); 3364 } 3365 3366 /******************************************************** 3367 * Vendor HAL operations 3368 ********************************************************/ 3369 /** 3370 * Callback to notify vendor HAL death. 3371 */ 3372 public interface VendorHalDeathEventHandler { 3373 /** 3374 * Invoked when the vendor HAL dies. 3375 */ 3376 void onDeath(); 3377 } 3378 3379 /** 3380 * Callback to notify when vendor HAL detects that a change in radio mode. 3381 */ 3382 public interface VendorHalRadioModeChangeEventHandler { 3383 /** 3384 * Invoked when the vendor HAL detects a change to MCC mode. 3385 * MCC (Multi channel concurrency) = Multiple interfaces are active on the same band, 3386 * different channels, same radios. 3387 * 3388 * @param band Band on which MCC is detected (specified by one of the 3389 * WifiScanner.WIFI_BAND_* constants) 3390 */ 3391 void onMcc(int band); 3392 /** 3393 * Invoked when the vendor HAL detects a change to SCC mode. 3394 * SCC (Single channel concurrency) = Multiple interfaces are active on the same band, same 3395 * channels, same radios. 3396 * 3397 * @param band Band on which SCC is detected (specified by one of the 3398 * WifiScanner.WIFI_BAND_* constants) 3399 */ 3400 void onScc(int band); 3401 /** 3402 * Invoked when the vendor HAL detects a change to SBS mode. 3403 * SBS (Single Band Simultaneous) = Multiple interfaces are active on the same band, 3404 * different channels, different radios. 3405 * 3406 * @param band Band on which SBS is detected (specified by one of the 3407 * WifiScanner.WIFI_BAND_* constants) 3408 */ 3409 void onSbs(int band); 3410 /** 3411 * Invoked when the vendor HAL detects a change to DBS mode. 3412 * DBS (Dual Band Simultaneous) = Multiple interfaces are active on the different bands, 3413 * different channels, different radios. 3414 */ 3415 void onDbs(); 3416 } 3417 3418 /** 3419 * Tests whether the HAL is running or not 3420 */ 3421 public boolean isHalStarted() { 3422 return mWifiVendorHal.isHalStarted(); 3423 } 3424 3425 /** 3426 * Tests whether the HAL is supported or not 3427 */ 3428 public boolean isHalSupported() { 3429 return mWifiVendorHal.isVendorHalSupported(); 3430 } 3431 3432 // TODO: Change variable names to camel style. 3433 public static class ScanCapabilities { 3434 public int max_scan_cache_size; 3435 public int max_scan_buckets; 3436 public int max_ap_cache_per_scan; 3437 public int max_rssi_sample_size; 3438 public int max_scan_reporting_threshold; 3439 } 3440 3441 /** 3442 * Gets the scan capabilities 3443 * 3444 * @param ifaceName Name of the interface. 3445 * @param capabilities object to be filled in 3446 * @return true for success. false for failure 3447 */ 3448 public boolean getBgScanCapabilities( 3449 @NonNull String ifaceName, ScanCapabilities capabilities) { 3450 return mWifiVendorHal.getBgScanCapabilities(ifaceName, capabilities); 3451 } 3452 3453 public static class ChannelSettings { 3454 public int frequency; 3455 public int dwell_time_ms; 3456 public boolean passive; 3457 } 3458 3459 public static class BucketSettings { 3460 public int bucket; 3461 public int band; 3462 public int period_ms; 3463 public int max_period_ms; 3464 public int step_count; 3465 public int report_events; 3466 public int num_channels; 3467 public ChannelSettings[] channels; 3468 } 3469 3470 /** 3471 * Network parameters for hidden networks to be scanned for. 3472 */ 3473 public static class HiddenNetwork { 3474 public String ssid; 3475 3476 @Override 3477 public boolean equals(Object otherObj) { 3478 if (this == otherObj) { 3479 return true; 3480 } else if (otherObj == null || getClass() != otherObj.getClass()) { 3481 return false; 3482 } 3483 HiddenNetwork other = (HiddenNetwork) otherObj; 3484 return Objects.equals(ssid, other.ssid); 3485 } 3486 3487 @Override 3488 public int hashCode() { 3489 return Objects.hash(ssid); 3490 } 3491 } 3492 3493 public static class ScanSettings { 3494 /** 3495 * Type of scan to perform. One of {@link WifiScanner#SCAN_TYPE_LOW_LATENCY}, 3496 * {@link WifiScanner#SCAN_TYPE_LOW_POWER} or {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}. 3497 */ 3498 @WifiAnnotations.ScanType 3499 public int scanType; 3500 public int base_period_ms; 3501 public int max_ap_per_scan; 3502 public int report_threshold_percent; 3503 public int report_threshold_num_scans; 3504 public int num_buckets; 3505 public boolean enable6GhzRnr; 3506 /* Not used for bg scans. Only works for single scans. */ 3507 public HiddenNetwork[] hiddenNetworks; 3508 public BucketSettings[] buckets; 3509 public byte[] vendorIes; 3510 } 3511 3512 /** 3513 * Network parameters to start PNO scan. 3514 */ 3515 public static class PnoNetwork { 3516 public String ssid; 3517 public byte flags; 3518 public byte auth_bit_field; 3519 public int[] frequencies; 3520 3521 @Override 3522 public boolean equals(Object otherObj) { 3523 if (this == otherObj) { 3524 return true; 3525 } else if (otherObj == null || getClass() != otherObj.getClass()) { 3526 return false; 3527 } 3528 PnoNetwork other = (PnoNetwork) otherObj; 3529 return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags) 3530 && (auth_bit_field == other.auth_bit_field)) 3531 && Arrays.equals(frequencies, other.frequencies); 3532 } 3533 3534 @Override 3535 public int hashCode() { 3536 return Objects.hash(ssid, flags, auth_bit_field, Arrays.hashCode(frequencies)); 3537 } 3538 3539 android.net.wifi.nl80211.PnoNetwork toNativePnoNetwork() { 3540 android.net.wifi.nl80211.PnoNetwork nativePnoNetwork = 3541 new android.net.wifi.nl80211.PnoNetwork(); 3542 nativePnoNetwork.setHidden( 3543 (flags & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0); 3544 try { 3545 nativePnoNetwork.setSsid( 3546 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid))); 3547 } catch (IllegalArgumentException e) { 3548 Log.e(TAG, "Illegal argument " + ssid, e); 3549 return null; 3550 } 3551 nativePnoNetwork.setFrequenciesMhz(frequencies); 3552 return nativePnoNetwork; 3553 } 3554 } 3555 3556 /** 3557 * Parameters to start PNO scan. This holds the list of networks which are going to used for 3558 * PNO scan. 3559 */ 3560 public static class PnoSettings { 3561 public int min5GHzRssi; 3562 public int min24GHzRssi; 3563 public int min6GHzRssi; 3564 public int periodInMs; 3565 public int scanIterations; 3566 public int scanIntervalMultiplier; 3567 public boolean isConnected; 3568 public PnoNetwork[] networkList; 3569 3570 android.net.wifi.nl80211.PnoSettings toNativePnoSettings() { 3571 android.net.wifi.nl80211.PnoSettings nativePnoSettings = 3572 new android.net.wifi.nl80211.PnoSettings(); 3573 nativePnoSettings.setIntervalMillis(periodInMs); 3574 nativePnoSettings.setMin2gRssiDbm(min24GHzRssi); 3575 nativePnoSettings.setMin5gRssiDbm(min5GHzRssi); 3576 nativePnoSettings.setMin6gRssiDbm(min6GHzRssi); 3577 if (SdkLevel.isAtLeastU()) { 3578 nativePnoSettings.setScanIterations(scanIterations); 3579 nativePnoSettings.setScanIntervalMultiplier(scanIntervalMultiplier); 3580 } 3581 3582 List<android.net.wifi.nl80211.PnoNetwork> pnoNetworks = new ArrayList<>(); 3583 if (networkList != null) { 3584 for (PnoNetwork network : networkList) { 3585 android.net.wifi.nl80211.PnoNetwork nativeNetwork = 3586 network.toNativePnoNetwork(); 3587 if (nativeNetwork != null) { 3588 pnoNetworks.add(nativeNetwork); 3589 } 3590 } 3591 } 3592 nativePnoSettings.setPnoNetworks(pnoNetworks); 3593 return nativePnoSettings; 3594 } 3595 } 3596 3597 public static interface ScanEventHandler { 3598 /** 3599 * Called for each AP as it is found with the entire contents of the beacon/probe response. 3600 * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified. 3601 */ 3602 void onFullScanResult(ScanResult fullScanResult, int bucketsScanned); 3603 /** 3604 * Callback on an event during a gscan scan. 3605 * See WifiNative.WIFI_SCAN_* for possible values. 3606 */ 3607 void onScanStatus(int event); 3608 /** 3609 * Called with the current cached scan results when gscan is paused. 3610 */ 3611 void onScanPaused(WifiScanner.ScanData[] data); 3612 /** 3613 * Called with the current cached scan results when gscan is resumed. 3614 */ 3615 void onScanRestarted(); 3616 /** 3617 * Callback to notify when the scan request fails. 3618 * See WifiScanner.REASON_* for possible values. 3619 */ 3620 void onScanRequestFailed(int errorCode); 3621 } 3622 3623 /** 3624 * Handler to notify the occurrence of various events during PNO scan. 3625 */ 3626 public interface PnoEventHandler { 3627 /** 3628 * Callback to notify when one of the shortlisted networks is found during PNO scan. 3629 * @param results List of Scan results received. 3630 */ 3631 void onPnoNetworkFound(ScanResult[] results); 3632 3633 /** 3634 * Callback to notify when the PNO scan schedule fails. 3635 */ 3636 void onPnoScanFailed(); 3637 } 3638 3639 public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0; 3640 public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1; 3641 public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2; 3642 public static final int WIFI_SCAN_FAILED = 3; 3643 3644 /** 3645 * Starts a background scan. 3646 * Any ongoing scan will be stopped first 3647 * 3648 * @param ifaceName Name of the interface. 3649 * @param settings to control the scan 3650 * @param eventHandler to call with the results 3651 * @return true for success 3652 */ 3653 public boolean startBgScan( 3654 @NonNull String ifaceName, ScanSettings settings, ScanEventHandler eventHandler) { 3655 return mWifiVendorHal.startBgScan(ifaceName, settings, eventHandler); 3656 } 3657 3658 /** 3659 * Stops any ongoing backgound scan 3660 * @param ifaceName Name of the interface. 3661 */ 3662 public void stopBgScan(@NonNull String ifaceName) { 3663 mWifiVendorHal.stopBgScan(ifaceName); 3664 } 3665 3666 /** 3667 * Pauses an ongoing backgound scan 3668 * @param ifaceName Name of the interface. 3669 */ 3670 public void pauseBgScan(@NonNull String ifaceName) { 3671 mWifiVendorHal.pauseBgScan(ifaceName); 3672 } 3673 3674 /** 3675 * Restarts a paused scan 3676 * @param ifaceName Name of the interface. 3677 */ 3678 public void restartBgScan(@NonNull String ifaceName) { 3679 mWifiVendorHal.restartBgScan(ifaceName); 3680 } 3681 3682 /** 3683 * Gets the latest scan results received. 3684 * @param ifaceName Name of the interface. 3685 */ 3686 public WifiScanner.ScanData[] getBgScanResults(@NonNull String ifaceName) { 3687 return mWifiVendorHal.getBgScanResults(ifaceName); 3688 } 3689 3690 /** 3691 * Sets whether global location mode is enabled. 3692 */ 3693 public void setLocationModeEnabled(boolean enabled) { 3694 if (!mIsLocationModeEnabled && enabled) { 3695 mLastLocationModeEnabledTimeMs = SystemClock.elapsedRealtime(); 3696 } 3697 Log.d(TAG, "mIsLocationModeEnabled " + enabled 3698 + " mLastLocationModeEnabledTimeMs " + mLastLocationModeEnabledTimeMs); 3699 mIsLocationModeEnabled = enabled; 3700 } 3701 3702 @NonNull 3703 private ScanResult[] getCachedScanResultsFilteredByLocationModeEnabled( 3704 @NonNull ScanResult[] scanResults) { 3705 List<ScanResult> resultList = new ArrayList<ScanResult>(); 3706 for (ScanResult scanResult : scanResults) { 3707 if (mIsLocationModeEnabled 3708 && scanResult.timestamp >= mLastLocationModeEnabledTimeMs * 1000) { 3709 resultList.add(scanResult); 3710 } 3711 } 3712 return resultList.toArray(new ScanResult[0]); 3713 } 3714 3715 /** 3716 * Gets the cached scan data from the given client interface 3717 */ 3718 @Nullable 3719 ScanData getCachedScanResults(String ifaceName) { 3720 ScanData scanData = mWifiVendorHal.getCachedScanData(ifaceName); 3721 if (scanData == null || scanData.getResults() == null) { 3722 return null; 3723 } 3724 ScanResult[] results = getCachedScanResultsFilteredByLocationModeEnabled( 3725 scanData.getResults()); 3726 return new ScanData(0, 0, 0, scanData.getScannedBands(), results); 3727 } 3728 3729 /** 3730 * Gets the cached scan data from all client interfaces 3731 */ 3732 @NonNull 3733 public ScanData getCachedScanResultsFromAllClientIfaces() { 3734 ScanData consolidatedScanData = new ScanData(); 3735 Set<String> ifaceNames = getClientInterfaceNames(); 3736 for (String ifaceName : ifaceNames) { 3737 ScanData scanData = getCachedScanResults(ifaceName); 3738 if (scanData == null) { 3739 continue; 3740 } 3741 consolidatedScanData.addResults(scanData.getResults()); 3742 } 3743 return consolidatedScanData; 3744 } 3745 3746 /** 3747 * Gets the latest link layer stats 3748 * @param ifaceName Name of the interface. 3749 */ 3750 public WifiLinkLayerStats getWifiLinkLayerStats(@NonNull String ifaceName) { 3751 WifiLinkLayerStats stats = mWifiVendorHal.getWifiLinkLayerStats(ifaceName); 3752 if (stats != null) { 3753 stats.aggregateLinkLayerStats(); 3754 } 3755 return stats; 3756 } 3757 3758 /** 3759 * Gets the usable channels 3760 * @param band one of the {@code WifiScanner#WIFI_BAND_*} constants. 3761 * @param mode bitmask of {@code WifiAvailablechannel#OP_MODE_*} constants. 3762 * @param filter bitmask of filters (regulatory, coex, concurrency). 3763 * 3764 * @return list of channels 3765 */ 3766 public List<WifiAvailableChannel> getUsableChannels( 3767 @WifiScanner.WifiBand int band, 3768 @WifiAvailableChannel.OpMode int mode, 3769 @WifiAvailableChannel.Filter int filter) { 3770 return mWifiVendorHal.getUsableChannels(band, mode, filter); 3771 } 3772 /** 3773 * Returns whether the device supports the requested 3774 * {@link HalDeviceManager.HdmIfaceTypeForCreation} combo. 3775 */ 3776 public boolean canDeviceSupportCreateTypeCombo(SparseArray<Integer> combo) { 3777 synchronized (mLock) { 3778 return mWifiVendorHal.canDeviceSupportCreateTypeCombo(combo); 3779 } 3780 } 3781 3782 /** 3783 * Returns whether STA + AP concurrency is supported or not. 3784 */ 3785 public boolean isStaApConcurrencySupported() { 3786 synchronized (mLock) { 3787 return mWifiVendorHal.canDeviceSupportCreateTypeCombo( 3788 new SparseArray<Integer>() {{ 3789 put(HDM_CREATE_IFACE_STA, 1); 3790 put(HDM_CREATE_IFACE_AP, 1); 3791 }}); 3792 } 3793 } 3794 3795 /** 3796 * Returns whether STA + STA concurrency is supported or not. 3797 */ 3798 public boolean isStaStaConcurrencySupported() { 3799 synchronized (mLock) { 3800 return mWifiVendorHal.canDeviceSupportCreateTypeCombo( 3801 new SparseArray<Integer>() {{ 3802 put(HDM_CREATE_IFACE_STA, 2); 3803 }}); 3804 } 3805 } 3806 3807 /** 3808 * Returns whether P2p + STA concurrency is supported or not. 3809 */ 3810 public boolean isP2pStaConcurrencySupported() { 3811 synchronized (mLock) { 3812 return mWifiVendorHal.canDeviceSupportCreateTypeCombo( 3813 new SparseArray<Integer>() {{ 3814 put(HDM_CREATE_IFACE_STA, 1); 3815 put(HDM_CREATE_IFACE_P2P, 1); 3816 }}); 3817 } 3818 } 3819 3820 /** 3821 * Returns whether Nan + STA concurrency is supported or not. 3822 */ 3823 public boolean isNanStaConcurrencySupported() { 3824 synchronized (mLock) { 3825 return mWifiVendorHal.canDeviceSupportCreateTypeCombo( 3826 new SparseArray<Integer>() {{ 3827 put(HDM_CREATE_IFACE_STA, 1); 3828 put(HDM_CREATE_IFACE_NAN, 1); 3829 }}); 3830 } 3831 } 3832 3833 /** 3834 * Returns whether a new AP iface can be created or not. 3835 */ 3836 public boolean isItPossibleToCreateApIface(@NonNull WorkSource requestorWs) { 3837 synchronized (mLock) { 3838 if (!isHalStarted()) { 3839 return canDeviceSupportCreateTypeCombo( 3840 new SparseArray<Integer>() {{ 3841 put(HDM_CREATE_IFACE_AP, 1); 3842 }}); 3843 } 3844 return mWifiVendorHal.isItPossibleToCreateApIface(requestorWs); 3845 } 3846 } 3847 3848 /** 3849 * Returns whether a new AP iface can be created or not. 3850 */ 3851 public boolean isItPossibleToCreateBridgedApIface(@NonNull WorkSource requestorWs) { 3852 synchronized (mLock) { 3853 if (!isHalStarted()) { 3854 return canDeviceSupportCreateTypeCombo( 3855 new SparseArray<Integer>() {{ 3856 put(HDM_CREATE_IFACE_AP_BRIDGE, 1); 3857 }}); 3858 } 3859 return mWifiVendorHal.isItPossibleToCreateBridgedApIface(requestorWs); 3860 } 3861 } 3862 3863 /** 3864 * Returns whether creating a single AP does not require destroying an existing iface, but 3865 * creating a bridged AP does. 3866 */ 3867 public boolean shouldDowngradeToSingleApForConcurrency(@NonNull WorkSource requestorWs) { 3868 synchronized (mLock) { 3869 if (!mWifiVendorHal.isHalStarted()) { 3870 return false; 3871 } 3872 return !mWifiVendorHal.canDeviceSupportAdditionalIface(HDM_CREATE_IFACE_AP_BRIDGE, 3873 requestorWs) 3874 && mWifiVendorHal.canDeviceSupportAdditionalIface(HDM_CREATE_IFACE_AP, 3875 requestorWs); 3876 } 3877 } 3878 3879 /** 3880 * Returns whether a new STA iface can be created or not. 3881 */ 3882 public boolean isItPossibleToCreateStaIface(@NonNull WorkSource requestorWs) { 3883 synchronized (mLock) { 3884 if (!isHalStarted()) { 3885 return canDeviceSupportCreateTypeCombo( 3886 new SparseArray<Integer>() {{ 3887 put(HDM_CREATE_IFACE_STA, 1); 3888 }}); 3889 } 3890 return mWifiVendorHal.isItPossibleToCreateStaIface(requestorWs); 3891 } 3892 } 3893 3894 /** 3895 * Set primary connection when multiple STA ifaces are active. 3896 * 3897 * @param ifaceName Name of the interface. 3898 * @return true for success 3899 */ 3900 public boolean setMultiStaPrimaryConnection(@NonNull String ifaceName) { 3901 synchronized (mLock) { 3902 return mWifiVendorHal.setMultiStaPrimaryConnection(ifaceName); 3903 } 3904 } 3905 3906 /** 3907 * Multi STA use case flags. 3908 */ 3909 public static final int DUAL_STA_TRANSIENT_PREFER_PRIMARY = 0; 3910 public static final int DUAL_STA_NON_TRANSIENT_UNBIASED = 1; 3911 3912 @IntDef({DUAL_STA_TRANSIENT_PREFER_PRIMARY, DUAL_STA_NON_TRANSIENT_UNBIASED}) 3913 @Retention(RetentionPolicy.SOURCE) 3914 public @interface MultiStaUseCase{} 3915 3916 /** 3917 * Set use-case when multiple STA ifaces are active. 3918 * 3919 * @param useCase one of the use cases. 3920 * @return true for success 3921 */ 3922 public boolean setMultiStaUseCase(@MultiStaUseCase int useCase) { 3923 synchronized (mLock) { 3924 return mWifiVendorHal.setMultiStaUseCase(useCase); 3925 } 3926 } 3927 3928 /** 3929 * Get the supported features 3930 * 3931 * @param ifaceName Name of the interface. 3932 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 3933 */ 3934 public long getSupportedFeatureSet(String ifaceName) { 3935 synchronized (mLock) { 3936 long featureSet = 0; 3937 // First get the complete feature set stored in config store when supplicant was 3938 // started 3939 featureSet = getCompleteFeatureSetFromConfigStore(); 3940 // Include the feature set saved in interface class. This is to make sure that 3941 // framework is returning the feature set for SoftAp only products and multi-chip 3942 // products. 3943 if (ifaceName != null) { 3944 Iface iface = mIfaceMgr.getIface(ifaceName); 3945 if (iface != null) { 3946 featureSet |= iface.featureSet; 3947 } 3948 } 3949 return featureSet; 3950 } 3951 } 3952 3953 /** 3954 * Get the supported bands for STA mode. 3955 * @return supported bands 3956 */ 3957 public @WifiScanner.WifiBand int getSupportedBandsForSta(String ifaceName) { 3958 synchronized (mLock) { 3959 if (ifaceName != null) { 3960 Iface iface = mIfaceMgr.getIface(ifaceName); 3961 if (iface != null) { 3962 return iface.bandsSupported; 3963 } 3964 } 3965 return WifiScanner.WIFI_BAND_UNSPECIFIED; 3966 } 3967 } 3968 3969 /** 3970 * Get the supported features 3971 * 3972 * @param ifaceName Name of the interface. 3973 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 3974 */ 3975 private long getSupportedFeatureSetInternal(@NonNull String ifaceName) { 3976 long featureSet = mSupplicantStaIfaceHal.getAdvancedCapabilities(ifaceName) 3977 | mWifiVendorHal.getSupportedFeatureSet(ifaceName) 3978 | mSupplicantStaIfaceHal.getWpaDriverFeatureSet(ifaceName); 3979 if (SdkLevel.isAtLeastT()) { 3980 if (((featureSet & WifiManager.WIFI_FEATURE_DPP) != 0) 3981 && mContext.getResources().getBoolean(R.bool.config_wifiDppAkmSupported)) { 3982 // Set if DPP is filled by supplicant and DPP AKM is enabled by overlay. 3983 featureSet |= WifiManager.WIFI_FEATURE_DPP_AKM; 3984 Log.v(TAG, ": DPP AKM supported"); 3985 } 3986 } 3987 Bundle twtCapabilities = mWifiVendorHal.getTwtCapabilities(ifaceName); 3988 if (twtCapabilities != null) mCachedTwtCapabilities.put(ifaceName, twtCapabilities); 3989 return featureSet; 3990 } 3991 3992 private void updateSupportedBandForStaInternal(Iface iface) { 3993 List<WifiAvailableChannel> usableChannelList = 3994 mWifiVendorHal.getUsableChannels(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ, 3995 WifiAvailableChannel.OP_MODE_STA, 3996 WifiAvailableChannel.FILTER_REGULATORY); 3997 int bands = 0; 3998 if (usableChannelList == null) { 3999 // If HAL doesn't support getUsableChannels then check wificond 4000 if (getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ).length > 0) { 4001 bands |= WifiScanner.WIFI_BAND_24_GHZ; 4002 } 4003 if (getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ).length > 0) { 4004 bands |= WifiScanner.WIFI_BAND_5_GHZ; 4005 } 4006 if (getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ).length > 0) { 4007 bands |= WifiScanner.WIFI_BAND_6_GHZ; 4008 } 4009 if (getChannelsForBand(WifiScanner.WIFI_BAND_60_GHZ).length > 0) { 4010 bands |= WifiScanner.WIFI_BAND_60_GHZ; 4011 } 4012 } else { 4013 for (int i = 0; i < usableChannelList.size(); i++) { 4014 int frequency = usableChannelList.get(i).getFrequencyMhz(); 4015 if (ScanResult.is24GHz(frequency)) { 4016 bands |= WifiScanner.WIFI_BAND_24_GHZ; 4017 } else if (ScanResult.is5GHz(frequency)) { 4018 bands |= WifiScanner.WIFI_BAND_5_GHZ; 4019 } else if (ScanResult.is6GHz(frequency)) { 4020 bands |= WifiScanner.WIFI_BAND_6_GHZ; 4021 } else if (ScanResult.is60GHz(frequency)) { 4022 bands |= WifiScanner.WIFI_BAND_60_GHZ; 4023 } 4024 } 4025 } 4026 if (mVerboseLoggingEnabled) { 4027 Log.i(TAG, "updateSupportedBandForStaInternal " + iface.name + " : 0x" 4028 + Integer.toHexString(bands)); 4029 } 4030 iface.bandsSupported = bands; 4031 } 4032 4033 /** 4034 * Class to retrieve connection capability parameters after association 4035 */ 4036 public static class ConnectionCapabilities { 4037 public @WifiAnnotations.WifiStandard int wifiStandard; 4038 public int channelBandwidth; 4039 public int maxNumberTxSpatialStreams; 4040 public int maxNumberRxSpatialStreams; 4041 public boolean is11bMode; 4042 /** Indicates the AP support for TID-to-link mapping negotiation. */ 4043 public boolean apTidToLinkMapNegotiationSupported; 4044 public @NonNull List<OuiKeyedData> vendorData; 4045 ConnectionCapabilities() { 4046 wifiStandard = ScanResult.WIFI_STANDARD_UNKNOWN; 4047 channelBandwidth = ScanResult.CHANNEL_WIDTH_20MHZ; 4048 maxNumberTxSpatialStreams = 1; 4049 maxNumberRxSpatialStreams = 1; 4050 is11bMode = false; 4051 vendorData = Collections.emptyList(); 4052 } 4053 } 4054 4055 /** 4056 * Returns connection capabilities of the current network 4057 * 4058 * @param ifaceName Name of the interface. 4059 * @return connection capabilities of the current network 4060 */ 4061 public ConnectionCapabilities getConnectionCapabilities(@NonNull String ifaceName) { 4062 return mSupplicantStaIfaceHal.getConnectionCapabilities(ifaceName); 4063 } 4064 4065 /** 4066 * Request signal polling to supplicant. 4067 * 4068 * @param ifaceName Name of the interface. 4069 * Returns an array of SignalPollResult objects. 4070 * Returns null on failure. 4071 */ 4072 @Nullable 4073 public WifiSignalPollResults signalPoll(@NonNull String ifaceName) { 4074 if (mMockWifiModem != null 4075 && mMockWifiModem.isMethodConfigured( 4076 MockWifiServiceUtil.MOCK_NL80211_SERVICE, "signalPoll")) { 4077 Log.i(TAG, "signalPoll was called from mock wificond"); 4078 WifiNl80211Manager.SignalPollResult result = 4079 mMockWifiModem.getWifiNl80211Manager().signalPoll(ifaceName); 4080 if (result != null) { 4081 // Convert WifiNl80211Manager#SignalPollResult to WifiSignalPollResults. 4082 // Assume single link and linkId = 0. 4083 WifiSignalPollResults results = new WifiSignalPollResults(); 4084 results.addEntry(0, result.currentRssiDbm, result.txBitrateMbps, 4085 result.rxBitrateMbps, result.associationFrequencyMHz); 4086 return results; 4087 } 4088 } 4089 // Query supplicant. 4090 WifiSignalPollResults results = mSupplicantStaIfaceHal.getSignalPollResults( 4091 ifaceName); 4092 if (results == null) { 4093 // Fallback to WifiCond. 4094 WifiNl80211Manager.SignalPollResult result = mWifiCondManager.signalPoll(ifaceName); 4095 if (result != null) { 4096 // Convert WifiNl80211Manager#SignalPollResult to WifiSignalPollResults. 4097 // Assume single link and linkId = 0. 4098 results = new WifiSignalPollResults(); 4099 results.addEntry(0, result.currentRssiDbm, result.txBitrateMbps, 4100 result.rxBitrateMbps, result.associationFrequencyMHz); 4101 } 4102 } 4103 return results; 4104 } 4105 4106 /** 4107 * Class to represent a connection MLO Link 4108 */ 4109 public static class ConnectionMloLink { 4110 private final int mLinkId; 4111 private final MacAddress mStaMacAddress; 4112 private final BitSet mTidsUplinkMap; 4113 private final BitSet mTidsDownlinkMap; 4114 private final MacAddress mApMacAddress; 4115 private final int mFrequencyMHz; 4116 4117 ConnectionMloLink(int id, MacAddress staMacAddress, MacAddress apMacAddress, 4118 byte tidsUplink, byte tidsDownlink, int frequencyMHz) { 4119 mLinkId = id; 4120 mStaMacAddress = staMacAddress; 4121 mApMacAddress = apMacAddress; 4122 mTidsDownlinkMap = BitSet.valueOf(new byte[] { tidsDownlink }); 4123 mTidsUplinkMap = BitSet.valueOf(new byte[] { tidsUplink }); 4124 mFrequencyMHz = frequencyMHz; 4125 }; 4126 4127 /** 4128 * Check if there is any TID mapped to this link in uplink of downlink direction. 4129 * 4130 * @return true if there is any TID mapped to this link, otherwise false. 4131 */ 4132 public boolean isAnyTidMapped() { 4133 if (mTidsDownlinkMap.isEmpty() && mTidsUplinkMap.isEmpty()) { 4134 return false; 4135 } 4136 return true; 4137 } 4138 4139 /** 4140 * Check if a TID is mapped to this link in uplink direction. 4141 * 4142 * @param tid TID value. 4143 * @return true if the TID is mapped in uplink direction. Otherwise, false. 4144 */ 4145 public boolean isTidMappedToUplink(byte tid) { 4146 if (tid < mTidsUplinkMap.length()) { 4147 return mTidsUplinkMap.get(tid); 4148 } 4149 return false; 4150 } 4151 4152 /** 4153 * Check if a TID is mapped to this link in downlink direction. Otherwise, false. 4154 * 4155 * @param tid TID value 4156 * @return true if the TID is mapped in downlink direction. Otherwise, false. 4157 */ 4158 public boolean isTidMappedtoDownlink(byte tid) { 4159 if (tid < mTidsDownlinkMap.length()) { 4160 return mTidsDownlinkMap.get(tid); 4161 } 4162 return false; 4163 } 4164 4165 /** 4166 * Get link id for the link. 4167 * 4168 * @return link id. 4169 */ 4170 public int getLinkId() { 4171 return mLinkId; 4172 } 4173 4174 /** 4175 * Get link STA MAC address. 4176 * 4177 * @return link mac address. 4178 */ 4179 public MacAddress getStaMacAddress() { 4180 return mStaMacAddress; 4181 } 4182 4183 /** 4184 * Get link AP MAC address. 4185 * 4186 * @return MAC address. 4187 */ 4188 public MacAddress getApMacAddress() { 4189 return mApMacAddress; 4190 } 4191 4192 /** 4193 * Get link frequency in MHz. 4194 * 4195 * @return frequency in Mhz. 4196 */ 4197 public int getFrequencyMHz() { 4198 return mFrequencyMHz; 4199 } 4200 } 4201 4202 /** 4203 * Class to represent the MLO links info for a connection that is collected after association 4204 */ 4205 public static class ConnectionMloLinksInfo { 4206 public ConnectionMloLink[] links; 4207 public MacAddress apMldMacAddress; 4208 public int apMloLinkId; 4209 ConnectionMloLinksInfo() { 4210 // Nothing for now 4211 } 4212 } 4213 4214 /** 4215 * Returns connection MLO Links Info. 4216 * 4217 * @param ifaceName Name of the interface. 4218 * @return connection MLO Links Info 4219 */ 4220 public ConnectionMloLinksInfo getConnectionMloLinksInfo(@NonNull String ifaceName) { 4221 return mSupplicantStaIfaceHal.getConnectionMloLinksInfo(ifaceName); 4222 } 4223 4224 /** 4225 * Get the APF (Android Packet Filter) capabilities of the device 4226 * @param ifaceName Name of the interface. 4227 */ 4228 public ApfCapabilities getApfCapabilities(@NonNull String ifaceName) { 4229 return mWifiVendorHal.getApfCapabilities(ifaceName); 4230 } 4231 4232 /** 4233 * Installs an APF program on this iface, replacing any existing program. 4234 * 4235 * @param ifaceName Name of the interface 4236 * @param filter is the android packet filter program 4237 * @return true for success 4238 */ 4239 public boolean installPacketFilter(@NonNull String ifaceName, byte[] filter) { 4240 return mWifiVendorHal.installPacketFilter(ifaceName, filter); 4241 } 4242 4243 /** 4244 * Reads the APF program and data buffer for this iface. 4245 * 4246 * @param ifaceName Name of the interface 4247 * @return the buffer returned by the driver, or null in case of an error 4248 */ 4249 public byte[] readPacketFilter(@NonNull String ifaceName) { 4250 return mWifiVendorHal.readPacketFilter(ifaceName); 4251 } 4252 4253 /** 4254 * Set country code for this AP iface. 4255 * @param ifaceName Name of the AP interface. 4256 * @param countryCode - two-letter country code (as ISO 3166) 4257 * @return true for success 4258 */ 4259 public boolean setApCountryCode(@NonNull String ifaceName, String countryCode) { 4260 if (mWifiVendorHal.setApCountryCode(ifaceName, countryCode)) { 4261 if (mCountryCodeChangeListener != null) { 4262 mCountryCodeChangeListener.onSetCountryCodeSucceeded(countryCode); 4263 } 4264 return true; 4265 } 4266 return false; 4267 } 4268 4269 /** 4270 * Set country code for this chip 4271 * @param countryCode - two-letter country code (as ISO 3166) 4272 * @return true for success 4273 */ 4274 public boolean setChipCountryCode(String countryCode) { 4275 if (mWifiVendorHal.setChipCountryCode(countryCode)) { 4276 if (mCountryCodeChangeListener != null) { 4277 mCountryCodeChangeListener.onSetCountryCodeSucceeded(countryCode); 4278 } 4279 return true; 4280 } 4281 return false; 4282 } 4283 4284 //--------------------------------------------------------------------------------- 4285 /* Wifi Logger commands/events */ 4286 public static interface WifiLoggerEventHandler { 4287 void onRingBufferData(RingBufferStatus status, byte[] buffer); 4288 void onWifiAlert(int errorCode, byte[] buffer); 4289 } 4290 4291 /** 4292 * Registers the logger callback and enables alerts. 4293 * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked. 4294 * 4295 * @param handler Callback to be invoked. 4296 * @return true on success, false otherwise. 4297 */ 4298 public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) { 4299 return mWifiVendorHal.setLoggingEventHandler(handler); 4300 } 4301 4302 /** 4303 * Control debug data collection 4304 * 4305 * @param verboseLevel 0 to 3, inclusive. 0 stops logging. 4306 * @param flags Ignored. 4307 * @param maxInterval Maximum interval between reports; ignore if 0. 4308 * @param minDataSize Minimum data size in buffer for report; ignore if 0. 4309 * @param ringName Name of the ring for which data collection is to start. 4310 * @return true for success, false otherwise. 4311 */ 4312 public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, 4313 int minDataSize, String ringName){ 4314 return mWifiVendorHal.startLoggingRingBuffer( 4315 verboseLevel, flags, maxInterval, minDataSize, ringName); 4316 } 4317 4318 /** 4319 * Logger features exposed. 4320 * This is a no-op now, will always return -1. 4321 * 4322 * @return true on success, false otherwise. 4323 */ 4324 public int getSupportedLoggerFeatureSet() { 4325 return mWifiVendorHal.getSupportedLoggerFeatureSet(); 4326 } 4327 4328 /** 4329 * Stops all logging and resets the logger callback. 4330 * This stops both the alerts and ring buffer data collection. 4331 * @return true on success, false otherwise. 4332 */ 4333 public boolean resetLogHandler() { 4334 return mWifiVendorHal.resetLogHandler(); 4335 } 4336 4337 /** 4338 * Vendor-provided wifi driver version string 4339 * 4340 * @return String returned from the HAL. 4341 */ 4342 public String getDriverVersion() { 4343 return mWifiVendorHal.getDriverVersion(); 4344 } 4345 4346 /** 4347 * Vendor-provided wifi firmware version string 4348 * 4349 * @return String returned from the HAL. 4350 */ 4351 public String getFirmwareVersion() { 4352 return mWifiVendorHal.getFirmwareVersion(); 4353 } 4354 4355 public static class RingBufferStatus{ 4356 public String name; 4357 public int flag; 4358 public int ringBufferId; 4359 public int ringBufferByteSize; 4360 public int verboseLevel; 4361 int writtenBytes; 4362 int readBytes; 4363 int writtenRecords; 4364 4365 // Bit masks for interpreting |flag| 4366 public static final int HAS_BINARY_ENTRIES = (1 << 0); 4367 public static final int HAS_ASCII_ENTRIES = (1 << 1); 4368 public static final int HAS_PER_PACKET_ENTRIES = (1 << 2); 4369 4370 @Override 4371 public String toString() { 4372 return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId + 4373 " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel + 4374 " writtenBytes: " + writtenBytes + " readBytes: " + readBytes + 4375 " writtenRecords: " + writtenRecords; 4376 } 4377 } 4378 4379 /** 4380 * API to get the status of all ring buffers supported by driver 4381 */ 4382 public RingBufferStatus[] getRingBufferStatus() { 4383 return mWifiVendorHal.getRingBufferStatus(); 4384 } 4385 4386 /** 4387 * Indicates to driver that all the data has to be uploaded urgently 4388 * 4389 * @param ringName Name of the ring buffer requested. 4390 * @return true on success, false otherwise. 4391 */ 4392 public boolean getRingBufferData(String ringName) { 4393 return mWifiVendorHal.getRingBufferData(ringName); 4394 } 4395 4396 /** 4397 * Request hal to flush ring buffers to files 4398 * 4399 * @return true on success, false otherwise. 4400 */ 4401 public boolean flushRingBufferData() { 4402 return mWifiVendorHal.flushRingBufferData(); 4403 } 4404 4405 /** 4406 * Request vendor debug info from the firmware 4407 * 4408 * @return Raw data obtained from the HAL. 4409 */ 4410 public byte[] getFwMemoryDump() { 4411 return mWifiVendorHal.getFwMemoryDump(); 4412 } 4413 4414 /** 4415 * Request vendor debug info from the driver 4416 * 4417 * @return Raw data obtained from the HAL. 4418 */ 4419 public byte[] getDriverStateDump() { 4420 return mWifiVendorHal.getDriverStateDump(); 4421 } 4422 4423 /** 4424 * Dump information about the internal state 4425 * 4426 * @param pw PrintWriter to write dump to 4427 */ 4428 protected void dump(PrintWriter pw) { 4429 pw.println("Dump of " + TAG); 4430 pw.println("mIsLocationModeEnabled: " + mIsLocationModeEnabled); 4431 pw.println("mLastLocationModeEnabledTimeMs: " + mLastLocationModeEnabledTimeMs); 4432 mHostapdHal.dump(pw); 4433 } 4434 4435 //--------------------------------------------------------------------------------- 4436 /* Packet fate API */ 4437 4438 @Immutable 4439 public abstract static class FateReport { 4440 final static int USEC_PER_MSEC = 1000; 4441 // The driver timestamp is a 32-bit counter, in microseconds. This field holds the 4442 // maximal value of a driver timestamp in milliseconds. 4443 final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000); 4444 final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS"); 4445 4446 public final byte mFate; 4447 public final long mDriverTimestampUSec; 4448 public final byte mFrameType; 4449 public final byte[] mFrameBytes; 4450 public final long mEstimatedWallclockMSec; 4451 4452 FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 4453 mFate = fate; 4454 mDriverTimestampUSec = driverTimestampUSec; 4455 mEstimatedWallclockMSec = 4456 convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec); 4457 mFrameType = frameType; 4458 mFrameBytes = frameBytes; 4459 } 4460 4461 public String toTableRowString() { 4462 StringWriter sw = new StringWriter(); 4463 PrintWriter pw = new PrintWriter(sw); 4464 FrameParser parser = new FrameParser(mFrameType, mFrameBytes); 4465 dateFormatter.setTimeZone(TimeZone.getDefault()); 4466 pw.format("%-15s %12s %-9s %-32s %-12s %-23s %s\n", 4467 mDriverTimestampUSec, 4468 dateFormatter.format(new Date(mEstimatedWallclockMSec)), 4469 directionToString(), fateToString(), parser.mMostSpecificProtocolString, 4470 parser.mTypeString, parser.mResultString); 4471 return sw.toString(); 4472 } 4473 4474 public String toVerboseStringWithPiiAllowed() { 4475 StringWriter sw = new StringWriter(); 4476 PrintWriter pw = new PrintWriter(sw); 4477 FrameParser parser = new FrameParser(mFrameType, mFrameBytes); 4478 pw.format("Frame direction: %s\n", directionToString()); 4479 pw.format("Frame timestamp: %d\n", mDriverTimestampUSec); 4480 pw.format("Frame fate: %s\n", fateToString()); 4481 pw.format("Frame type: %s\n", frameTypeToString(mFrameType)); 4482 pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString); 4483 pw.format("Frame protocol type: %s\n", parser.mTypeString); 4484 pw.format("Frame length: %d\n", mFrameBytes.length); 4485 pw.append("Frame bytes"); 4486 pw.append(HexDump.dumpHexString(mFrameBytes)); // potentially contains PII 4487 pw.append("\n"); 4488 return sw.toString(); 4489 } 4490 4491 /* Returns a header to match the output of toTableRowString(). */ 4492 public static String getTableHeader() { 4493 StringWriter sw = new StringWriter(); 4494 PrintWriter pw = new PrintWriter(sw); 4495 pw.format("\n%-15s %-12s %-9s %-32s %-12s %-23s %s\n", 4496 "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result"); 4497 pw.format("%-15s %-12s %-9s %-32s %-12s %-23s %s\n", 4498 "---------", "--------", "---------", "----", "--------", "----", "------"); 4499 return sw.toString(); 4500 } 4501 4502 protected abstract String directionToString(); 4503 4504 protected abstract String fateToString(); 4505 4506 private static String frameTypeToString(byte frameType) { 4507 switch (frameType) { 4508 case WifiLoggerHal.FRAME_TYPE_UNKNOWN: 4509 return "unknown"; 4510 case WifiLoggerHal.FRAME_TYPE_ETHERNET_II: 4511 return "data"; 4512 case WifiLoggerHal.FRAME_TYPE_80211_MGMT: 4513 return "802.11 management"; 4514 default: 4515 return Byte.toString(frameType); 4516 } 4517 } 4518 4519 /** 4520 * Converts a driver timestamp to a wallclock time, based on the current 4521 * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of 4522 * microseconds, with the same base as BOOTTIME. 4523 */ 4524 private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) { 4525 final long wallclockMillisNow = System.currentTimeMillis(); 4526 final long boottimeMillisNow = SystemClock.elapsedRealtime(); 4527 final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC; 4528 4529 long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC; 4530 if (boottimeTimestampMillis < driverTimestampMillis) { 4531 // The 32-bit microsecond count has wrapped between the time that the driver 4532 // recorded the packet, and the call to this function. Adjust the BOOTTIME 4533 // timestamp, to compensate. 4534 // 4535 // Note that overflow is not a concern here, since the result is less than 4536 // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above, 4537 // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since 4538 // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit 4539 // within a long. 4540 boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC; 4541 } 4542 4543 final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis; 4544 return wallclockMillisNow - millisSincePacketTimestamp; 4545 } 4546 } 4547 4548 /** 4549 * Represents the fate information for one outbound packet. 4550 */ 4551 @Immutable 4552 public static final class TxFateReport extends FateReport { 4553 public TxFateReport(byte fate, long driverTimestampUSec, byte frameType, 4554 byte[] frameBytes) { 4555 super(fate, driverTimestampUSec, frameType, frameBytes); 4556 } 4557 4558 @Override 4559 protected String directionToString() { 4560 return "TX"; 4561 } 4562 4563 @Override 4564 protected String fateToString() { 4565 switch (mFate) { 4566 case WifiLoggerHal.TX_PKT_FATE_ACKED: 4567 return "acked"; 4568 case WifiLoggerHal.TX_PKT_FATE_SENT: 4569 return "sent"; 4570 case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED: 4571 return "firmware queued"; 4572 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID: 4573 return "firmware dropped (invalid frame)"; 4574 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS: 4575 return "firmware dropped (no bufs)"; 4576 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER: 4577 return "firmware dropped (other)"; 4578 case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED: 4579 return "driver queued"; 4580 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID: 4581 return "driver dropped (invalid frame)"; 4582 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS: 4583 return "driver dropped (no bufs)"; 4584 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER: 4585 return "driver dropped (other)"; 4586 default: 4587 return Byte.toString(mFate); 4588 } 4589 } 4590 } 4591 4592 /** 4593 * Represents the fate information for one inbound packet. 4594 */ 4595 @Immutable 4596 public static final class RxFateReport extends FateReport { 4597 public RxFateReport(byte fate, long driverTimestampUSec, byte frameType, 4598 byte[] frameBytes) { 4599 super(fate, driverTimestampUSec, frameType, frameBytes); 4600 } 4601 4602 @Override 4603 protected String directionToString() { 4604 return "RX"; 4605 } 4606 4607 @Override 4608 protected String fateToString() { 4609 switch (mFate) { 4610 case WifiLoggerHal.RX_PKT_FATE_SUCCESS: 4611 return "success"; 4612 case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED: 4613 return "firmware queued"; 4614 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER: 4615 return "firmware dropped (filter)"; 4616 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID: 4617 return "firmware dropped (invalid frame)"; 4618 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS: 4619 return "firmware dropped (no bufs)"; 4620 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER: 4621 return "firmware dropped (other)"; 4622 case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED: 4623 return "driver queued"; 4624 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER: 4625 return "driver dropped (filter)"; 4626 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID: 4627 return "driver dropped (invalid frame)"; 4628 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS: 4629 return "driver dropped (no bufs)"; 4630 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER: 4631 return "driver dropped (other)"; 4632 default: 4633 return Byte.toString(mFate); 4634 } 4635 } 4636 } 4637 4638 /** 4639 * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started. 4640 * 4641 * @param ifaceName Name of the interface. 4642 * @return true for success, false otherwise. 4643 */ 4644 public boolean startPktFateMonitoring(@NonNull String ifaceName) { 4645 return mWifiVendorHal.startPktFateMonitoring(ifaceName); 4646 } 4647 4648 /** 4649 * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started. 4650 * 4651 * @param ifaceName Name of the interface. 4652 * @return TxFateReport list on success, empty list on failure. Never returns null. 4653 */ 4654 @NonNull 4655 public List<TxFateReport> getTxPktFates(@NonNull String ifaceName) { 4656 return mWifiVendorHal.getTxPktFates(ifaceName); 4657 } 4658 4659 /** 4660 * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started. 4661 * @param ifaceName Name of the interface. 4662 * @return RxFateReport list on success, empty list on failure. Never returns null. 4663 */ 4664 @NonNull 4665 public List<RxFateReport> getRxPktFates(@NonNull String ifaceName) { 4666 return mWifiVendorHal.getRxPktFates(ifaceName); 4667 } 4668 4669 /** 4670 * Get the tx packet counts for the interface. 4671 * 4672 * @param ifaceName Name of the interface. 4673 * @return tx packet counts 4674 */ 4675 public long getTxPackets(@NonNull String ifaceName) { 4676 return TrafficStats.getTxPackets(ifaceName); 4677 } 4678 4679 /** 4680 * Get the rx packet counts for the interface. 4681 * 4682 * @param ifaceName Name of the interface 4683 * @return rx packet counts 4684 */ 4685 public long getRxPackets(@NonNull String ifaceName) { 4686 return TrafficStats.getRxPackets(ifaceName); 4687 } 4688 4689 /** 4690 * Start sending the specified keep alive packets periodically. 4691 * 4692 * @param ifaceName Name of the interface. 4693 * @param slot Integer used to identify each request. 4694 * @param dstMac Destination MAC Address 4695 * @param packet Raw packet contents to send. 4696 * @param protocol The ethernet protocol type 4697 * @param period Period to use for sending these packets. 4698 * @return 0 for success, -1 for error 4699 */ 4700 public int startSendingOffloadedPacket(@NonNull String ifaceName, int slot, 4701 byte[] dstMac, byte[] packet, int protocol, int period) { 4702 byte[] srcMac = NativeUtil.macAddressToByteArray(getMacAddress(ifaceName)); 4703 return mWifiVendorHal.startSendingOffloadedPacket( 4704 ifaceName, slot, srcMac, dstMac, packet, protocol, period); 4705 } 4706 4707 /** 4708 * Stop sending the specified keep alive packets. 4709 * 4710 * @param ifaceName Name of the interface. 4711 * @param slot id - same as startSendingOffloadedPacket call. 4712 * @return 0 for success, -1 for error 4713 */ 4714 public int stopSendingOffloadedPacket(@NonNull String ifaceName, int slot) { 4715 return mWifiVendorHal.stopSendingOffloadedPacket(ifaceName, slot); 4716 } 4717 4718 public static interface WifiRssiEventHandler { 4719 void onRssiThresholdBreached(byte curRssi); 4720 } 4721 4722 /** 4723 * Start RSSI monitoring on the currently connected access point. 4724 * 4725 * @param ifaceName Name of the interface. 4726 * @param maxRssi Maximum RSSI threshold. 4727 * @param minRssi Minimum RSSI threshold. 4728 * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi 4729 * @return 0 for success, -1 for failure 4730 */ 4731 public int startRssiMonitoring( 4732 @NonNull String ifaceName, byte maxRssi, byte minRssi, 4733 WifiRssiEventHandler rssiEventHandler) { 4734 return mWifiVendorHal.startRssiMonitoring( 4735 ifaceName, maxRssi, minRssi, rssiEventHandler); 4736 } 4737 4738 /** 4739 * Stop RSSI monitoring on the currently connected access point. 4740 * 4741 * @param ifaceName Name of the interface. 4742 * @return 0 for success, -1 for failure 4743 */ 4744 public int stopRssiMonitoring(@NonNull String ifaceName) { 4745 return mWifiVendorHal.stopRssiMonitoring(ifaceName); 4746 } 4747 4748 /** 4749 * Fetch the host wakeup reasons stats from wlan driver. 4750 * 4751 * @return the |WlanWakeReasonAndCounts| object retrieved from the wlan driver. 4752 */ 4753 public WlanWakeReasonAndCounts getWlanWakeReasonCount() { 4754 return mWifiVendorHal.getWlanWakeReasonCount(); 4755 } 4756 4757 /** 4758 * Enable/Disable Neighbour discovery offload functionality in the firmware. 4759 * 4760 * @param ifaceName Name of the interface. 4761 * @param enabled true to enable, false to disable. 4762 * @return true for success, false otherwise. 4763 */ 4764 public boolean configureNeighborDiscoveryOffload(@NonNull String ifaceName, boolean enabled) { 4765 return mWifiVendorHal.configureNeighborDiscoveryOffload(ifaceName, enabled); 4766 } 4767 4768 // Firmware roaming control. 4769 4770 /** 4771 * Class to retrieve firmware roaming capability parameters. 4772 */ 4773 public static class RoamingCapabilities { 4774 public int maxBlocklistSize; 4775 public int maxAllowlistSize; 4776 } 4777 4778 /** 4779 * Query the firmware roaming capabilities. 4780 * @param ifaceName Name of the interface. 4781 * @return capabilities object on success, null otherwise. 4782 */ 4783 @Nullable 4784 public RoamingCapabilities getRoamingCapabilities(@NonNull String ifaceName) { 4785 return mWifiVendorHal.getRoamingCapabilities(ifaceName); 4786 } 4787 4788 /** 4789 * Macros for controlling firmware roaming. 4790 */ 4791 public static final int DISABLE_FIRMWARE_ROAMING = 0; 4792 public static final int ENABLE_FIRMWARE_ROAMING = 1; 4793 4794 @IntDef({ENABLE_FIRMWARE_ROAMING, DISABLE_FIRMWARE_ROAMING}) 4795 @Retention(RetentionPolicy.SOURCE) 4796 public @interface RoamingEnableState {} 4797 4798 /** 4799 * Indicates success for enableFirmwareRoaming 4800 */ 4801 public static final int SET_FIRMWARE_ROAMING_SUCCESS = 0; 4802 4803 /** 4804 * Indicates failure for enableFirmwareRoaming 4805 */ 4806 public static final int SET_FIRMWARE_ROAMING_FAILURE = 1; 4807 4808 /** 4809 * Indicates temporary failure for enableFirmwareRoaming - try again later 4810 */ 4811 public static final int SET_FIRMWARE_ROAMING_BUSY = 2; 4812 4813 @IntDef({SET_FIRMWARE_ROAMING_SUCCESS, SET_FIRMWARE_ROAMING_FAILURE, SET_FIRMWARE_ROAMING_BUSY}) 4814 @Retention(RetentionPolicy.SOURCE) 4815 public @interface RoamingEnableStatus {} 4816 4817 /** 4818 * Enable/disable firmware roaming. 4819 * 4820 * @param ifaceName Name of the interface. 4821 * @return SET_FIRMWARE_ROAMING_SUCCESS, SET_FIRMWARE_ROAMING_FAILURE, 4822 * or SET_FIRMWARE_ROAMING_BUSY 4823 */ 4824 public @RoamingEnableStatus int enableFirmwareRoaming(@NonNull String ifaceName, 4825 @RoamingEnableState int state) { 4826 return mWifiVendorHal.enableFirmwareRoaming(ifaceName, state); 4827 } 4828 4829 /** 4830 * Class for specifying the roaming configurations. 4831 */ 4832 public static class RoamingConfig { 4833 public ArrayList<String> blocklistBssids; 4834 public ArrayList<String> allowlistSsids; 4835 } 4836 4837 /** 4838 * Set firmware roaming configurations. 4839 * @param ifaceName Name of the interface. 4840 */ 4841 public boolean configureRoaming(@NonNull String ifaceName, RoamingConfig config) { 4842 return mWifiVendorHal.configureRoaming(ifaceName, config); 4843 } 4844 4845 /** 4846 * Reset firmware roaming configuration. 4847 * @param ifaceName Name of the interface. 4848 */ 4849 public boolean resetRoamingConfiguration(@NonNull String ifaceName) { 4850 // Pass in an empty RoamingConfig object which translates to zero size 4851 // blacklist and whitelist to reset the firmware roaming configuration. 4852 return mWifiVendorHal.configureRoaming(ifaceName, new RoamingConfig()); 4853 } 4854 4855 /** 4856 * Select one of the pre-configured transmit power level scenarios or reset it back to normal. 4857 * Primarily used for meeting SAR requirements. 4858 * 4859 * @param sarInfo The collection of inputs used to select the SAR scenario. 4860 * @return true for success; false for failure or if the HAL version does not support this API. 4861 */ 4862 public boolean selectTxPowerScenario(SarInfo sarInfo) { 4863 return mWifiVendorHal.selectTxPowerScenario(sarInfo); 4864 } 4865 4866 /** 4867 * Set MBO cellular data status 4868 * 4869 * @param ifaceName Name of the interface. 4870 * @param available cellular data status, 4871 * true means cellular data available, false otherwise. 4872 */ 4873 public void setMboCellularDataStatus(@NonNull String ifaceName, boolean available) { 4874 mSupplicantStaIfaceHal.setMboCellularDataStatus(ifaceName, available); 4875 } 4876 4877 /** 4878 * Query of support of Wi-Fi standard 4879 * 4880 * @param ifaceName name of the interface to check support on 4881 * @param standard the wifi standard to check on 4882 * @return true if the wifi standard is supported on this interface, false otherwise. 4883 */ 4884 public boolean isWifiStandardSupported(@NonNull String ifaceName, 4885 @WifiAnnotations.WifiStandard int standard) { 4886 synchronized (mLock) { 4887 Iface iface = mIfaceMgr.getIface(ifaceName); 4888 if (iface == null || iface.phyCapabilities == null) { 4889 return false; 4890 } 4891 return iface.phyCapabilities.isWifiStandardSupported(standard); 4892 } 4893 } 4894 4895 /** 4896 * Get the Wiphy capabilities of a device for a given interface 4897 * If the interface is not associated with one, 4898 * it will be read from the device through wificond 4899 * 4900 * @param ifaceName name of the interface 4901 * @return the device capabilities for this interface 4902 */ 4903 public DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String ifaceName) { 4904 return getDeviceWiphyCapabilities(ifaceName, false); 4905 } 4906 4907 /** 4908 * Get the Wiphy capabilities of a device for a given interface 4909 * If the interface is not associated with one, 4910 * it will be read from the device through wificond 4911 * 4912 * @param ifaceName name of the interface 4913 * @param isBridgedAp If the iface is bridge AP iface or not. 4914 * @return the device capabilities for this interface 4915 */ 4916 public DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String ifaceName, 4917 boolean isBridgedAp) { 4918 synchronized (mLock) { 4919 Iface iface = mIfaceMgr.getIface(ifaceName); 4920 if (iface == null) { 4921 Log.e(TAG, "Failed to get device capabilities, interface not found: " + ifaceName); 4922 return null; 4923 } 4924 if (iface.phyCapabilities == null) { 4925 if (isBridgedAp) { 4926 List<String> instances = getBridgedApInstances(ifaceName); 4927 if (instances != null && instances.size() != 0) { 4928 iface.phyCapabilities = mWifiCondManager.getDeviceWiphyCapabilities( 4929 instances.get(0)); 4930 } 4931 } else { 4932 iface.phyCapabilities = mWifiCondManager.getDeviceWiphyCapabilities(ifaceName); 4933 } 4934 } 4935 if (iface.phyCapabilities != null 4936 && iface.phyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE) 4937 != mWifiInjector.getSettingsConfigStore() 4938 .get(WifiSettingsConfigStore.WIFI_WIPHY_11BE_SUPPORTED)) { 4939 mWifiInjector.getSettingsConfigStore().put( 4940 WifiSettingsConfigStore.WIFI_WIPHY_11BE_SUPPORTED, 4941 iface.phyCapabilities.isWifiStandardSupported( 4942 ScanResult.WIFI_STANDARD_11BE)); 4943 } 4944 return iface.phyCapabilities; 4945 } 4946 } 4947 4948 /** 4949 * Set the Wiphy capabilities of a device for a given interface 4950 * 4951 * @param ifaceName name of the interface 4952 * @param capabilities the wiphy capabilities to set for this interface 4953 */ 4954 public void setDeviceWiphyCapabilities(@NonNull String ifaceName, 4955 DeviceWiphyCapabilities capabilities) { 4956 synchronized (mLock) { 4957 Iface iface = mIfaceMgr.getIface(ifaceName); 4958 if (iface == null) { 4959 Log.e(TAG, "Failed to set device capabilities, interface not found: " + ifaceName); 4960 return; 4961 } 4962 iface.phyCapabilities = capabilities; 4963 } 4964 } 4965 4966 /** 4967 * Notify scan mode state to driver to save power in scan-only mode. 4968 * 4969 * @param ifaceName Name of the interface. 4970 * @param enable whether is in scan-only mode 4971 * @return true for success 4972 */ 4973 public boolean setScanMode(String ifaceName, boolean enable) { 4974 return mWifiVendorHal.setScanMode(ifaceName, enable); 4975 } 4976 4977 /** updates linked networks of the |networkId| in supplicant if it's the current network, 4978 * if the current configured network matches |networkId|. 4979 * 4980 * @param ifaceName Name of the interface. 4981 * @param networkId network id of the network to be updated from supplicant. 4982 * @param linkedNetworks Map of config profile key and config for linking. 4983 */ 4984 public boolean updateLinkedNetworks(@NonNull String ifaceName, int networkId, 4985 Map<String, WifiConfiguration> linkedNetworks) { 4986 return mSupplicantStaIfaceHal.updateLinkedNetworks(ifaceName, networkId, linkedNetworks); 4987 } 4988 4989 /** 4990 * Start Subsystem Restart 4991 * @return true on success 4992 */ 4993 public boolean startSubsystemRestart() { 4994 return mWifiVendorHal.startSubsystemRestart(); 4995 } 4996 4997 /** 4998 * Register the provided listener for country code event. 4999 * 5000 * @param listener listener for country code changed events. 5001 */ 5002 public void registerCountryCodeEventListener(WifiCountryCode.ChangeListener listener) { 5003 registerWificondListenerIfNecessary(); 5004 if (mCountryCodeChangeListener != null) { 5005 mCountryCodeChangeListener.setChangeListener(listener); 5006 } 5007 } 5008 5009 /** 5010 * Gets the security params of the current network associated with this interface 5011 * 5012 * @param ifaceName Name of the interface 5013 * @return Security params of the current network associated with the interface 5014 */ 5015 public SecurityParams getCurrentNetworkSecurityParams(@NonNull String ifaceName) { 5016 return mSupplicantStaIfaceHal.getCurrentNetworkSecurityParams(ifaceName); 5017 } 5018 5019 /** 5020 * Check if the network-centric QoS policy feature was successfully enabled. 5021 */ 5022 public boolean isQosPolicyFeatureEnabled() { 5023 return mQosPolicyFeatureEnabled; 5024 } 5025 5026 /** 5027 * Sends a QoS policy response. 5028 * 5029 * @param ifaceName Name of the interface. 5030 * @param qosPolicyRequestId Dialog token to identify the request. 5031 * @param morePolicies Flag to indicate more QoS policies can be accommodated. 5032 * @param qosPolicyStatusList List of framework QosPolicyStatus objects. 5033 * @return true if response is sent successfully, false otherwise. 5034 */ 5035 public boolean sendQosPolicyResponse(String ifaceName, int qosPolicyRequestId, 5036 boolean morePolicies, @NonNull List<QosPolicyStatus> qosPolicyStatusList) { 5037 if (!mQosPolicyFeatureEnabled) { 5038 Log.e(TAG, "Unable to send QoS policy response, feature is not enabled"); 5039 return false; 5040 } 5041 return mSupplicantStaIfaceHal.sendQosPolicyResponse(ifaceName, qosPolicyRequestId, 5042 morePolicies, qosPolicyStatusList); 5043 } 5044 5045 /** 5046 * Indicates the removal of all active QoS policies configured by the AP. 5047 * 5048 * @param ifaceName Name of the interface. 5049 */ 5050 public boolean removeAllQosPolicies(String ifaceName) { 5051 if (!mQosPolicyFeatureEnabled) { 5052 Log.e(TAG, "Unable to remove all QoS policies, feature is not enabled"); 5053 return false; 5054 } 5055 return mSupplicantStaIfaceHal.removeAllQosPolicies(ifaceName); 5056 } 5057 5058 /** 5059 * Send a set of QoS SCS policy add requests to the AP. 5060 * 5061 * Immediate response will indicate which policies were sent to the AP, and which were 5062 * rejected immediately by the supplicant. If any requests were sent to the AP, the AP's 5063 * response will arrive later in the onQosPolicyResponseForScs callback. 5064 * 5065 * @param ifaceName Name of the interface. 5066 * @param policies List of policies that the caller is requesting to add. 5067 * @return List of responses for each policy in the request, or null if an error occurred. 5068 * Status code will be one of 5069 * {@link SupplicantStaIfaceHal.QosPolicyScsRequestStatusCode}. 5070 */ 5071 List<SupplicantStaIfaceHal.QosPolicyStatus> addQosPolicyRequestForScs( 5072 @NonNull String ifaceName, @NonNull List<QosPolicyParams> policies) { 5073 return mSupplicantStaIfaceHal.addQosPolicyRequestForScs(ifaceName, policies); 5074 } 5075 5076 /** 5077 * Request the removal of specific QoS policies for SCS. 5078 * 5079 * Immediate response will indicate which policies were sent to the AP, and which were 5080 * rejected immediately by the supplicant. If any requests were sent to the AP, the AP's 5081 * response will arrive later in the onQosPolicyResponseForScs callback. 5082 * 5083 * @param ifaceName Name of the interface. 5084 * @param policyIds List of policy IDs for policies that should be removed. 5085 * @return List of responses for each policy in the request, or null if an error occurred. 5086 * Status code will be one of 5087 * {@link SupplicantStaIfaceHal.QosPolicyScsRequestStatusCode}. 5088 */ 5089 List<SupplicantStaIfaceHal.QosPolicyStatus> removeQosPolicyForScs( 5090 @NonNull String ifaceName, @NonNull List<Byte> policyIds) { 5091 return mSupplicantStaIfaceHal.removeQosPolicyForScs(ifaceName, policyIds); 5092 } 5093 5094 /** 5095 * Register a callback to receive notifications for QoS SCS transactions. 5096 * Callback should only be registered once. 5097 * 5098 * @param callback {@link SupplicantStaIfaceHal.QosScsResponseCallback} to register. 5099 */ 5100 public void registerQosScsResponseCallback( 5101 @NonNull SupplicantStaIfaceHal.QosScsResponseCallback callback) { 5102 mSupplicantStaIfaceHal.registerQosScsResponseCallback(callback); 5103 } 5104 5105 /** 5106 * Generate DPP credential for network access 5107 * 5108 * @param ifaceName Name of the interface. 5109 * @param ssid ssid of the network 5110 * @param privEcKey Private EC Key for DPP Configurator 5111 * Returns true when operation is successful. On error, false is returned. 5112 */ 5113 public boolean generateSelfDppConfiguration(@NonNull String ifaceName, @NonNull String ssid, 5114 byte[] privEcKey) { 5115 return mSupplicantStaIfaceHal.generateSelfDppConfiguration(ifaceName, ssid, privEcKey); 5116 } 5117 5118 /** 5119 * This set anonymous identity to supplicant. 5120 * 5121 * @param ifaceName Name of the interface. 5122 * @param anonymousIdentity the anonymouns identity. 5123 * @param updateToNativeService write the data to the native service. 5124 * @return true if succeeds, false otherwise. 5125 */ 5126 public boolean setEapAnonymousIdentity(@NonNull String ifaceName, String anonymousIdentity, 5127 boolean updateToNativeService) { 5128 if (null == anonymousIdentity) { 5129 Log.e(TAG, "Cannot set null anonymous identity."); 5130 return false; 5131 } 5132 return mSupplicantStaIfaceHal.setEapAnonymousIdentity(ifaceName, anonymousIdentity, 5133 updateToNativeService); 5134 } 5135 5136 /** 5137 * Notify wificond daemon of country code have changed. 5138 */ 5139 public void countryCodeChanged(String countryCode) { 5140 if (SdkLevel.isAtLeastT()) { 5141 try { 5142 mWifiCondManager.notifyCountryCodeChanged(countryCode); 5143 } catch (RuntimeException re) { 5144 Log.e(TAG, "Fail to notify wificond country code changed to " + countryCode 5145 + "because exception happened:" + re); 5146 } 5147 } 5148 } 5149 5150 /** 5151 * Return the maximum number of concurrent TDLS sessions supported by the device. 5152 * @return -1 if the information is not available on the device 5153 */ 5154 public int getMaxSupportedConcurrentTdlsSessions(@NonNull String ifaceName) { 5155 return mWifiVendorHal.getMaxSupportedConcurrentTdlsSessions(ifaceName); 5156 } 5157 5158 /** 5159 * Save the complete list of features retrieved from WiFi HAL and Supplicant HAL in 5160 * config store. 5161 */ 5162 private void saveCompleteFeatureSetInConfigStoreIfNecessary(long featureSet) { 5163 long cachedFeatureSet = getCompleteFeatureSetFromConfigStore(); 5164 if (cachedFeatureSet != featureSet) { 5165 mCachedFeatureSet = featureSet; 5166 mWifiInjector.getSettingsConfigStore() 5167 .put(WIFI_NATIVE_SUPPORTED_FEATURES, mCachedFeatureSet); 5168 Log.i(TAG, "Supported features is updated in config store: " + mCachedFeatureSet); 5169 } 5170 } 5171 5172 /** 5173 * Get the feature set from cache/config store 5174 */ 5175 private long getCompleteFeatureSetFromConfigStore() { 5176 if (mCachedFeatureSet == 0) { 5177 mCachedFeatureSet = mWifiInjector.getSettingsConfigStore() 5178 .get(WIFI_NATIVE_SUPPORTED_FEATURES); 5179 } 5180 return mCachedFeatureSet; 5181 } 5182 5183 /** 5184 * Returns whether or not the hostapd HAL supports reporting single instance died event. 5185 */ 5186 public boolean isSoftApInstanceDiedHandlerSupported() { 5187 return mHostapdHal.isSoftApInstanceDiedHandlerSupported(); 5188 } 5189 5190 /** Checks if there are any STA (for connectivity) iface active. */ 5191 @VisibleForTesting 5192 boolean hasAnyStaIfaceForConnectivity() { 5193 return mIfaceMgr.hasAnyStaIfaceForConnectivity(); 5194 } 5195 5196 /** Checks if there are any STA (for scan) iface active. */ 5197 @VisibleForTesting 5198 boolean hasAnyStaIfaceForScan() { 5199 return mIfaceMgr.hasAnyStaIfaceForScan(); 5200 } 5201 5202 /** Checks if there are any AP iface active. */ 5203 @VisibleForTesting 5204 boolean hasAnyApIface() { 5205 return mIfaceMgr.hasAnyApIface(); 5206 } 5207 5208 /** Checks if there are any iface active. */ 5209 @VisibleForTesting 5210 boolean hasAnyIface() { 5211 return mIfaceMgr.hasAnyIface(); 5212 } 5213 5214 /** Checks if there are any P2P iface active. */ 5215 @VisibleForTesting 5216 boolean hasAnyP2pIface() { 5217 return mIfaceMgr.hasAnyP2pIface(); 5218 } 5219 5220 /** 5221 * Sets or clean mock wifi service 5222 * 5223 * @param serviceName the service name of mock wifi service. When service name is empty, the 5224 * framework will clean mock wifi service. 5225 */ 5226 public void setMockWifiService(String serviceName) { 5227 Log.d(TAG, "set MockWifiModemService to " + serviceName); 5228 if (TextUtils.isEmpty(serviceName)) { 5229 mMockWifiModem.unbindMockModemService(); 5230 mMockWifiModem = null; 5231 mWifiInjector.setMockWifiServiceUtil(null); 5232 return; 5233 } 5234 mMockWifiModem = new MockWifiServiceUtil(mContext, serviceName, mWifiMonitor); 5235 mWifiInjector.setMockWifiServiceUtil(mMockWifiModem); 5236 if (mMockWifiModem == null) { 5237 Log.e(TAG, "MockWifiServiceUtil creation failed."); 5238 return; 5239 } 5240 5241 // mock wifi modem service is set, try to bind all supported mock HAL services 5242 mMockWifiModem.bindAllMockModemService(); 5243 for (int service = MockWifiServiceUtil.MIN_SERVICE_IDX; 5244 service < MockWifiServiceUtil.NUM_SERVICES; service++) { 5245 int retryCount = 0; 5246 IBinder binder; 5247 do { 5248 binder = mMockWifiModem.getServiceBinder(service); 5249 retryCount++; 5250 if (binder == null) { 5251 Log.d(TAG, "Retry(" + retryCount + ") for " 5252 + mMockWifiModem.getModuleName(service)); 5253 try { 5254 Thread.sleep(MockWifiServiceUtil.BINDER_RETRY_MILLIS); 5255 } catch (InterruptedException e) { 5256 } 5257 } 5258 } while ((binder == null) && (retryCount < MockWifiServiceUtil.BINDER_MAX_RETRY)); 5259 5260 if (binder == null) { 5261 Log.e(TAG, "Mock " + mMockWifiModem.getModuleName(service) + " bind fail"); 5262 } 5263 } 5264 } 5265 5266 /** 5267 * Returns mock wifi service name. 5268 */ 5269 public String getMockWifiServiceName() { 5270 String serviceName = mMockWifiModem != null ? mMockWifiModem.getServiceName() : null; 5271 Log.d(TAG, "getMockWifiServiceName - service name is " + serviceName); 5272 return serviceName; 5273 } 5274 5275 /** 5276 * Sets mocked methods which like to be called. 5277 * 5278 * @param methods the methods string with formats HAL name - method name, ... 5279 */ 5280 public boolean setMockWifiMethods(String methods) { 5281 if (mMockWifiModem == null || methods == null) { 5282 return false; 5283 } 5284 return mMockWifiModem.setMockedMethods(methods); 5285 } 5286 5287 /** 5288 * Set maximum acceptable DTIM multiplier to hardware driver. Any multiplier larger than the 5289 * maximum value must not be accepted, it will cause packet loss higher than what the system 5290 * can accept, which will cause unexpected behavior for apps, and may interrupt the network 5291 * connection. 5292 * 5293 * @param ifaceName Name of the interface. 5294 * @param multiplier integer maximum DTIM multiplier value to set. 5295 * @return true for success 5296 */ 5297 public boolean setDtimMultiplier(String ifaceName, int multiplier) { 5298 return mWifiVendorHal.setDtimMultiplier(ifaceName, multiplier); 5299 } 5300 5301 /** 5302 * Set Multi-Link Operation mode. 5303 * 5304 * @param mode Multi-Link Operation mode {@link android.net.wifi.WifiManager.MloMode}. 5305 * @return {@link WifiStatusCode#SUCCESS} if success, otherwise error code. 5306 */ 5307 public @WifiStatusCode int setMloMode(@WifiManager.MloMode int mode) { 5308 @WifiStatusCode int errorCode = mWifiVendorHal.setMloMode(mode); 5309 // If set is success, cache it. 5310 if (errorCode == WifiStatusCode.SUCCESS) mCachedMloMode = mode; 5311 return errorCode; 5312 } 5313 5314 /** 5315 * Get Multi-Link Operation mode. 5316 * 5317 * @return Current Multi-Link Operation mode {@link android.net.wifi.WifiManager.MloMode}. 5318 */ 5319 public @WifiManager.MloMode int getMloMode() { 5320 return mCachedMloMode; 5321 } 5322 5323 /** 5324 * Get the maximum number of links supported by the chip for MLO association. 5325 * 5326 * e.g. if the chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous 5327 * Transmit and Receive) with following capabilities, 5328 * - Maximum MLO association link count = 3 5329 * - Maximum MLO STR link count = 2 See {@link WifiNative#getMaxMloStrLinkCount(String)} 5330 * One of the possible configuration is - STR (2.4 , eMLSR(5, 6)), provided the radio 5331 * combination of the chip supports it. 5332 * 5333 * Note: This is an input to MLO aware network scoring logic to predict maximum multi-link 5334 * throughput. 5335 * 5336 * @param ifaceName Name of the interface. 5337 * @return maximum number of association links or -1 if error or not available. 5338 */ 5339 public int getMaxMloAssociationLinkCount(@NonNull String ifaceName) { 5340 return mWifiVendorHal.getMaxMloAssociationLinkCount(ifaceName); 5341 } 5342 5343 /** 5344 * Get the maximum number of STR links used in Multi-Link Operation. The maximum number of STR 5345 * links used for MLO can be different from the number of radios supported by the chip. 5346 * 5347 * e.g. if the chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous 5348 * Transmit and Receive) with following capabilities, 5349 * - Maximum MLO association link count = 3 5350 * See {@link WifiNative#getMaxMloAssociationLinkCount(String)} 5351 * - Maximum MLO STR link count = 2 5352 * One of the possible configuration is - STR (2.4, eMLSR(5, 6)), provided the radio 5353 * combination of the chip supports it. 5354 * 5355 * Note: This is an input to MLO aware network scoring logic to predict maximum multi-link 5356 * throughput. 5357 * 5358 * @param ifaceName Name of the interface. 5359 * @return maximum number of MLO STR links or -1 if error or not available. 5360 */ 5361 public int getMaxMloStrLinkCount(@NonNull String ifaceName) { 5362 return mWifiVendorHal.getMaxMloStrLinkCount(ifaceName); 5363 } 5364 5365 /** 5366 * Check the given band combination is supported simultaneously by the Wi-Fi chip. 5367 * 5368 * Note: This method is for checking simultaneous band operations and not for multichannel 5369 * concurrent operation (MCC). 5370 * 5371 * @param ifaceName Name of the interface. 5372 * @param bands A list of bands in the combination. See {@link WifiScanner.WifiBand} 5373 * for the band enums. List of bands can be in any order. 5374 * @return true if the provided band combination is supported by the chip, otherwise false. 5375 */ 5376 public boolean isBandCombinationSupported(@NonNull String ifaceName, List<Integer> bands) { 5377 return mWifiVendorHal.isBandCombinationSupported(ifaceName, bands); 5378 } 5379 5380 /** 5381 * Get the set of band combinations supported simultaneously by the Wi-Fi Chip. 5382 * 5383 * Note: This method returns simultaneous band operation combination and not multichannel 5384 * concurrent operation (MCC) combination. 5385 * 5386 * @param ifaceName Name of the interface. 5387 * @return An unmodifiable set of supported band combinations. 5388 */ 5389 public Set<List<Integer>> getSupportedBandCombinations(@NonNull String ifaceName) { 5390 return mWifiVendorHal.getSupportedBandCombinations(ifaceName); 5391 } 5392 5393 /** 5394 * Sends the AFC allowed channels and frequencies to the driver. 5395 * 5396 * @param afcChannelAllowance the allowed frequencies and channels received from 5397 * querying the AFC server. 5398 * @return whether the channel allowance was set successfully. 5399 */ 5400 public boolean setAfcChannelAllowance(WifiChip.AfcChannelAllowance afcChannelAllowance) { 5401 return mWifiVendorHal.setAfcChannelAllowance(afcChannelAllowance); 5402 } 5403 5404 /** 5405 * Enable Mirrored Stream Classification Service (MSCS) and configure using 5406 * the provided configuration values. 5407 * 5408 * @param mscsParams {@link MscsParams} object containing the configuration parameters. 5409 * @param ifaceName Name of the interface. 5410 */ 5411 public void enableMscs(@NonNull MscsParams mscsParams, String ifaceName) { 5412 mSupplicantStaIfaceHal.enableMscs(mscsParams, ifaceName); 5413 } 5414 5415 /** 5416 * Resend the previously configured MSCS parameters on this interface, if any exist. 5417 * 5418 * @param ifaceName Name of the interface. 5419 */ 5420 public void resendMscs(String ifaceName) { 5421 mSupplicantStaIfaceHal.resendMscs(ifaceName); 5422 } 5423 5424 /** 5425 * Disable Mirrored Stream Classification Service (MSCS). 5426 * 5427 * @param ifaceName Name of the interface. 5428 */ 5429 public void disableMscs(String ifaceName) { 5430 mSupplicantStaIfaceHal.disableMscs(ifaceName); 5431 } 5432 5433 /** 5434 * Set the roaming mode value. 5435 * 5436 * @param ifaceName Name of the interface. 5437 * @param roamingMode {@link android.net.wifi.WifiManager.RoamingMode}. 5438 * @return {@link WifiStatusCode#SUCCESS} if success, otherwise error code. 5439 */ 5440 public @WifiStatusCode int setRoamingMode(@NonNull String ifaceName, 5441 @RoamingMode int roamingMode) { 5442 return mWifiVendorHal.setRoamingMode(ifaceName, roamingMode); 5443 } 5444 5445 /* 5446 * TWT callback events 5447 */ 5448 public interface WifiTwtEvents { 5449 /** 5450 * Called when a TWT operation fails 5451 * 5452 * @param cmdId Unique command id. 5453 * @param twtErrorCode Error code 5454 */ 5455 void onTwtFailure(int cmdId, @TwtSessionCallback.TwtErrorCode int twtErrorCode); 5456 5457 /** 5458 * Called when {@link #setupTwtSession(int, String, TwtRequest)} succeeds. 5459 * 5460 * @param cmdId Unique command id used in {@link #setupTwtSession(int, String, TwtRequest)} 5461 * @param wakeDurationUs TWT wake duration for the session in microseconds 5462 * @param wakeIntervalUs TWT wake interval for the session in microseconds 5463 * @param linkId Multi link operation link id 5464 * @param sessionId TWT session id 5465 */ 5466 void onTwtSessionCreate(int cmdId, int wakeDurationUs, long wakeIntervalUs, int linkId, 5467 int sessionId); 5468 /** 5469 * Called when TWT session is torn down by {@link #tearDownTwtSession(int, String, int)}. 5470 * Can also be called unsolicitedly by the vendor software with proper reason code. 5471 * 5472 * @param cmdId Unique command id used in {@link #tearDownTwtSession(int, String, int)} 5473 * @param twtSessionId TWT session Id 5474 * @param twtReasonCode Reason code for teardown 5475 */ 5476 void onTwtSessionTeardown(int cmdId, int twtSessionId, 5477 @TwtSessionCallback.TwtReasonCode int twtReasonCode); 5478 5479 /** 5480 * Called as a response to {@link #getStatsTwtSession(int, String, int)} 5481 * 5482 * @param cmdId Unique command id used in {@link #getStatsTwtSession(int, String, int)} 5483 * @param twtSessionId TWT session Id 5484 * @param twtStats TWT stats object 5485 */ 5486 void onTwtSessionStats(int cmdId, int twtSessionId, Bundle twtStats); 5487 } 5488 5489 5490 /** 5491 * Sets up a TWT session for the interface 5492 * 5493 * @param commandId A unique command id to identify this command 5494 * @param interfaceName Interface name 5495 * @param twtRequest TWT request parameters 5496 * @return true if successful, otherwise false 5497 */ 5498 public boolean setupTwtSession(int commandId, String interfaceName, TwtRequest twtRequest) { 5499 return mWifiVendorHal.setupTwtSession(commandId, interfaceName, twtRequest); 5500 } 5501 5502 /** 5503 * Registers TWT callbacks 5504 * 5505 * @param wifiTwtCallback TWT callbacks 5506 */ 5507 public void registerTwtCallbacks(WifiTwtEvents wifiTwtCallback) { 5508 mWifiVendorHal.registerTwtCallbacks(wifiTwtCallback); 5509 } 5510 5511 /** 5512 * Teardown the TWT session 5513 * 5514 * @param commandId A unique command id to identify this command 5515 * @param interfaceName Interface name 5516 * @param sessionId TWT session id 5517 * @return true if successful, otherwise false 5518 */ 5519 public boolean tearDownTwtSession(int commandId, String interfaceName, int sessionId) { 5520 return mWifiVendorHal.tearDownTwtSession(commandId, interfaceName, sessionId); 5521 } 5522 5523 /** 5524 * Gets stats of the TWT session 5525 * 5526 * @param commandId A unique command id to identify this command 5527 * @param interfaceName Interface name 5528 * @param sessionId TWT session id 5529 * @return true if successful, otherwise false 5530 */ 5531 public boolean getStatsTwtSession(int commandId, String interfaceName, int sessionId) { 5532 return mWifiVendorHal.getStatsTwtSession(commandId, interfaceName, sessionId); 5533 } 5534 5535 /** 5536 * Sets the wifi VoIP mode. 5537 * 5538 * @param mode Voip mode as defined by the enum |WifiVoipMode| 5539 * @return true if successful, false otherwise. 5540 */ 5541 public boolean setVoipMode(@WifiChip.WifiVoipMode int mode) { 5542 return mWifiVendorHal.setVoipMode(mode); 5543 } 5544 } 5545