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