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