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 android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.net.InterfaceConfiguration; 22 import android.net.MacAddress; 23 import android.net.TrafficStats; 24 import android.net.apf.ApfCapabilities; 25 import android.net.wifi.ScanResult; 26 import android.net.wifi.WifiConfiguration; 27 import android.net.wifi.WifiScanner; 28 import android.os.Handler; 29 import android.os.INetworkManagementService; 30 import android.os.RemoteException; 31 import android.os.SystemClock; 32 import android.text.TextUtils; 33 import android.util.Log; 34 import android.util.SparseArray; 35 36 import com.android.internal.annotations.Immutable; 37 import com.android.internal.util.HexDump; 38 import com.android.server.net.BaseNetworkObserver; 39 import com.android.server.wifi.util.FrameParser; 40 import com.android.server.wifi.util.NativeUtil; 41 import com.android.server.wifi.wificond.NativeWifiClient; 42 43 import java.io.PrintWriter; 44 import java.io.StringWriter; 45 import java.lang.annotation.Retention; 46 import java.lang.annotation.RetentionPolicy; 47 import java.nio.ByteBuffer; 48 import java.nio.ByteOrder; 49 import java.nio.CharBuffer; 50 import java.nio.charset.CharacterCodingException; 51 import java.nio.charset.CharsetDecoder; 52 import java.nio.charset.StandardCharsets; 53 import java.text.SimpleDateFormat; 54 import java.util.ArrayList; 55 import java.util.Arrays; 56 import java.util.Date; 57 import java.util.HashMap; 58 import java.util.HashSet; 59 import java.util.Iterator; 60 import java.util.List; 61 import java.util.Map; 62 import java.util.Objects; 63 import java.util.Random; 64 import java.util.Set; 65 import java.util.TimeZone; 66 67 /** 68 * Native calls for bring up/shut down of the supplicant daemon and for 69 * sending requests to the supplicant daemon 70 * 71 * {@hide} 72 */ 73 public class WifiNative { 74 private static final String TAG = "WifiNative"; 75 private final SupplicantStaIfaceHal mSupplicantStaIfaceHal; 76 private final HostapdHal mHostapdHal; 77 private final WifiVendorHal mWifiVendorHal; 78 private final WificondControl mWificondControl; 79 private final WifiMonitor mWifiMonitor; 80 private final INetworkManagementService mNwManagementService; 81 private final PropertyService mPropertyService; 82 private final WifiMetrics mWifiMetrics; 83 private final Handler mHandler; 84 private final Random mRandom; 85 private boolean mVerboseLoggingEnabled = false; 86 WifiNative(WifiVendorHal vendorHal, SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal, WificondControl condControl, WifiMonitor wifiMonitor, INetworkManagementService nwService, PropertyService propertyService, WifiMetrics wifiMetrics, Handler handler, Random random)87 public WifiNative(WifiVendorHal vendorHal, 88 SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal, 89 WificondControl condControl, WifiMonitor wifiMonitor, 90 INetworkManagementService nwService, 91 PropertyService propertyService, WifiMetrics wifiMetrics, 92 Handler handler, Random random) { 93 mWifiVendorHal = vendorHal; 94 mSupplicantStaIfaceHal = staIfaceHal; 95 mHostapdHal = hostapdHal; 96 mWificondControl = condControl; 97 mWifiMonitor = wifiMonitor; 98 mNwManagementService = nwService; 99 mPropertyService = propertyService; 100 mWifiMetrics = wifiMetrics; 101 mHandler = handler; 102 mRandom = random; 103 } 104 105 /** 106 * Enable verbose logging for all sub modules. 107 */ enableVerboseLogging(int verbose)108 public void enableVerboseLogging(int verbose) { 109 mVerboseLoggingEnabled = verbose > 0 ? true : false; 110 mWificondControl.enableVerboseLogging(mVerboseLoggingEnabled); 111 mSupplicantStaIfaceHal.enableVerboseLogging(mVerboseLoggingEnabled); 112 mWifiVendorHal.enableVerboseLogging(mVerboseLoggingEnabled); 113 } 114 115 /******************************************************** 116 * Interface management related methods. 117 ********************************************************/ 118 /** 119 * Meta-info about every iface that is active. 120 */ 121 private static class Iface { 122 /** Type of ifaces possible */ 123 public static final int IFACE_TYPE_AP = 0; 124 public static final int IFACE_TYPE_STA_FOR_CONNECTIVITY = 1; 125 public static final int IFACE_TYPE_STA_FOR_SCAN = 2; 126 127 @IntDef({IFACE_TYPE_AP, IFACE_TYPE_STA_FOR_CONNECTIVITY, IFACE_TYPE_STA_FOR_SCAN}) 128 @Retention(RetentionPolicy.SOURCE) 129 public @interface IfaceType{} 130 131 /** Identifier allocated for the interface */ 132 public final int id; 133 /** Type of the iface: STA (for Connectivity or Scan) or AP */ 134 public final @IfaceType int type; 135 /** Name of the interface */ 136 public String name; 137 /** Is the interface up? This is used to mask up/down notifications to external clients. */ 138 public boolean isUp; 139 /** External iface destroyed listener for the iface */ 140 public InterfaceCallback externalListener; 141 /** Network observer registered for this interface */ 142 public NetworkObserverInternal networkObserver; 143 /** Interface feature set / capabilities */ 144 public long featureSet; 145 Iface(int id, @Iface.IfaceType int type)146 Iface(int id, @Iface.IfaceType int type) { 147 this.id = id; 148 this.type = type; 149 } 150 151 @Override toString()152 public String toString() { 153 StringBuffer sb = new StringBuffer(); 154 String typeString; 155 switch(type) { 156 case IFACE_TYPE_STA_FOR_CONNECTIVITY: 157 typeString = "STA_CONNECTIVITY"; 158 break; 159 case IFACE_TYPE_STA_FOR_SCAN: 160 typeString = "STA_SCAN"; 161 break; 162 case IFACE_TYPE_AP: 163 typeString = "AP"; 164 break; 165 default: 166 typeString = "<UNKNOWN>"; 167 break; 168 } 169 sb.append("Iface:") 170 .append("{") 171 .append("Name=").append(name) 172 .append(",") 173 .append("Id=").append(id) 174 .append(",") 175 .append("Type=").append(typeString) 176 .append("}"); 177 return sb.toString(); 178 } 179 } 180 181 /** 182 * Iface Management entity. This class maintains list of all the active ifaces. 183 */ 184 private static class IfaceManager { 185 /** Integer to allocate for the next iface being created */ 186 private int mNextId; 187 /** Map of the id to the iface structure */ 188 private HashMap<Integer, Iface> mIfaces = new HashMap<>(); 189 190 /** Allocate a new iface for the given type */ allocateIface(@face.IfaceType int type)191 private Iface allocateIface(@Iface.IfaceType int type) { 192 Iface iface = new Iface(mNextId, type); 193 mIfaces.put(mNextId, iface); 194 mNextId++; 195 return iface; 196 } 197 198 /** Remove the iface using the provided id */ removeIface(int id)199 private Iface removeIface(int id) { 200 return mIfaces.remove(id); 201 } 202 203 /** Lookup the iface using the provided id */ getIface(int id)204 private Iface getIface(int id) { 205 return mIfaces.get(id); 206 } 207 208 /** Lookup the iface using the provided name */ getIface(@onNull String ifaceName)209 private Iface getIface(@NonNull String ifaceName) { 210 for (Iface iface : mIfaces.values()) { 211 if (TextUtils.equals(iface.name, ifaceName)) { 212 return iface; 213 } 214 } 215 return null; 216 } 217 218 /** Iterator to use for deleting all the ifaces while performing teardown on each of them */ getIfaceIdIter()219 private Iterator<Integer> getIfaceIdIter() { 220 return mIfaces.keySet().iterator(); 221 } 222 223 /** Checks if there are any iface active. */ hasAnyIface()224 private boolean hasAnyIface() { 225 return !mIfaces.isEmpty(); 226 } 227 228 /** Checks if there are any iface of the given type active. */ hasAnyIfaceOfType(@face.IfaceType int type)229 private boolean hasAnyIfaceOfType(@Iface.IfaceType int type) { 230 for (Iface iface : mIfaces.values()) { 231 if (iface.type == type) { 232 return true; 233 } 234 } 235 return false; 236 } 237 238 /** Checks if there are any iface of the given type active. */ findAnyIfaceOfType(@face.IfaceType int type)239 private Iface findAnyIfaceOfType(@Iface.IfaceType int type) { 240 for (Iface iface : mIfaces.values()) { 241 if (iface.type == type) { 242 return iface; 243 } 244 } 245 return null; 246 } 247 248 /** Checks if there are any STA (for connectivity) iface active. */ hasAnyStaIfaceForConnectivity()249 private boolean hasAnyStaIfaceForConnectivity() { 250 return hasAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY); 251 } 252 253 /** Checks if there are any STA (for scan) iface active. */ hasAnyStaIfaceForScan()254 private boolean hasAnyStaIfaceForScan() { 255 return hasAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_SCAN); 256 } 257 258 /** Checks if there are any AP iface active. */ hasAnyApIface()259 private boolean hasAnyApIface() { 260 return hasAnyIfaceOfType(Iface.IFACE_TYPE_AP); 261 } 262 263 /** Finds the name of any STA iface active. */ findAnyStaIfaceName()264 private String findAnyStaIfaceName() { 265 Iface iface = findAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY); 266 if (iface == null) { 267 iface = findAnyIfaceOfType(Iface.IFACE_TYPE_STA_FOR_SCAN); 268 } 269 if (iface == null) { 270 return null; 271 } 272 return iface.name; 273 } 274 275 /** Finds the name of any AP iface active. */ findAnyApIfaceName()276 private String findAnyApIfaceName() { 277 Iface iface = findAnyIfaceOfType(Iface.IFACE_TYPE_AP); 278 if (iface == null) { 279 return null; 280 } 281 return iface.name; 282 } 283 284 /** Removes the existing iface that does not match the provided id. */ removeExistingIface(int newIfaceId)285 public Iface removeExistingIface(int newIfaceId) { 286 Iface removedIface = null; 287 // The number of ifaces in the database could be 1 existing & 1 new at the max. 288 if (mIfaces.size() > 2) { 289 Log.wtf(TAG, "More than 1 existing interface found"); 290 } 291 Iterator<Map.Entry<Integer, Iface>> iter = mIfaces.entrySet().iterator(); 292 while (iter.hasNext()) { 293 Map.Entry<Integer, Iface> entry = iter.next(); 294 if (entry.getKey() != newIfaceId) { 295 removedIface = entry.getValue(); 296 iter.remove(); 297 } 298 } 299 return removedIface; 300 } 301 } 302 303 private Object mLock = new Object(); 304 private final IfaceManager mIfaceMgr = new IfaceManager(); 305 private HashSet<StatusListener> mStatusListeners = new HashSet<>(); 306 307 /** Helper method invoked to start supplicant if there were no ifaces */ startHal()308 private boolean startHal() { 309 synchronized (mLock) { 310 if (!mIfaceMgr.hasAnyIface()) { 311 if (mWifiVendorHal.isVendorHalSupported()) { 312 if (!mWifiVendorHal.startVendorHal()) { 313 Log.e(TAG, "Failed to start vendor HAL"); 314 return false; 315 } 316 } else { 317 Log.i(TAG, "Vendor Hal not supported, ignoring start."); 318 } 319 } 320 return true; 321 } 322 } 323 324 /** Helper method invoked to stop HAL if there are no more ifaces */ stopHalAndWificondIfNecessary()325 private void stopHalAndWificondIfNecessary() { 326 synchronized (mLock) { 327 if (!mIfaceMgr.hasAnyIface()) { 328 if (!mWificondControl.tearDownInterfaces()) { 329 Log.e(TAG, "Failed to teardown ifaces from wificond"); 330 } 331 if (mWifiVendorHal.isVendorHalSupported()) { 332 mWifiVendorHal.stopVendorHal(); 333 } else { 334 Log.i(TAG, "Vendor Hal not supported, ignoring stop."); 335 } 336 } 337 } 338 } 339 340 private static final int CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS = 100; 341 private static final int CONNECT_TO_SUPPLICANT_RETRY_TIMES = 50; 342 /** 343 * This method is called to wait for establishing connection to wpa_supplicant. 344 * 345 * @return true if connection is established, false otherwise. 346 */ startAndWaitForSupplicantConnection()347 private boolean startAndWaitForSupplicantConnection() { 348 // Start initialization if not already started. 349 if (!mSupplicantStaIfaceHal.isInitializationStarted() 350 && !mSupplicantStaIfaceHal.initialize()) { 351 return false; 352 } 353 if (!mSupplicantStaIfaceHal.startDaemon()) { 354 Log.e(TAG, "Failed to startup supplicant"); 355 return false; 356 } 357 boolean connected = false; 358 int connectTries = 0; 359 while (!connected && connectTries++ < CONNECT_TO_SUPPLICANT_RETRY_TIMES) { 360 // Check if the initialization is complete. 361 connected = mSupplicantStaIfaceHal.isInitializationComplete(); 362 if (connected) { 363 break; 364 } 365 try { 366 Thread.sleep(CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS); 367 } catch (InterruptedException ignore) { 368 } 369 } 370 return connected; 371 } 372 373 /** Helper method invoked to start supplicant if there were no STA ifaces */ startSupplicant()374 private boolean startSupplicant() { 375 synchronized (mLock) { 376 if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) { 377 if (!startAndWaitForSupplicantConnection()) { 378 Log.e(TAG, "Failed to connect to supplicant"); 379 return false; 380 } 381 if (!mSupplicantStaIfaceHal.registerDeathHandler( 382 new SupplicantDeathHandlerInternal())) { 383 Log.e(TAG, "Failed to register supplicant death handler"); 384 return false; 385 } 386 } 387 return true; 388 } 389 } 390 391 /** Helper method invoked to stop supplicant if there are no more STA ifaces */ stopSupplicantIfNecessary()392 private void stopSupplicantIfNecessary() { 393 synchronized (mLock) { 394 if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) { 395 if (!mSupplicantStaIfaceHal.deregisterDeathHandler()) { 396 Log.e(TAG, "Failed to deregister supplicant death handler"); 397 } 398 mSupplicantStaIfaceHal.terminate(); 399 } 400 } 401 } 402 403 /** Helper method invoked to start hostapd if there were no AP ifaces */ startHostapd()404 private boolean startHostapd() { 405 synchronized (mLock) { 406 if (!mIfaceMgr.hasAnyApIface()) { 407 if (!startAndWaitForHostapdConnection()) { 408 Log.e(TAG, "Failed to connect to hostapd"); 409 return false; 410 } 411 if (!mHostapdHal.registerDeathHandler( 412 new HostapdDeathHandlerInternal())) { 413 Log.e(TAG, "Failed to register hostapd death handler"); 414 return false; 415 } 416 } 417 return true; 418 } 419 } 420 421 /** Helper method invoked to stop hostapd if there are no more AP ifaces */ stopHostapdIfNecessary()422 private void stopHostapdIfNecessary() { 423 synchronized (mLock) { 424 if (!mIfaceMgr.hasAnyApIface()) { 425 if (!mHostapdHal.deregisterDeathHandler()) { 426 Log.e(TAG, "Failed to deregister hostapd death handler"); 427 } 428 mHostapdHal.terminate(); 429 } 430 } 431 } 432 433 /** Helper method to register a network observer and return it */ registerNetworkObserver(NetworkObserverInternal observer)434 private boolean registerNetworkObserver(NetworkObserverInternal observer) { 435 if (observer == null) return false; 436 try { 437 mNwManagementService.registerObserver(observer); 438 } catch (RemoteException | IllegalStateException e) { 439 Log.e(TAG, "Unable to register observer", e); 440 return false; 441 } 442 return true; 443 } 444 445 /** Helper method to unregister a network observer */ unregisterNetworkObserver(NetworkObserverInternal observer)446 private boolean unregisterNetworkObserver(NetworkObserverInternal observer) { 447 if (observer == null) return false; 448 try { 449 mNwManagementService.unregisterObserver(observer); 450 } catch (RemoteException | IllegalStateException e) { 451 Log.e(TAG, "Unable to unregister observer", e); 452 return false; 453 } 454 return true; 455 } 456 457 /** 458 * Helper method invoked to teardown client iface (for connectivity) and perform 459 * necessary cleanup 460 */ onClientInterfaceForConnectivityDestroyed(@onNull Iface iface)461 private void onClientInterfaceForConnectivityDestroyed(@NonNull Iface iface) { 462 synchronized (mLock) { 463 mWifiMonitor.stopMonitoring(iface.name); 464 if (!unregisterNetworkObserver(iface.networkObserver)) { 465 Log.e(TAG, "Failed to unregister network observer on " + iface); 466 } 467 if (!mSupplicantStaIfaceHal.teardownIface(iface.name)) { 468 Log.e(TAG, "Failed to teardown iface in supplicant on " + iface); 469 } 470 if (!mWificondControl.tearDownClientInterface(iface.name)) { 471 Log.e(TAG, "Failed to teardown iface in wificond on " + iface); 472 } 473 stopSupplicantIfNecessary(); 474 stopHalAndWificondIfNecessary(); 475 } 476 } 477 478 /** Helper method invoked to teardown client iface (for scan) and perform necessary cleanup */ onClientInterfaceForScanDestroyed(@onNull Iface iface)479 private void onClientInterfaceForScanDestroyed(@NonNull Iface iface) { 480 synchronized (mLock) { 481 mWifiMonitor.stopMonitoring(iface.name); 482 if (!unregisterNetworkObserver(iface.networkObserver)) { 483 Log.e(TAG, "Failed to unregister network observer on " + iface); 484 } 485 if (!mWificondControl.tearDownClientInterface(iface.name)) { 486 Log.e(TAG, "Failed to teardown iface in wificond on " + iface); 487 } 488 stopHalAndWificondIfNecessary(); 489 } 490 } 491 492 /** Helper method invoked to teardown softAp iface and perform necessary cleanup */ onSoftApInterfaceDestroyed(@onNull Iface iface)493 private void onSoftApInterfaceDestroyed(@NonNull Iface iface) { 494 synchronized (mLock) { 495 if (!unregisterNetworkObserver(iface.networkObserver)) { 496 Log.e(TAG, "Failed to unregister network observer on " + iface); 497 } 498 if (!mHostapdHal.removeAccessPoint(iface.name)) { 499 Log.e(TAG, "Failed to remove access point on " + iface); 500 } 501 if (!mWificondControl.tearDownSoftApInterface(iface.name)) { 502 Log.e(TAG, "Failed to teardown iface in wificond on " + iface); 503 } 504 stopHostapdIfNecessary(); 505 stopHalAndWificondIfNecessary(); 506 } 507 } 508 509 /** Helper method invoked to teardown iface and perform necessary cleanup */ onInterfaceDestroyed(@onNull Iface iface)510 private void onInterfaceDestroyed(@NonNull Iface iface) { 511 synchronized (mLock) { 512 if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY) { 513 onClientInterfaceForConnectivityDestroyed(iface); 514 } else if (iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { 515 onClientInterfaceForScanDestroyed(iface); 516 } else if (iface.type == Iface.IFACE_TYPE_AP) { 517 onSoftApInterfaceDestroyed(iface); 518 } 519 // Invoke the external callback. 520 iface.externalListener.onDestroyed(iface.name); 521 } 522 } 523 524 /** 525 * Callback to be invoked by HalDeviceManager when an interface is destroyed. 526 */ 527 private class InterfaceDestoyedListenerInternal 528 implements HalDeviceManager.InterfaceDestroyedListener { 529 /** Identifier allocated for the interface */ 530 private final int mInterfaceId; 531 InterfaceDestoyedListenerInternal(int ifaceId)532 InterfaceDestoyedListenerInternal(int ifaceId) { 533 mInterfaceId = ifaceId; 534 } 535 536 @Override onDestroyed(@onNull String ifaceName)537 public void onDestroyed(@NonNull String ifaceName) { 538 synchronized (mLock) { 539 final Iface iface = mIfaceMgr.removeIface(mInterfaceId); 540 if (iface == null) { 541 if (mVerboseLoggingEnabled) { 542 Log.v(TAG, "Received iface destroyed notification on an invalid iface=" 543 + ifaceName); 544 } 545 return; 546 } 547 onInterfaceDestroyed(iface); 548 Log.i(TAG, "Successfully torn down " + iface); 549 } 550 } 551 } 552 553 /** 554 * Helper method invoked to trigger the status changed callback after one of the native 555 * daemon's death. 556 */ onNativeDaemonDeath()557 private void onNativeDaemonDeath() { 558 synchronized (mLock) { 559 for (StatusListener listener : mStatusListeners) { 560 listener.onStatusChanged(false); 561 } 562 for (StatusListener listener : mStatusListeners) { 563 listener.onStatusChanged(true); 564 } 565 } 566 } 567 568 /** 569 * Death handler for the Vendor HAL daemon. 570 */ 571 private class VendorHalDeathHandlerInternal implements VendorHalDeathEventHandler { 572 @Override onDeath()573 public void onDeath() { 574 synchronized (mLock) { 575 Log.i(TAG, "Vendor HAL died. Cleaning up internal state."); 576 onNativeDaemonDeath(); 577 mWifiMetrics.incrementNumHalCrashes(); 578 } 579 } 580 } 581 582 /** 583 * Death handler for the wificond daemon. 584 */ 585 private class WificondDeathHandlerInternal implements WificondDeathEventHandler { 586 @Override onDeath()587 public void onDeath() { 588 synchronized (mLock) { 589 Log.i(TAG, "wificond died. Cleaning up internal state."); 590 onNativeDaemonDeath(); 591 mWifiMetrics.incrementNumWificondCrashes(); 592 } 593 } 594 } 595 596 /** 597 * Death handler for the supplicant daemon. 598 */ 599 private class SupplicantDeathHandlerInternal implements SupplicantDeathEventHandler { 600 @Override onDeath()601 public void onDeath() { 602 synchronized (mLock) { 603 Log.i(TAG, "wpa_supplicant died. Cleaning up internal state."); 604 onNativeDaemonDeath(); 605 mWifiMetrics.incrementNumSupplicantCrashes(); 606 } 607 } 608 } 609 610 /** 611 * Death handler for the hostapd daemon. 612 */ 613 private class HostapdDeathHandlerInternal implements HostapdDeathEventHandler { 614 @Override onDeath()615 public void onDeath() { 616 synchronized (mLock) { 617 Log.i(TAG, "hostapd died. Cleaning up internal state."); 618 onNativeDaemonDeath(); 619 mWifiMetrics.incrementNumHostapdCrashes(); 620 } 621 } 622 } 623 624 /** Helper method invoked to handle interface change. */ onInterfaceStateChanged(Iface iface, boolean isUp)625 private void onInterfaceStateChanged(Iface iface, boolean isUp) { 626 synchronized (mLock) { 627 // Mask multiple notifications with the same state. 628 if (isUp == iface.isUp) { 629 if (mVerboseLoggingEnabled) { 630 Log.v(TAG, "Interface status unchanged on " + iface + " from " + isUp 631 + ", Ignoring..."); 632 } 633 return; 634 } 635 Log.i(TAG, "Interface state changed on " + iface + ", isUp=" + isUp); 636 if (isUp) { 637 iface.externalListener.onUp(iface.name); 638 } else { 639 iface.externalListener.onDown(iface.name); 640 if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY 641 || iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { 642 mWifiMetrics.incrementNumClientInterfaceDown(); 643 } else if (iface.type == Iface.IFACE_TYPE_AP) { 644 mWifiMetrics.incrementNumSoftApInterfaceDown(); 645 } 646 } 647 iface.isUp = isUp; 648 } 649 } 650 651 /** 652 * Network observer to use for all interface up/down notifications. 653 */ 654 private class NetworkObserverInternal extends BaseNetworkObserver { 655 /** Identifier allocated for the interface */ 656 private final int mInterfaceId; 657 NetworkObserverInternal(int id)658 NetworkObserverInternal(int id) { 659 mInterfaceId = id; 660 } 661 662 /** 663 * Note: We should ideally listen to 664 * {@link BaseNetworkObserver#interfaceStatusChanged(String, boolean)} here. But, that 665 * callback is not working currently (broken in netd). So, instead listen to link state 666 * change callbacks as triggers to query the real interface state. We should get rid of 667 * this workaround if we get the |interfaceStatusChanged| callback to work in netd. 668 * Also, this workaround will not detect an interface up event, if the link state is 669 * still down. 670 */ 671 @Override interfaceLinkStateChanged(String ifaceName, boolean unusedIsLinkUp)672 public void interfaceLinkStateChanged(String ifaceName, boolean unusedIsLinkUp) { 673 // This is invoked from the main system_server thread. Post to our handler. 674 mHandler.post(() -> { 675 synchronized (mLock) { 676 final Iface ifaceWithId = mIfaceMgr.getIface(mInterfaceId); 677 if (ifaceWithId == null) { 678 if (mVerboseLoggingEnabled) { 679 Log.v(TAG, "Received iface link up/down notification on an invalid" 680 + " iface=" + mInterfaceId); 681 } 682 return; 683 } 684 final Iface ifaceWithName = mIfaceMgr.getIface(ifaceName); 685 if (ifaceWithName == null || ifaceWithName != ifaceWithId) { 686 if (mVerboseLoggingEnabled) { 687 Log.v(TAG, "Received iface link up/down notification on an invalid" 688 + " iface=" + ifaceName); 689 } 690 return; 691 } 692 onInterfaceStateChanged(ifaceWithName, isInterfaceUp(ifaceName)); 693 } 694 }); 695 } 696 } 697 698 /** 699 * Radio mode change handler for the Vendor HAL daemon. 700 */ 701 private class VendorHalRadioModeChangeHandlerInternal 702 implements VendorHalRadioModeChangeEventHandler { 703 @Override onMcc(int band)704 public void onMcc(int band) { 705 synchronized (mLock) { 706 Log.i(TAG, "Device is in MCC mode now"); 707 mWifiMetrics.incrementNumRadioModeChangeToMcc(); 708 } 709 } 710 @Override onScc(int band)711 public void onScc(int band) { 712 synchronized (mLock) { 713 Log.i(TAG, "Device is in SCC mode now"); 714 mWifiMetrics.incrementNumRadioModeChangeToScc(); 715 } 716 } 717 @Override onSbs(int band)718 public void onSbs(int band) { 719 synchronized (mLock) { 720 Log.i(TAG, "Device is in SBS mode now"); 721 mWifiMetrics.incrementNumRadioModeChangeToSbs(); 722 } 723 } 724 @Override onDbs()725 public void onDbs() { 726 synchronized (mLock) { 727 Log.i(TAG, "Device is in DBS mode now"); 728 mWifiMetrics.incrementNumRadioModeChangeToDbs(); 729 } 730 } 731 } 732 733 // For devices that don't support the vendor HAL, we will not support any concurrency. 734 // So simulate the HalDeviceManager behavior by triggering the destroy listener for 735 // any active interface. handleIfaceCreationWhenVendorHalNotSupported(@onNull Iface newIface)736 private String handleIfaceCreationWhenVendorHalNotSupported(@NonNull Iface newIface) { 737 synchronized (mLock) { 738 Iface existingIface = mIfaceMgr.removeExistingIface(newIface.id); 739 if (existingIface != null) { 740 onInterfaceDestroyed(existingIface); 741 Log.i(TAG, "Successfully torn down " + existingIface); 742 } 743 // Return the interface name directly from the system property. 744 return mPropertyService.getString("wifi.interface", "wlan0"); 745 } 746 } 747 748 /** 749 * Helper function to handle creation of STA iface. 750 * For devices which do not the support the HAL, this will bypass HalDeviceManager & 751 * teardown any existing iface. 752 */ createStaIface(@onNull Iface iface, boolean lowPrioritySta)753 private String createStaIface(@NonNull Iface iface, boolean lowPrioritySta) { 754 synchronized (mLock) { 755 if (mWifiVendorHal.isVendorHalSupported()) { 756 return mWifiVendorHal.createStaIface(lowPrioritySta, 757 new InterfaceDestoyedListenerInternal(iface.id)); 758 } else { 759 Log.i(TAG, "Vendor Hal not supported, ignoring createStaIface."); 760 return handleIfaceCreationWhenVendorHalNotSupported(iface); 761 } 762 } 763 } 764 765 /** 766 * Helper function to handle creation of AP iface. 767 * For devices which do not the support the HAL, this will bypass HalDeviceManager & 768 * teardown any existing iface. 769 */ createApIface(@onNull Iface iface)770 private String createApIface(@NonNull Iface iface) { 771 synchronized (mLock) { 772 if (mWifiVendorHal.isVendorHalSupported()) { 773 return mWifiVendorHal.createApIface( 774 new InterfaceDestoyedListenerInternal(iface.id)); 775 } else { 776 Log.i(TAG, "Vendor Hal not supported, ignoring createApIface."); 777 return handleIfaceCreationWhenVendorHalNotSupported(iface); 778 } 779 } 780 } 781 782 // For devices that don't support the vendor HAL, we will not support any concurrency. 783 // So simulate the HalDeviceManager behavior by triggering the destroy listener for 784 // the interface. handleIfaceRemovalWhenVendorHalNotSupported(@onNull Iface iface)785 private boolean handleIfaceRemovalWhenVendorHalNotSupported(@NonNull Iface iface) { 786 synchronized (mLock) { 787 mIfaceMgr.removeIface(iface.id); 788 onInterfaceDestroyed(iface); 789 Log.i(TAG, "Successfully torn down " + iface); 790 return true; 791 } 792 } 793 794 /** 795 * Helper function to handle removal of STA iface. 796 * For devices which do not the support the HAL, this will bypass HalDeviceManager & 797 * teardown any existing iface. 798 */ removeStaIface(@onNull Iface iface)799 private boolean removeStaIface(@NonNull Iface iface) { 800 synchronized (mLock) { 801 if (mWifiVendorHal.isVendorHalSupported()) { 802 return mWifiVendorHal.removeStaIface(iface.name); 803 } else { 804 Log.i(TAG, "Vendor Hal not supported, ignoring removeStaIface."); 805 return handleIfaceRemovalWhenVendorHalNotSupported(iface); 806 } 807 } 808 } 809 810 /** 811 * Helper function to handle removal of STA iface. 812 */ removeApIface(@onNull Iface iface)813 private boolean removeApIface(@NonNull Iface iface) { 814 synchronized (mLock) { 815 if (mWifiVendorHal.isVendorHalSupported()) { 816 return mWifiVendorHal.removeApIface(iface.name); 817 } else { 818 Log.i(TAG, "Vendor Hal not supported, ignoring removeApIface."); 819 return handleIfaceRemovalWhenVendorHalNotSupported(iface); 820 } 821 } 822 } 823 824 /** 825 * Initialize the native modules. 826 * 827 * @return true on success, false otherwise. 828 */ initialize()829 public boolean initialize() { 830 synchronized (mLock) { 831 if (!mWifiVendorHal.initialize(new VendorHalDeathHandlerInternal())) { 832 Log.e(TAG, "Failed to initialize vendor HAL"); 833 return false; 834 } 835 if (!mWificondControl.initialize(new WificondDeathHandlerInternal())) { 836 Log.e(TAG, "Failed to initialize wificond"); 837 return false; 838 } 839 mWifiVendorHal.registerRadioModeChangeHandler( 840 new VendorHalRadioModeChangeHandlerInternal()); 841 return true; 842 } 843 } 844 845 /** 846 * Callback to notify when the status of one of the native daemons 847 * (wificond, wpa_supplicant & vendor HAL) changes. 848 */ 849 public interface StatusListener { 850 /** 851 * @param allReady Indicates if all the native daemons are ready for operation or not. 852 */ onStatusChanged(boolean allReady)853 void onStatusChanged(boolean allReady); 854 } 855 856 /** 857 * Register a StatusListener to get notified about any status changes from the native daemons. 858 * 859 * It is safe to re-register the same callback object - duplicates are detected and only a 860 * single copy kept. 861 * 862 * @param listener StatusListener listener object. 863 */ registerStatusListener(@onNull StatusListener listener)864 public void registerStatusListener(@NonNull StatusListener listener) { 865 mStatusListeners.add(listener); 866 } 867 868 /** 869 * Callback to notify when the associated interface is destroyed, up or down. 870 */ 871 public interface InterfaceCallback { 872 /** 873 * Interface destroyed by HalDeviceManager. 874 * 875 * @param ifaceName Name of the iface. 876 */ onDestroyed(String ifaceName)877 void onDestroyed(String ifaceName); 878 879 /** 880 * Interface is up. 881 * 882 * @param ifaceName Name of the iface. 883 */ onUp(String ifaceName)884 void onUp(String ifaceName); 885 886 /** 887 * Interface is down. 888 * 889 * @param ifaceName Name of the iface. 890 */ onDown(String ifaceName)891 void onDown(String ifaceName); 892 } 893 initializeNwParamsForClientInterface(@onNull String ifaceName)894 private void initializeNwParamsForClientInterface(@NonNull String ifaceName) { 895 try { 896 // A runtime crash or shutting down AP mode can leave 897 // IP addresses configured, and this affects 898 // connectivity when supplicant starts up. 899 // Ensure we have no IP addresses before a supplicant start. 900 mNwManagementService.clearInterfaceAddresses(ifaceName); 901 902 // Set privacy extensions 903 mNwManagementService.setInterfaceIpv6PrivacyExtensions(ifaceName, true); 904 905 // IPv6 is enabled only as long as access point is connected since: 906 // - IPv6 addresses and routes stick around after disconnection 907 // - kernel is unaware when connected and fails to start IPv6 negotiation 908 // - kernel can start autoconfiguration when 802.1x is not complete 909 mNwManagementService.disableIpv6(ifaceName); 910 } catch (RemoteException | IllegalStateException e) { 911 Log.e(TAG, "Unable to change interface settings", e); 912 } 913 } 914 915 /** 916 * Setup an interface for client mode (for connectivity) operations. 917 * 918 * This method configures an interface in STA mode in all the native daemons 919 * (wificond, wpa_supplicant & vendor HAL). 920 * 921 * @param interfaceCallback Associated callback for notifying status changes for the iface. 922 * @return Returns the name of the allocated interface, will be null on failure. 923 */ setupInterfaceForClientInConnectivityMode( @onNull InterfaceCallback interfaceCallback)924 public String setupInterfaceForClientInConnectivityMode( 925 @NonNull InterfaceCallback interfaceCallback) { 926 synchronized (mLock) { 927 if (!startHal()) { 928 Log.e(TAG, "Failed to start Hal"); 929 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); 930 return null; 931 } 932 if (!startSupplicant()) { 933 Log.e(TAG, "Failed to start supplicant"); 934 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); 935 return null; 936 } 937 Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY); 938 if (iface == null) { 939 Log.e(TAG, "Failed to allocate new STA iface"); 940 return null; 941 } 942 iface.externalListener = interfaceCallback; 943 iface.name = createStaIface(iface, /* lowPrioritySta */ false); 944 if (TextUtils.isEmpty(iface.name)) { 945 Log.e(TAG, "Failed to create STA iface in vendor HAL"); 946 mIfaceMgr.removeIface(iface.id); 947 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); 948 return null; 949 } 950 if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) { 951 Log.e(TAG, "Failed to setup iface in wificond on " + iface); 952 teardownInterface(iface.name); 953 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond(); 954 return null; 955 } 956 if (!mSupplicantStaIfaceHal.setupIface(iface.name)) { 957 Log.e(TAG, "Failed to setup iface in supplicant on " + iface); 958 teardownInterface(iface.name); 959 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); 960 return null; 961 } 962 iface.networkObserver = new NetworkObserverInternal(iface.id); 963 if (!registerNetworkObserver(iface.networkObserver)) { 964 Log.e(TAG, "Failed to register network observer on " + iface); 965 teardownInterface(iface.name); 966 return null; 967 } 968 mWifiMonitor.startMonitoring(iface.name); 969 // Just to avoid any race conditions with interface state change callbacks, 970 // update the interface state before we exit. 971 onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); 972 initializeNwParamsForClientInterface(iface.name); 973 Log.i(TAG, "Successfully setup " + iface); 974 975 iface.featureSet = getSupportedFeatureSetInternal(iface.name); 976 return iface.name; 977 } 978 } 979 980 /** 981 * Setup an interface for client mode (for scan) operations. 982 * 983 * This method configures an interface in STA mode in the native daemons 984 * (wificond, vendor HAL). 985 * 986 * @param interfaceCallback Associated callback for notifying status changes for the iface. 987 * @return Returns the name of the allocated interface, will be null on failure. 988 */ setupInterfaceForClientInScanMode( @onNull InterfaceCallback interfaceCallback)989 public String setupInterfaceForClientInScanMode( 990 @NonNull InterfaceCallback interfaceCallback) { 991 synchronized (mLock) { 992 if (!startHal()) { 993 Log.e(TAG, "Failed to start Hal"); 994 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); 995 return null; 996 } 997 Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_SCAN); 998 if (iface == null) { 999 Log.e(TAG, "Failed to allocate new STA iface"); 1000 return null; 1001 } 1002 iface.externalListener = interfaceCallback; 1003 iface.name = createStaIface(iface, /* lowPrioritySta */ true); 1004 if (TextUtils.isEmpty(iface.name)) { 1005 Log.e(TAG, "Failed to create iface in vendor HAL"); 1006 mIfaceMgr.removeIface(iface.id); 1007 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); 1008 return null; 1009 } 1010 if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) { 1011 Log.e(TAG, "Failed to setup iface in wificond=" + iface.name); 1012 teardownInterface(iface.name); 1013 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond(); 1014 return null; 1015 } 1016 iface.networkObserver = new NetworkObserverInternal(iface.id); 1017 if (!registerNetworkObserver(iface.networkObserver)) { 1018 Log.e(TAG, "Failed to register network observer for iface=" + iface.name); 1019 teardownInterface(iface.name); 1020 return null; 1021 } 1022 mWifiMonitor.startMonitoring(iface.name); 1023 // Just to avoid any race conditions with interface state change callbacks, 1024 // update the interface state before we exit. 1025 onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); 1026 Log.i(TAG, "Successfully setup " + iface); 1027 1028 iface.featureSet = getSupportedFeatureSetInternal(iface.name); 1029 return iface.name; 1030 } 1031 } 1032 1033 /** 1034 * Setup an interface for Soft AP mode operations. 1035 * 1036 * This method configures an interface in AP mode in all the native daemons 1037 * (wificond, wpa_supplicant & vendor HAL). 1038 * 1039 * @param interfaceCallback Associated callback for notifying status changes for the iface. 1040 * @return Returns the name of the allocated interface, will be null on failure. 1041 */ setupInterfaceForSoftApMode(@onNull InterfaceCallback interfaceCallback)1042 public String setupInterfaceForSoftApMode(@NonNull InterfaceCallback interfaceCallback) { 1043 synchronized (mLock) { 1044 if (!startHal()) { 1045 Log.e(TAG, "Failed to start Hal"); 1046 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); 1047 return null; 1048 } 1049 if (!startHostapd()) { 1050 Log.e(TAG, "Failed to start hostapd"); 1051 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd(); 1052 return null; 1053 } 1054 Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_AP); 1055 if (iface == null) { 1056 Log.e(TAG, "Failed to allocate new AP iface"); 1057 return null; 1058 } 1059 iface.externalListener = interfaceCallback; 1060 iface.name = createApIface(iface); 1061 if (TextUtils.isEmpty(iface.name)) { 1062 Log.e(TAG, "Failed to create AP iface in vendor HAL"); 1063 mIfaceMgr.removeIface(iface.id); 1064 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal(); 1065 return null; 1066 } 1067 if (mWificondControl.setupInterfaceForSoftApMode(iface.name) == null) { 1068 Log.e(TAG, "Failed to setup iface in wificond on " + iface); 1069 teardownInterface(iface.name); 1070 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond(); 1071 return null; 1072 } 1073 iface.networkObserver = new NetworkObserverInternal(iface.id); 1074 if (!registerNetworkObserver(iface.networkObserver)) { 1075 Log.e(TAG, "Failed to register network observer on " + iface); 1076 teardownInterface(iface.name); 1077 return null; 1078 } 1079 // Just to avoid any race conditions with interface state change callbacks, 1080 // update the interface state before we exit. 1081 onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); 1082 Log.i(TAG, "Successfully setup " + iface); 1083 1084 iface.featureSet = getSupportedFeatureSetInternal(iface.name); 1085 return iface.name; 1086 } 1087 } 1088 1089 /** 1090 * 1091 * Check if the interface is up or down. 1092 * 1093 * @param ifaceName Name of the interface. 1094 * @return true if iface is up, false if it's down or on error. 1095 */ isInterfaceUp(@onNull String ifaceName)1096 public boolean isInterfaceUp(@NonNull String ifaceName) { 1097 synchronized (mLock) { 1098 final Iface iface = mIfaceMgr.getIface(ifaceName); 1099 if (iface == null) { 1100 Log.e(TAG, "Trying to get iface state on invalid iface=" + ifaceName); 1101 return false; 1102 } 1103 InterfaceConfiguration config = null; 1104 try { 1105 config = mNwManagementService.getInterfaceConfig(ifaceName); 1106 } catch (RemoteException | IllegalStateException e) { 1107 Log.e(TAG, "Unable to get interface config", e); 1108 } 1109 if (config == null) { 1110 return false; 1111 } 1112 return config.isUp(); 1113 } 1114 } 1115 1116 /** 1117 * Teardown an interface in Client/AP mode. 1118 * 1119 * This method tears down the associated interface from all the native daemons 1120 * (wificond, wpa_supplicant & vendor HAL). 1121 * Also, brings down the HAL, supplicant or hostapd as necessary. 1122 * 1123 * @param ifaceName Name of the interface. 1124 */ teardownInterface(@onNull String ifaceName)1125 public void teardownInterface(@NonNull String ifaceName) { 1126 synchronized (mLock) { 1127 final Iface iface = mIfaceMgr.getIface(ifaceName); 1128 if (iface == null) { 1129 Log.e(TAG, "Trying to teardown an invalid iface=" + ifaceName); 1130 return; 1131 } 1132 // Trigger the iface removal from HAL. The rest of the cleanup will be triggered 1133 // from the interface destroyed callback. 1134 if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY 1135 || iface.type == Iface.IFACE_TYPE_STA_FOR_SCAN) { 1136 if (!removeStaIface(iface)) { 1137 Log.e(TAG, "Failed to remove iface in vendor HAL=" + ifaceName); 1138 return; 1139 } 1140 } else if (iface.type == Iface.IFACE_TYPE_AP) { 1141 if (!removeApIface(iface)) { 1142 Log.e(TAG, "Failed to remove iface in vendor HAL=" + ifaceName); 1143 return; 1144 } 1145 } 1146 Log.i(TAG, "Successfully initiated teardown for iface=" + ifaceName); 1147 } 1148 } 1149 1150 /** 1151 * Teardown all the active interfaces. 1152 * 1153 * This method tears down the associated interfaces from all the native daemons 1154 * (wificond, wpa_supplicant & vendor HAL). 1155 * Also, brings down the HAL, supplicant or hostapd as necessary. 1156 */ teardownAllInterfaces()1157 public void teardownAllInterfaces() { 1158 synchronized (mLock) { 1159 Iterator<Integer> ifaceIdIter = mIfaceMgr.getIfaceIdIter(); 1160 while (ifaceIdIter.hasNext()) { 1161 Iface iface = mIfaceMgr.getIface(ifaceIdIter.next()); 1162 ifaceIdIter.remove(); 1163 onInterfaceDestroyed(iface); 1164 Log.i(TAG, "Successfully torn down " + iface); 1165 } 1166 Log.i(TAG, "Successfully torn down all ifaces"); 1167 } 1168 } 1169 1170 /** 1171 * Get name of the client interface. 1172 * 1173 * This is mainly used by external modules that needs to perform some 1174 * client operations on the STA interface. 1175 * 1176 * TODO(b/70932231): This may need to be reworked once we start supporting STA + STA. 1177 * 1178 * @return Interface name of any active client interface, null if no active client interface 1179 * exist. 1180 * Return Values for the different scenarios are listed below: 1181 * a) When there are no client interfaces, returns null. 1182 * b) when there is 1 client interface, returns the name of that interface. 1183 * c) When there are 2 or more client interface, returns the name of any client interface. 1184 */ getClientInterfaceName()1185 public String getClientInterfaceName() { 1186 synchronized (mLock) { 1187 return mIfaceMgr.findAnyStaIfaceName(); 1188 } 1189 } 1190 1191 /** 1192 * Get name of the softap interface. 1193 * 1194 * This is mainly used by external modules that needs to perform some 1195 * operations on the AP interface. 1196 * 1197 * TODO(b/70932231): This may need to be reworked once we start supporting AP + AP. 1198 * 1199 * @return Interface name of any active softap interface, null if no active softap interface 1200 * exist. 1201 * Return Values for the different scenarios are listed below: 1202 * a) When there are no softap interfaces, returns null. 1203 * b) when there is 1 softap interface, returns the name of that interface. 1204 * c) When there are 2 or more softap interface, returns the name of any softap interface. 1205 */ getSoftApInterfaceName()1206 public String getSoftApInterfaceName() { 1207 synchronized (mLock) { 1208 return mIfaceMgr.findAnyApIfaceName(); 1209 } 1210 } 1211 1212 /******************************************************** 1213 * Wificond operations 1214 ********************************************************/ 1215 /** 1216 * Result of a signal poll. 1217 */ 1218 public static class SignalPollResult { 1219 // RSSI value in dBM. 1220 public int currentRssi; 1221 //Transmission bit rate in Mbps. 1222 public int txBitrate; 1223 // Association frequency in MHz. 1224 public int associationFrequency; 1225 //Last received packet bit rate in Mbps. 1226 public int rxBitrate; 1227 } 1228 1229 /** 1230 * WiFi interface transimission counters. 1231 */ 1232 public static class TxPacketCounters { 1233 // Number of successfully transmitted packets. 1234 public int txSucceeded; 1235 // Number of tramsmission failures. 1236 public int txFailed; 1237 } 1238 1239 /** 1240 * Callback to notify wificond death. 1241 */ 1242 public interface WificondDeathEventHandler { 1243 /** 1244 * Invoked when the wificond dies. 1245 */ onDeath()1246 void onDeath(); 1247 } 1248 1249 /** 1250 * Request signal polling to wificond. 1251 * 1252 * @param ifaceName Name of the interface. 1253 * Returns an SignalPollResult object. 1254 * Returns null on failure. 1255 */ signalPoll(@onNull String ifaceName)1256 public SignalPollResult signalPoll(@NonNull String ifaceName) { 1257 return mWificondControl.signalPoll(ifaceName); 1258 } 1259 1260 /** 1261 * Fetch TX packet counters on current connection from wificond. 1262 * @param ifaceName Name of the interface. 1263 * Returns an TxPacketCounters object. 1264 * Returns null on failure. 1265 */ getTxPacketCounters(@onNull String ifaceName)1266 public TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) { 1267 return mWificondControl.getTxPacketCounters(ifaceName); 1268 } 1269 1270 /** 1271 * Query the list of valid frequencies for the provided band. 1272 * The result depends on the on the country code that has been set. 1273 * 1274 * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants. 1275 * The following bands are supported: 1276 * WifiScanner.WIFI_BAND_24_GHZ 1277 * WifiScanner.WIFI_BAND_5_GHZ 1278 * WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY 1279 * @return frequencies vector of valid frequencies (MHz), or null for error. 1280 * @throws IllegalArgumentException if band is not recognized. 1281 */ getChannelsForBand(int band)1282 public int [] getChannelsForBand(int band) { 1283 return mWificondControl.getChannelsForBand(band); 1284 } 1285 1286 /** 1287 * Start a scan using wificond for the given parameters. 1288 * @param ifaceName Name of the interface. 1289 * @param scanType Type of scan to perform. One of {@link ScanSettings#SCAN_TYPE_LOW_LATENCY}, 1290 * {@link ScanSettings#SCAN_TYPE_LOW_POWER} or {@link ScanSettings#SCAN_TYPE_HIGH_ACCURACY}. 1291 * @param freqs list of frequencies to scan for, if null scan all supported channels. 1292 * @param hiddenNetworkSSIDs List of hidden networks to be scanned for. 1293 * @return Returns true on success. 1294 */ scan( @onNull String ifaceName, int scanType, Set<Integer> freqs, List<String> hiddenNetworkSSIDs)1295 public boolean scan( 1296 @NonNull String ifaceName, int scanType, Set<Integer> freqs, 1297 List<String> hiddenNetworkSSIDs) { 1298 return mWificondControl.scan(ifaceName, scanType, freqs, hiddenNetworkSSIDs); 1299 } 1300 1301 /** 1302 * Fetch the latest scan result from kernel via wificond. 1303 * @param ifaceName Name of the interface. 1304 * @return Returns an ArrayList of ScanDetail. 1305 * Returns an empty ArrayList on failure. 1306 */ getScanResults(@onNull String ifaceName)1307 public ArrayList<ScanDetail> getScanResults(@NonNull String ifaceName) { 1308 return mWificondControl.getScanResults( 1309 ifaceName, WificondControl.SCAN_TYPE_SINGLE_SCAN); 1310 } 1311 1312 /** 1313 * Fetch the latest scan result from kernel via wificond. 1314 * @param ifaceName Name of the interface. 1315 * @return Returns an ArrayList of ScanDetail. 1316 * Returns an empty ArrayList on failure. 1317 */ getPnoScanResults(@onNull String ifaceName)1318 public ArrayList<ScanDetail> getPnoScanResults(@NonNull String ifaceName) { 1319 return mWificondControl.getScanResults(ifaceName, WificondControl.SCAN_TYPE_PNO_SCAN); 1320 } 1321 1322 /** 1323 * Start PNO scan. 1324 * @param ifaceName Name of the interface. 1325 * @param pnoSettings Pno scan configuration. 1326 * @return true on success. 1327 */ startPnoScan(@onNull String ifaceName, PnoSettings pnoSettings)1328 public boolean startPnoScan(@NonNull String ifaceName, PnoSettings pnoSettings) { 1329 return mWificondControl.startPnoScan(ifaceName, pnoSettings); 1330 } 1331 1332 /** 1333 * Stop PNO scan. 1334 * @param ifaceName Name of the interface. 1335 * @return true on success. 1336 */ stopPnoScan(@onNull String ifaceName)1337 public boolean stopPnoScan(@NonNull String ifaceName) { 1338 return mWificondControl.stopPnoScan(ifaceName); 1339 } 1340 1341 /** 1342 * Callback to notify the results of a 1343 * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()} call. 1344 * Note: no callbacks will be triggered if the iface dies while sending a frame. 1345 */ 1346 public interface SendMgmtFrameCallback { 1347 /** 1348 * Called when the management frame was successfully sent and ACKed by the recipient. 1349 * @param elapsedTimeMs The elapsed time between when the management frame was sent and when 1350 * the ACK was processed, in milliseconds, as measured by wificond. 1351 * This includes the time that the send frame spent queuing before it 1352 * was sent, any firmware retries, and the time the received ACK spent 1353 * queuing before it was processed. 1354 */ onAck(int elapsedTimeMs)1355 void onAck(int elapsedTimeMs); 1356 1357 /** 1358 * Called when the send failed. 1359 * @param reason The error code for the failure. 1360 */ onFailure(@endMgmtFrameError int reason)1361 void onFailure(@SendMgmtFrameError int reason); 1362 } 1363 1364 @Retention(RetentionPolicy.SOURCE) 1365 @IntDef(prefix = {"SEND_MGMT_FRAME_ERROR_"}, 1366 value = {SEND_MGMT_FRAME_ERROR_UNKNOWN, 1367 SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED, 1368 SEND_MGMT_FRAME_ERROR_NO_ACK, 1369 SEND_MGMT_FRAME_ERROR_TIMEOUT, 1370 SEND_MGMT_FRAME_ERROR_ALREADY_STARTED}) 1371 public @interface SendMgmtFrameError {} 1372 1373 // Send management frame error codes 1374 1375 /** 1376 * Unknown error occurred during call to 1377 * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()}. 1378 */ 1379 public static final int SEND_MGMT_FRAME_ERROR_UNKNOWN = 1; 1380 1381 /** 1382 * Specifying the MCS rate in 1383 * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()} is not 1384 * supported by this device. 1385 */ 1386 public static final int SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED = 2; 1387 1388 /** 1389 * Driver reported that no ACK was received for the frame transmitted using 1390 * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()}. 1391 */ 1392 public static final int SEND_MGMT_FRAME_ERROR_NO_ACK = 3; 1393 1394 /** 1395 * Error code for when the driver fails to report on the status of the frame sent by 1396 * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()} 1397 * after {@link WificondControl#SEND_MGMT_FRAME_TIMEOUT_MS} milliseconds. 1398 */ 1399 public static final int SEND_MGMT_FRAME_ERROR_TIMEOUT = 4; 1400 1401 /** 1402 * An existing call to 1403 * {@link #sendMgmtFrame(String, byte[], SendMgmtFrameCallback, int) sendMgmtFrame()} 1404 * is in progress. Another frame cannot be sent until the first call completes. 1405 */ 1406 public static final int SEND_MGMT_FRAME_ERROR_ALREADY_STARTED = 5; 1407 1408 /** 1409 * Sends an arbitrary 802.11 management frame on the current channel. 1410 * 1411 * @param ifaceName Name of the interface. 1412 * @param frame Bytes of the 802.11 management frame to be sent, including the header, but not 1413 * including the frame check sequence (FCS). 1414 * @param callback A callback triggered when the transmitted frame is ACKed or the transmission 1415 * fails. 1416 * @param mcs The MCS index that the frame will be sent at. If mcs < 0, the driver will select 1417 * the rate automatically. If the device does not support sending the frame at a 1418 * specified MCS rate, the transmission will be aborted and 1419 * {@link SendMgmtFrameCallback#onFailure(int)} will be called with reason 1420 * {@link #SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED}. 1421 */ sendMgmtFrame(@onNull String ifaceName, @NonNull byte[] frame, @NonNull SendMgmtFrameCallback callback, int mcs)1422 public void sendMgmtFrame(@NonNull String ifaceName, @NonNull byte[] frame, 1423 @NonNull SendMgmtFrameCallback callback, int mcs) { 1424 mWificondControl.sendMgmtFrame(ifaceName, frame, callback, mcs); 1425 } 1426 1427 /** 1428 * Sends a probe request to the AP and waits for a response in order to determine whether 1429 * there is connectivity between the device and AP. 1430 * 1431 * @param ifaceName Name of the interface. 1432 * @param receiverMac the MAC address of the AP that the probe request will be sent to. 1433 * @param callback callback triggered when the probe was ACKed by the AP, or when 1434 * an error occurs after the link probe was started. 1435 * @param mcs The MCS index that this probe will be sent at. If mcs < 0, the driver will select 1436 * the rate automatically. If the device does not support sending the frame at a 1437 * specified MCS rate, the transmission will be aborted and 1438 * {@link SendMgmtFrameCallback#onFailure(int)} will be called with reason 1439 * {@link #SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED}. 1440 */ probeLink(@onNull String ifaceName, @NonNull MacAddress receiverMac, @NonNull SendMgmtFrameCallback callback, int mcs)1441 public void probeLink(@NonNull String ifaceName, @NonNull MacAddress receiverMac, 1442 @NonNull SendMgmtFrameCallback callback, int mcs) { 1443 if (callback == null) { 1444 Log.e(TAG, "callback cannot be null!"); 1445 return; 1446 } 1447 1448 if (receiverMac == null) { 1449 Log.e(TAG, "Receiver MAC address cannot be null!"); 1450 callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN); 1451 return; 1452 } 1453 1454 String senderMacStr = getMacAddress(ifaceName); 1455 if (senderMacStr == null) { 1456 Log.e(TAG, "Failed to get this device's MAC Address"); 1457 callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN); 1458 return; 1459 } 1460 1461 byte[] frame = buildProbeRequestFrame( 1462 receiverMac.toByteArray(), 1463 NativeUtil.macAddressToByteArray(senderMacStr)); 1464 sendMgmtFrame(ifaceName, frame, callback, mcs); 1465 } 1466 1467 // header = 24 bytes, minimal body = 2 bytes, no FCS (will be added by driver) 1468 private static final int BASIC_PROBE_REQUEST_FRAME_SIZE = 24 + 2; 1469 buildProbeRequestFrame(byte[] receiverMac, byte[] transmitterMac)1470 private byte[] buildProbeRequestFrame(byte[] receiverMac, byte[] transmitterMac) { 1471 ByteBuffer frame = ByteBuffer.allocate(BASIC_PROBE_REQUEST_FRAME_SIZE); 1472 // ByteBuffer is big endian by default, switch to little endian 1473 frame.order(ByteOrder.LITTLE_ENDIAN); 1474 1475 // Protocol version = 0, Type = management, Subtype = Probe Request 1476 frame.put((byte) 0x40); 1477 1478 // no flags set 1479 frame.put((byte) 0x00); 1480 1481 // duration = 60 microseconds. Note: this is little endian 1482 // Note: driver should calculate the duration and replace it before sending, putting a 1483 // reasonable default value here just in case. 1484 frame.putShort((short) 0x3c); 1485 1486 // receiver/destination MAC address byte array 1487 frame.put(receiverMac); 1488 // sender MAC address byte array 1489 frame.put(transmitterMac); 1490 // BSSID (same as receiver address since we are sending to the AP) 1491 frame.put(receiverMac); 1492 1493 // Generate random sequence number, fragment number = 0 1494 // Note: driver should replace the sequence number with the correct number that is 1495 // incremented from the last used sequence number. Putting a random sequence number as a 1496 // default here just in case. 1497 // bit 0 is least significant bit, bit 15 is most significant bit 1498 // bits [0, 7] go in byte 0 1499 // bits [8, 15] go in byte 1 1500 // bits [0, 3] represent the fragment number (which is 0) 1501 // bits [4, 15] represent the sequence number (which is random) 1502 // clear bits [0, 3] to set fragment number = 0 1503 short sequenceAndFragmentNumber = (short) (mRandom.nextInt() & 0xfff0); 1504 frame.putShort(sequenceAndFragmentNumber); 1505 1506 // NL80211 rejects frames with an empty body, so we just need to put a placeholder 1507 // information element. 1508 // Tag for SSID 1509 frame.put((byte) 0x00); 1510 // Represents broadcast SSID. Not accurate, but works as placeholder. 1511 frame.put((byte) 0x00); 1512 1513 return frame.array(); 1514 } 1515 1516 /** 1517 * Callbacks for SoftAp interface. 1518 */ 1519 public interface SoftApListener { 1520 /** 1521 * Invoked when there is some fatal failure in the lower layers. 1522 */ onFailure()1523 void onFailure(); 1524 1525 /** 1526 * Invoked when the associated stations changes. 1527 */ onConnectedClientsChanged(List<NativeWifiClient> clients)1528 void onConnectedClientsChanged(List<NativeWifiClient> clients); 1529 1530 /** 1531 * Invoked when the channel switch event happens. 1532 */ onSoftApChannelSwitched(int frequency, int bandwidth)1533 void onSoftApChannelSwitched(int frequency, int bandwidth); 1534 } 1535 1536 private static final int CONNECT_TO_HOSTAPD_RETRY_INTERVAL_MS = 100; 1537 private static final int CONNECT_TO_HOSTAPD_RETRY_TIMES = 50; 1538 /** 1539 * This method is called to wait for establishing connection to hostapd. 1540 * 1541 * @return true if connection is established, false otherwise. 1542 */ startAndWaitForHostapdConnection()1543 private boolean startAndWaitForHostapdConnection() { 1544 // Start initialization if not already started. 1545 if (!mHostapdHal.isInitializationStarted() 1546 && !mHostapdHal.initialize()) { 1547 return false; 1548 } 1549 if (!mHostapdHal.startDaemon()) { 1550 Log.e(TAG, "Failed to startup hostapd"); 1551 return false; 1552 } 1553 boolean connected = false; 1554 int connectTries = 0; 1555 while (!connected && connectTries++ < CONNECT_TO_HOSTAPD_RETRY_TIMES) { 1556 // Check if the initialization is complete. 1557 connected = mHostapdHal.isInitializationComplete(); 1558 if (connected) { 1559 break; 1560 } 1561 try { 1562 Thread.sleep(CONNECT_TO_HOSTAPD_RETRY_INTERVAL_MS); 1563 } catch (InterruptedException ignore) { 1564 } 1565 } 1566 return connected; 1567 } 1568 1569 /** 1570 * Start Soft AP operation using the provided configuration. 1571 * 1572 * @param ifaceName Name of the interface. 1573 * @param config Configuration to use for the soft ap created. 1574 * @param listener Callback for AP events. 1575 * @return true on success, false otherwise. 1576 */ startSoftAp( @onNull String ifaceName, WifiConfiguration config, SoftApListener listener)1577 public boolean startSoftAp( 1578 @NonNull String ifaceName, WifiConfiguration config, SoftApListener listener) { 1579 if (!mWificondControl.registerApListener(ifaceName, listener)) { 1580 Log.e(TAG, "Failed to register ap listener"); 1581 return false; 1582 } 1583 if (!mHostapdHal.addAccessPoint(ifaceName, config, listener)) { 1584 Log.e(TAG, "Failed to add acccess point"); 1585 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd(); 1586 return false; 1587 } 1588 return true; 1589 } 1590 1591 /** 1592 * Set MAC address of the given interface 1593 * @param interfaceName Name of the interface 1594 * @param mac Mac address to change into 1595 * @return true on success 1596 */ setMacAddress(String interfaceName, MacAddress mac)1597 public boolean setMacAddress(String interfaceName, MacAddress mac) { 1598 // TODO(b/72459123): Suppress interface down/up events from this call 1599 return mWifiVendorHal.setMacAddress(interfaceName, mac); 1600 } 1601 1602 /** 1603 * Get the factory MAC address of the given interface 1604 * @param interfaceName Name of the interface. 1605 * @return factory MAC address, or null on a failed call or if feature is unavailable. 1606 */ getFactoryMacAddress(@onNull String interfaceName)1607 public MacAddress getFactoryMacAddress(@NonNull String interfaceName) { 1608 return mWifiVendorHal.getFactoryMacAddress(interfaceName); 1609 } 1610 1611 /******************************************************** 1612 * Hostapd operations 1613 ********************************************************/ 1614 1615 /** 1616 * Callback to notify hostapd death. 1617 */ 1618 public interface HostapdDeathEventHandler { 1619 /** 1620 * Invoked when the supplicant dies. 1621 */ onDeath()1622 void onDeath(); 1623 } 1624 1625 /******************************************************** 1626 * Supplicant operations 1627 ********************************************************/ 1628 1629 /** 1630 * Callback to notify supplicant death. 1631 */ 1632 public interface SupplicantDeathEventHandler { 1633 /** 1634 * Invoked when the supplicant dies. 1635 */ onDeath()1636 void onDeath(); 1637 } 1638 1639 /** 1640 * Set supplicant log level 1641 * 1642 * @param turnOnVerbose Whether to turn on verbose logging or not. 1643 */ setSupplicantLogLevel(boolean turnOnVerbose)1644 public void setSupplicantLogLevel(boolean turnOnVerbose) { 1645 mSupplicantStaIfaceHal.setLogLevel(turnOnVerbose); 1646 } 1647 1648 /** 1649 * Trigger a reconnection if the iface is disconnected. 1650 * 1651 * @param ifaceName Name of the interface. 1652 * @return true if request is sent successfully, false otherwise. 1653 */ reconnect(@onNull String ifaceName)1654 public boolean reconnect(@NonNull String ifaceName) { 1655 return mSupplicantStaIfaceHal.reconnect(ifaceName); 1656 } 1657 1658 /** 1659 * Trigger a reassociation even if the iface is currently connected. 1660 * 1661 * @param ifaceName Name of the interface. 1662 * @return true if request is sent successfully, false otherwise. 1663 */ reassociate(@onNull String ifaceName)1664 public boolean reassociate(@NonNull String ifaceName) { 1665 return mSupplicantStaIfaceHal.reassociate(ifaceName); 1666 } 1667 1668 /** 1669 * Trigger a disconnection from the currently connected network. 1670 * 1671 * @param ifaceName Name of the interface. 1672 * @return true if request is sent successfully, false otherwise. 1673 */ disconnect(@onNull String ifaceName)1674 public boolean disconnect(@NonNull String ifaceName) { 1675 return mSupplicantStaIfaceHal.disconnect(ifaceName); 1676 } 1677 1678 /** 1679 * Makes a callback to HIDL to getMacAddress from supplicant 1680 * 1681 * @param ifaceName Name of the interface. 1682 * @return string containing the MAC address, or null on a failed call 1683 */ getMacAddress(@onNull String ifaceName)1684 public String getMacAddress(@NonNull String ifaceName) { 1685 return mSupplicantStaIfaceHal.getMacAddress(ifaceName); 1686 } 1687 1688 public static final int RX_FILTER_TYPE_V4_MULTICAST = 0; 1689 public static final int RX_FILTER_TYPE_V6_MULTICAST = 1; 1690 /** 1691 * Start filtering out Multicast V4 packets 1692 * @param ifaceName Name of the interface. 1693 * @return {@code true} if the operation succeeded, {@code false} otherwise 1694 * 1695 * Multicast filtering rules work as follows: 1696 * 1697 * The driver can filter multicast (v4 and/or v6) and broadcast packets when in 1698 * a power optimized mode (typically when screen goes off). 1699 * 1700 * In order to prevent the driver from filtering the multicast/broadcast packets, we have to 1701 * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective 1702 * 1703 * DRIVER RXFILTER-ADD Num 1704 * where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6 1705 * 1706 * and DRIVER RXFILTER-START 1707 * In order to stop the usage of these rules, we do 1708 * 1709 * DRIVER RXFILTER-STOP 1710 * DRIVER RXFILTER-REMOVE Num 1711 * where Num is as described for RXFILTER-ADD 1712 * 1713 * The SETSUSPENDOPT driver command overrides the filtering rules 1714 */ startFilteringMulticastV4Packets(@onNull String ifaceName)1715 public boolean startFilteringMulticastV4Packets(@NonNull String ifaceName) { 1716 return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) 1717 && mSupplicantStaIfaceHal.removeRxFilter( 1718 ifaceName, RX_FILTER_TYPE_V4_MULTICAST) 1719 && mSupplicantStaIfaceHal.startRxFilter(ifaceName); 1720 } 1721 1722 /** 1723 * Stop filtering out Multicast V4 packets. 1724 * @param ifaceName Name of the interface. 1725 * @return {@code true} if the operation succeeded, {@code false} otherwise 1726 */ stopFilteringMulticastV4Packets(@onNull String ifaceName)1727 public boolean stopFilteringMulticastV4Packets(@NonNull String ifaceName) { 1728 return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) 1729 && mSupplicantStaIfaceHal.addRxFilter( 1730 ifaceName, RX_FILTER_TYPE_V4_MULTICAST) 1731 && mSupplicantStaIfaceHal.startRxFilter(ifaceName); 1732 } 1733 1734 /** 1735 * Start filtering out Multicast V6 packets 1736 * @param ifaceName Name of the interface. 1737 * @return {@code true} if the operation succeeded, {@code false} otherwise 1738 */ startFilteringMulticastV6Packets(@onNull String ifaceName)1739 public boolean startFilteringMulticastV6Packets(@NonNull String ifaceName) { 1740 return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) 1741 && mSupplicantStaIfaceHal.removeRxFilter( 1742 ifaceName, RX_FILTER_TYPE_V6_MULTICAST) 1743 && mSupplicantStaIfaceHal.startRxFilter(ifaceName); 1744 } 1745 1746 /** 1747 * Stop filtering out Multicast V6 packets. 1748 * @param ifaceName Name of the interface. 1749 * @return {@code true} if the operation succeeded, {@code false} otherwise 1750 */ stopFilteringMulticastV6Packets(@onNull String ifaceName)1751 public boolean stopFilteringMulticastV6Packets(@NonNull String ifaceName) { 1752 return mSupplicantStaIfaceHal.stopRxFilter(ifaceName) 1753 && mSupplicantStaIfaceHal.addRxFilter( 1754 ifaceName, RX_FILTER_TYPE_V6_MULTICAST) 1755 && mSupplicantStaIfaceHal.startRxFilter(ifaceName); 1756 } 1757 1758 public static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0; 1759 public static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1; 1760 public static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2; 1761 /** 1762 * Sets the bluetooth coexistence mode. 1763 * 1764 * @param ifaceName Name of the interface. 1765 * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED}, 1766 * {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or 1767 * {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}. 1768 * @return Whether the mode was successfully set. 1769 */ setBluetoothCoexistenceMode(@onNull String ifaceName, int mode)1770 public boolean setBluetoothCoexistenceMode(@NonNull String ifaceName, int mode) { 1771 return mSupplicantStaIfaceHal.setBtCoexistenceMode(ifaceName, mode); 1772 } 1773 1774 /** 1775 * Enable or disable Bluetooth coexistence scan mode. When this mode is on, 1776 * some of the low-level scan parameters used by the driver are changed to 1777 * reduce interference with A2DP streaming. 1778 * 1779 * @param ifaceName Name of the interface. 1780 * @param setCoexScanMode whether to enable or disable this mode 1781 * @return {@code true} if the command succeeded, {@code false} otherwise. 1782 */ setBluetoothCoexistenceScanMode( @onNull String ifaceName, boolean setCoexScanMode)1783 public boolean setBluetoothCoexistenceScanMode( 1784 @NonNull String ifaceName, boolean setCoexScanMode) { 1785 return mSupplicantStaIfaceHal.setBtCoexistenceScanModeEnabled( 1786 ifaceName, setCoexScanMode); 1787 } 1788 1789 /** 1790 * Enable or disable suspend mode optimizations. 1791 * 1792 * @param ifaceName Name of the interface. 1793 * @param enabled true to enable, false otherwise. 1794 * @return true if request is sent successfully, false otherwise. 1795 */ setSuspendOptimizations(@onNull String ifaceName, boolean enabled)1796 public boolean setSuspendOptimizations(@NonNull String ifaceName, boolean enabled) { 1797 return mSupplicantStaIfaceHal.setSuspendModeEnabled(ifaceName, enabled); 1798 } 1799 1800 /** 1801 * Set country code. 1802 * 1803 * @param ifaceName Name of the interface. 1804 * @param countryCode 2 byte ASCII string. For ex: US, CA. 1805 * @return true if request is sent successfully, false otherwise. 1806 */ setCountryCode(@onNull String ifaceName, String countryCode)1807 public boolean setCountryCode(@NonNull String ifaceName, String countryCode) { 1808 return mSupplicantStaIfaceHal.setCountryCode(ifaceName, countryCode); 1809 } 1810 1811 /** 1812 * Initiate TDLS discover and setup or teardown with the specified peer. 1813 * 1814 * @param ifaceName Name of the interface. 1815 * @param macAddr MAC Address of the peer. 1816 * @param enable true to start discovery and setup, false to teardown. 1817 */ startTdls(@onNull String ifaceName, String macAddr, boolean enable)1818 public void startTdls(@NonNull String ifaceName, String macAddr, boolean enable) { 1819 if (enable) { 1820 mSupplicantStaIfaceHal.initiateTdlsDiscover(ifaceName, macAddr); 1821 mSupplicantStaIfaceHal.initiateTdlsSetup(ifaceName, macAddr); 1822 } else { 1823 mSupplicantStaIfaceHal.initiateTdlsTeardown(ifaceName, macAddr); 1824 } 1825 } 1826 1827 /** 1828 * Start WPS pin display operation with the specified peer. 1829 * 1830 * @param ifaceName Name of the interface. 1831 * @param bssid BSSID of the peer. 1832 * @return true if request is sent successfully, false otherwise. 1833 */ startWpsPbc(@onNull String ifaceName, String bssid)1834 public boolean startWpsPbc(@NonNull String ifaceName, String bssid) { 1835 return mSupplicantStaIfaceHal.startWpsPbc(ifaceName, bssid); 1836 } 1837 1838 /** 1839 * Start WPS pin keypad operation with the specified pin. 1840 * 1841 * @param ifaceName Name of the interface. 1842 * @param pin Pin to be used. 1843 * @return true if request is sent successfully, false otherwise. 1844 */ startWpsPinKeypad(@onNull String ifaceName, String pin)1845 public boolean startWpsPinKeypad(@NonNull String ifaceName, String pin) { 1846 return mSupplicantStaIfaceHal.startWpsPinKeypad(ifaceName, pin); 1847 } 1848 1849 /** 1850 * Start WPS pin display operation with the specified peer. 1851 * 1852 * @param ifaceName Name of the interface. 1853 * @param bssid BSSID of the peer. 1854 * @return new pin generated on success, null otherwise. 1855 */ startWpsPinDisplay(@onNull String ifaceName, String bssid)1856 public String startWpsPinDisplay(@NonNull String ifaceName, String bssid) { 1857 return mSupplicantStaIfaceHal.startWpsPinDisplay(ifaceName, bssid); 1858 } 1859 1860 /** 1861 * Sets whether to use external sim for SIM/USIM processing. 1862 * 1863 * @param ifaceName Name of the interface. 1864 * @param external true to enable, false otherwise. 1865 * @return true if request is sent successfully, false otherwise. 1866 */ setExternalSim(@onNull String ifaceName, boolean external)1867 public boolean setExternalSim(@NonNull String ifaceName, boolean external) { 1868 return mSupplicantStaIfaceHal.setExternalSim(ifaceName, external); 1869 } 1870 1871 /** 1872 * Sim auth response types. 1873 */ 1874 public static final String SIM_AUTH_RESP_TYPE_GSM_AUTH = "GSM-AUTH"; 1875 public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTH = "UMTS-AUTH"; 1876 public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTS = "UMTS-AUTS"; 1877 1878 /** 1879 * EAP-SIM Error Codes 1880 */ 1881 public static final int EAP_SIM_NOT_SUBSCRIBED = 1031; 1882 public static final int EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED = 16385; 1883 1884 /** 1885 * Send the sim auth response for the currently configured network. 1886 * 1887 * @param ifaceName Name of the interface. 1888 * @param type |GSM-AUTH|, |UMTS-AUTH| or |UMTS-AUTS|. 1889 * @param response Response params. 1890 * @return true if succeeds, false otherwise. 1891 */ simAuthResponse( @onNull String ifaceName, int id, String type, String response)1892 public boolean simAuthResponse( 1893 @NonNull String ifaceName, int id, String type, String response) { 1894 if (SIM_AUTH_RESP_TYPE_GSM_AUTH.equals(type)) { 1895 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthResponse( 1896 ifaceName, response); 1897 } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTH.equals(type)) { 1898 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthResponse( 1899 ifaceName, response); 1900 } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTS.equals(type)) { 1901 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAutsResponse( 1902 ifaceName, response); 1903 } else { 1904 return false; 1905 } 1906 } 1907 1908 /** 1909 * Send the eap sim gsm auth failure for the currently configured network. 1910 * 1911 * @param ifaceName Name of the interface. 1912 * @return true if succeeds, false otherwise. 1913 */ simAuthFailedResponse(@onNull String ifaceName, int id)1914 public boolean simAuthFailedResponse(@NonNull String ifaceName, int id) { 1915 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthFailure(ifaceName); 1916 } 1917 1918 /** 1919 * Send the eap sim umts auth failure for the currently configured network. 1920 * 1921 * @param ifaceName Name of the interface. 1922 * @return true if succeeds, false otherwise. 1923 */ umtsAuthFailedResponse(@onNull String ifaceName, int id)1924 public boolean umtsAuthFailedResponse(@NonNull String ifaceName, int id) { 1925 return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthFailure(ifaceName); 1926 } 1927 1928 /** 1929 * Send the eap identity response for the currently configured network. 1930 * 1931 * @param ifaceName Name of the interface. 1932 * @param unencryptedResponse String to send. 1933 * @param encryptedResponse String to send. 1934 * @return true if succeeds, false otherwise. 1935 */ simIdentityResponse(@onNull String ifaceName, int id, String unencryptedResponse, String encryptedResponse)1936 public boolean simIdentityResponse(@NonNull String ifaceName, int id, 1937 String unencryptedResponse, String encryptedResponse) { 1938 return mSupplicantStaIfaceHal.sendCurrentNetworkEapIdentityResponse(ifaceName, 1939 unencryptedResponse, encryptedResponse); 1940 } 1941 1942 /** 1943 * This get anonymous identity from supplicant and returns it as a string. 1944 * 1945 * @param ifaceName Name of the interface. 1946 * @return anonymous identity string if succeeds, null otherwise. 1947 */ getEapAnonymousIdentity(@onNull String ifaceName)1948 public String getEapAnonymousIdentity(@NonNull String ifaceName) { 1949 return mSupplicantStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(ifaceName); 1950 } 1951 1952 /** 1953 * Start WPS pin registrar operation with the specified peer and pin. 1954 * 1955 * @param ifaceName Name of the interface. 1956 * @param bssid BSSID of the peer. 1957 * @param pin Pin to be used. 1958 * @return true if request is sent successfully, false otherwise. 1959 */ startWpsRegistrar(@onNull String ifaceName, String bssid, String pin)1960 public boolean startWpsRegistrar(@NonNull String ifaceName, String bssid, String pin) { 1961 return mSupplicantStaIfaceHal.startWpsRegistrar(ifaceName, bssid, pin); 1962 } 1963 1964 /** 1965 * Cancels any ongoing WPS requests. 1966 * 1967 * @param ifaceName Name of the interface. 1968 * @return true if request is sent successfully, false otherwise. 1969 */ cancelWps(@onNull String ifaceName)1970 public boolean cancelWps(@NonNull String ifaceName) { 1971 return mSupplicantStaIfaceHal.cancelWps(ifaceName); 1972 } 1973 1974 /** 1975 * Set WPS device name. 1976 * 1977 * @param ifaceName Name of the interface. 1978 * @param name String to be set. 1979 * @return true if request is sent successfully, false otherwise. 1980 */ setDeviceName(@onNull String ifaceName, String name)1981 public boolean setDeviceName(@NonNull String ifaceName, String name) { 1982 return mSupplicantStaIfaceHal.setWpsDeviceName(ifaceName, name); 1983 } 1984 1985 /** 1986 * Set WPS device type. 1987 * 1988 * @param ifaceName Name of the interface. 1989 * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg> 1990 * @return true if request is sent successfully, false otherwise. 1991 */ setDeviceType(@onNull String ifaceName, String type)1992 public boolean setDeviceType(@NonNull String ifaceName, String type) { 1993 return mSupplicantStaIfaceHal.setWpsDeviceType(ifaceName, type); 1994 } 1995 1996 /** 1997 * Set WPS config methods 1998 * 1999 * @param cfg List of config methods. 2000 * @return true if request is sent successfully, false otherwise. 2001 */ setConfigMethods(@onNull String ifaceName, String cfg)2002 public boolean setConfigMethods(@NonNull String ifaceName, String cfg) { 2003 return mSupplicantStaIfaceHal.setWpsConfigMethods(ifaceName, cfg); 2004 } 2005 2006 /** 2007 * Set WPS manufacturer. 2008 * 2009 * @param ifaceName Name of the interface. 2010 * @param value String to be set. 2011 * @return true if request is sent successfully, false otherwise. 2012 */ setManufacturer(@onNull String ifaceName, String value)2013 public boolean setManufacturer(@NonNull String ifaceName, String value) { 2014 return mSupplicantStaIfaceHal.setWpsManufacturer(ifaceName, value); 2015 } 2016 2017 /** 2018 * Set WPS model name. 2019 * 2020 * @param ifaceName Name of the interface. 2021 * @param value String to be set. 2022 * @return true if request is sent successfully, false otherwise. 2023 */ setModelName(@onNull String ifaceName, String value)2024 public boolean setModelName(@NonNull String ifaceName, String value) { 2025 return mSupplicantStaIfaceHal.setWpsModelName(ifaceName, value); 2026 } 2027 2028 /** 2029 * Set WPS model number. 2030 * 2031 * @param ifaceName Name of the interface. 2032 * @param value String to be set. 2033 * @return true if request is sent successfully, false otherwise. 2034 */ setModelNumber(@onNull String ifaceName, String value)2035 public boolean setModelNumber(@NonNull String ifaceName, String value) { 2036 return mSupplicantStaIfaceHal.setWpsModelNumber(ifaceName, value); 2037 } 2038 2039 /** 2040 * Set WPS serial number. 2041 * 2042 * @param ifaceName Name of the interface. 2043 * @param value String to be set. 2044 * @return true if request is sent successfully, false otherwise. 2045 */ setSerialNumber(@onNull String ifaceName, String value)2046 public boolean setSerialNumber(@NonNull String ifaceName, String value) { 2047 return mSupplicantStaIfaceHal.setWpsSerialNumber(ifaceName, value); 2048 } 2049 2050 /** 2051 * Enable or disable power save mode. 2052 * 2053 * @param ifaceName Name of the interface. 2054 * @param enabled true to enable, false to disable. 2055 */ setPowerSave(@onNull String ifaceName, boolean enabled)2056 public void setPowerSave(@NonNull String ifaceName, boolean enabled) { 2057 mSupplicantStaIfaceHal.setPowerSave(ifaceName, enabled); 2058 } 2059 2060 /** 2061 * Enable or disable low latency mode. 2062 * 2063 * @param enabled true to enable, false to disable. 2064 * @return true on success, false on failure 2065 */ setLowLatencyMode(boolean enabled)2066 public boolean setLowLatencyMode(boolean enabled) { 2067 return mWifiVendorHal.setLowLatencyMode(enabled); 2068 } 2069 2070 /** 2071 * Set concurrency priority between P2P & STA operations. 2072 * 2073 * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations, 2074 * false otherwise. 2075 * @return true if request is sent successfully, false otherwise. 2076 */ setConcurrencyPriority(boolean isStaHigherPriority)2077 public boolean setConcurrencyPriority(boolean isStaHigherPriority) { 2078 return mSupplicantStaIfaceHal.setConcurrencyPriority(isStaHigherPriority); 2079 } 2080 2081 /** 2082 * Enable/Disable auto reconnect functionality in wpa_supplicant. 2083 * 2084 * @param ifaceName Name of the interface. 2085 * @param enable true to enable auto reconnecting, false to disable. 2086 * @return true if request is sent successfully, false otherwise. 2087 */ enableStaAutoReconnect(@onNull String ifaceName, boolean enable)2088 public boolean enableStaAutoReconnect(@NonNull String ifaceName, boolean enable) { 2089 return mSupplicantStaIfaceHal.enableAutoReconnect(ifaceName, enable); 2090 } 2091 2092 /** 2093 * Migrate all the configured networks from wpa_supplicant. 2094 * 2095 * @param ifaceName Name of the interface. 2096 * @param configs Map of configuration key to configuration objects corresponding to all 2097 * the networks. 2098 * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf 2099 * @return Max priority of all the configs. 2100 */ migrateNetworksFromSupplicant( @onNull String ifaceName, Map<String, WifiConfiguration> configs, SparseArray<Map<String, String>> networkExtras)2101 public boolean migrateNetworksFromSupplicant( 2102 @NonNull String ifaceName, Map<String, WifiConfiguration> configs, 2103 SparseArray<Map<String, String>> networkExtras) { 2104 return mSupplicantStaIfaceHal.loadNetworks(ifaceName, configs, networkExtras); 2105 } 2106 2107 /** 2108 * Add the provided network configuration to wpa_supplicant and initiate connection to it. 2109 * This method does the following: 2110 * 1. Abort any ongoing scan to unblock the connection request. 2111 * 2. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect). 2112 * 3. Add a new network to wpa_supplicant. 2113 * 4. Save the provided configuration to wpa_supplicant. 2114 * 5. Select the new network in wpa_supplicant. 2115 * 6. Triggers reconnect command to wpa_supplicant. 2116 * 2117 * @param ifaceName Name of the interface. 2118 * @param configuration WifiConfiguration parameters for the provided network. 2119 * @return {@code true} if it succeeds, {@code false} otherwise 2120 */ connectToNetwork(@onNull String ifaceName, WifiConfiguration configuration)2121 public boolean connectToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) { 2122 // Abort ongoing scan before connect() to unblock connection request. 2123 mWificondControl.abortScan(ifaceName); 2124 return mSupplicantStaIfaceHal.connectToNetwork(ifaceName, configuration); 2125 } 2126 2127 /** 2128 * Initiates roaming to the already configured network in wpa_supplicant. If the network 2129 * configuration provided does not match the already configured network, then this triggers 2130 * a new connection attempt (instead of roam). 2131 * 1. Abort any ongoing scan to unblock the roam request. 2132 * 2. First check if we're attempting to connect to the same network as we currently have 2133 * configured. 2134 * 3. Set the new bssid for the network in wpa_supplicant. 2135 * 4. Triggers reassociate command to wpa_supplicant. 2136 * 2137 * @param ifaceName Name of the interface. 2138 * @param configuration WifiConfiguration parameters for the provided network. 2139 * @return {@code true} if it succeeds, {@code false} otherwise 2140 */ roamToNetwork(@onNull String ifaceName, WifiConfiguration configuration)2141 public boolean roamToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) { 2142 // Abort ongoing scan before connect() to unblock roaming request. 2143 mWificondControl.abortScan(ifaceName); 2144 return mSupplicantStaIfaceHal.roamToNetwork(ifaceName, configuration); 2145 } 2146 2147 /** 2148 * Remove all the networks. 2149 * 2150 * @param ifaceName Name of the interface. 2151 * @return {@code true} if it succeeds, {@code false} otherwise 2152 */ removeAllNetworks(@onNull String ifaceName)2153 public boolean removeAllNetworks(@NonNull String ifaceName) { 2154 return mSupplicantStaIfaceHal.removeAllNetworks(ifaceName); 2155 } 2156 2157 /** 2158 * Set the BSSID for the currently configured network in wpa_supplicant. 2159 * 2160 * @param ifaceName Name of the interface. 2161 * @return true if successful, false otherwise. 2162 */ setConfiguredNetworkBSSID(@onNull String ifaceName, String bssid)2163 public boolean setConfiguredNetworkBSSID(@NonNull String ifaceName, String bssid) { 2164 return mSupplicantStaIfaceHal.setCurrentNetworkBssid(ifaceName, bssid); 2165 } 2166 2167 /** 2168 * Initiate ANQP query. 2169 * 2170 * @param ifaceName Name of the interface. 2171 * @param bssid BSSID of the AP to be queried 2172 * @param anqpIds Set of anqp IDs. 2173 * @param hs20Subtypes Set of HS20 subtypes. 2174 * @return true on success, false otherwise. 2175 */ requestAnqp( @onNull String ifaceName, String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes)2176 public boolean requestAnqp( 2177 @NonNull String ifaceName, String bssid, Set<Integer> anqpIds, 2178 Set<Integer> hs20Subtypes) { 2179 if (bssid == null || ((anqpIds == null || anqpIds.isEmpty()) 2180 && (hs20Subtypes == null || hs20Subtypes.isEmpty()))) { 2181 Log.e(TAG, "Invalid arguments for ANQP request."); 2182 return false; 2183 } 2184 ArrayList<Short> anqpIdList = new ArrayList<>(); 2185 for (Integer anqpId : anqpIds) { 2186 anqpIdList.add(anqpId.shortValue()); 2187 } 2188 ArrayList<Integer> hs20SubtypeList = new ArrayList<>(); 2189 hs20SubtypeList.addAll(hs20Subtypes); 2190 return mSupplicantStaIfaceHal.initiateAnqpQuery( 2191 ifaceName, bssid, anqpIdList, hs20SubtypeList); 2192 } 2193 2194 /** 2195 * Request a passpoint icon file |filename| from the specified AP |bssid|. 2196 * 2197 * @param ifaceName Name of the interface. 2198 * @param bssid BSSID of the AP 2199 * @param fileName name of the icon file 2200 * @return true if request is sent successfully, false otherwise 2201 */ requestIcon(@onNull String ifaceName, String bssid, String fileName)2202 public boolean requestIcon(@NonNull String ifaceName, String bssid, String fileName) { 2203 if (bssid == null || fileName == null) { 2204 Log.e(TAG, "Invalid arguments for Icon request."); 2205 return false; 2206 } 2207 return mSupplicantStaIfaceHal.initiateHs20IconQuery(ifaceName, bssid, fileName); 2208 } 2209 2210 /** 2211 * Get the currently configured network's WPS NFC token. 2212 * 2213 * @param ifaceName Name of the interface. 2214 * @return Hex string corresponding to the WPS NFC token. 2215 */ getCurrentNetworkWpsNfcConfigurationToken(@onNull String ifaceName)2216 public String getCurrentNetworkWpsNfcConfigurationToken(@NonNull String ifaceName) { 2217 return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken(ifaceName); 2218 } 2219 2220 /** Remove the request |networkId| from supplicant if it's the current network, 2221 * if the current configured network matches |networkId|. 2222 * 2223 * @param ifaceName Name of the interface. 2224 * @param networkId network id of the network to be removed from supplicant. 2225 */ removeNetworkIfCurrent(@onNull String ifaceName, int networkId)2226 public void removeNetworkIfCurrent(@NonNull String ifaceName, int networkId) { 2227 mSupplicantStaIfaceHal.removeNetworkIfCurrent(ifaceName, networkId); 2228 } 2229 2230 /* 2231 * DPP 2232 */ 2233 2234 /** 2235 * Adds a DPP peer URI to the URI list. 2236 * 2237 * @param ifaceName Interface name 2238 * @param uri Bootstrap (URI) string (e.g. DPP:....) 2239 * @return ID, or -1 for failure 2240 */ addDppPeerUri(@onNull String ifaceName, @NonNull String uri)2241 public int addDppPeerUri(@NonNull String ifaceName, @NonNull String uri) { 2242 return mSupplicantStaIfaceHal.addDppPeerUri(ifaceName, uri); 2243 } 2244 2245 /** 2246 * Removes a DPP URI to the URI list given an ID. 2247 * 2248 * @param ifaceName Interface name 2249 * @param bootstrapId Bootstrap (URI) ID 2250 * @return true when operation is successful, or false for failure 2251 */ removeDppUri(@onNull String ifaceName, int bootstrapId)2252 public boolean removeDppUri(@NonNull String ifaceName, int bootstrapId) { 2253 return mSupplicantStaIfaceHal.removeDppUri(ifaceName, bootstrapId); 2254 } 2255 2256 /** 2257 * Stops/aborts DPP Initiator request 2258 * 2259 * @param ifaceName Interface name 2260 * @return true when operation is successful, or false for failure 2261 */ stopDppInitiator(@onNull String ifaceName)2262 public boolean stopDppInitiator(@NonNull String ifaceName) { 2263 return mSupplicantStaIfaceHal.stopDppInitiator(ifaceName); 2264 } 2265 2266 /** 2267 * Starts DPP Configurator-Initiator request 2268 * 2269 * @param ifaceName Interface name 2270 * @param peerBootstrapId Peer's bootstrap (URI) ID 2271 * @param ownBootstrapId Own bootstrap (URI) ID - Optional, 0 for none 2272 * @param ssid SSID of the selected network 2273 * @param password Password of the selected network, or 2274 * @param psk PSK of the selected network in hexadecimal representation 2275 * @param netRole The network role of the enrollee (STA or AP) 2276 * @param securityAkm Security AKM to use: PSK, SAE 2277 * @return true when operation is successful, or false for failure 2278 */ startDppConfiguratorInitiator(@onNull String ifaceName, int peerBootstrapId, int ownBootstrapId, @NonNull String ssid, String password, String psk, int netRole, int securityAkm)2279 public boolean startDppConfiguratorInitiator(@NonNull String ifaceName, int peerBootstrapId, 2280 int ownBootstrapId, @NonNull String ssid, String password, String psk, 2281 int netRole, int securityAkm) { 2282 return mSupplicantStaIfaceHal.startDppConfiguratorInitiator(ifaceName, peerBootstrapId, 2283 ownBootstrapId, ssid, password, psk, netRole, securityAkm); 2284 } 2285 2286 /** 2287 * Starts DPP Enrollee-Initiator request 2288 * 2289 * @param ifaceName Interface name 2290 * @param peerBootstrapId Peer's bootstrap (URI) ID 2291 * @param ownBootstrapId Own bootstrap (URI) ID - Optional, 0 for none 2292 * @return true when operation is successful, or false for failure 2293 */ startDppEnrolleeInitiator(@onNull String ifaceName, int peerBootstrapId, int ownBootstrapId)2294 public boolean startDppEnrolleeInitiator(@NonNull String ifaceName, int peerBootstrapId, 2295 int ownBootstrapId) { 2296 return mSupplicantStaIfaceHal.startDppEnrolleeInitiator(ifaceName, peerBootstrapId, 2297 ownBootstrapId); 2298 } 2299 2300 /** 2301 * Callback to notify about DPP success, failure and progress events. 2302 */ 2303 public interface DppEventCallback { 2304 /** 2305 * Called when local DPP Enrollee successfully receives a new Wi-Fi configuratrion from the 2306 * peer DPP configurator. 2307 * 2308 * @param newWifiConfiguration New Wi-Fi configuration received from the configurator 2309 */ onSuccessConfigReceived(WifiConfiguration newWifiConfiguration)2310 void onSuccessConfigReceived(WifiConfiguration newWifiConfiguration); 2311 2312 /** 2313 * Called when local DPP configurator successfully sends Wi-Fi configuration to a remote 2314 * Enrollee. 2315 */ onSuccessConfigSent()2316 void onSuccessConfigSent(); 2317 2318 /** 2319 * DPP Progress event. 2320 * 2321 * @param dppStatusCode Status code of the progress event. 2322 */ onProgress(int dppStatusCode)2323 void onProgress(int dppStatusCode); 2324 2325 /** 2326 * DPP Failure event. 2327 * 2328 * @param dppStatusCode Status code of the failure event. 2329 */ onFailure(int dppStatusCode)2330 void onFailure(int dppStatusCode); 2331 } 2332 2333 /** 2334 * Registers DPP event callbacks. 2335 * 2336 * @param dppEventCallback Callback object. 2337 */ registerDppEventCallback(DppEventCallback dppEventCallback)2338 public void registerDppEventCallback(DppEventCallback dppEventCallback) { 2339 mSupplicantStaIfaceHal.registerDppCallback(dppEventCallback); 2340 } 2341 2342 /******************************************************** 2343 * Vendor HAL operations 2344 ********************************************************/ 2345 /** 2346 * Callback to notify vendor HAL death. 2347 */ 2348 public interface VendorHalDeathEventHandler { 2349 /** 2350 * Invoked when the vendor HAL dies. 2351 */ onDeath()2352 void onDeath(); 2353 } 2354 2355 /** 2356 * Callback to notify when vendor HAL detects that a change in radio mode. 2357 */ 2358 public interface VendorHalRadioModeChangeEventHandler { 2359 /** 2360 * Invoked when the vendor HAL detects a change to MCC mode. 2361 * MCC (Multi channel concurrency) = Multiple interfaces are active on the same band, 2362 * different channels, same radios. 2363 * 2364 * @param band Band on which MCC is detected (specified by one of the 2365 * WifiScanner.WIFI_BAND_* constants) 2366 */ onMcc(int band)2367 void onMcc(int band); 2368 /** 2369 * Invoked when the vendor HAL detects a change to SCC mode. 2370 * SCC (Single channel concurrency) = Multiple interfaces are active on the same band, same 2371 * channels, same radios. 2372 * 2373 * @param band Band on which SCC is detected (specified by one of the 2374 * WifiScanner.WIFI_BAND_* constants) 2375 */ onScc(int band)2376 void onScc(int band); 2377 /** 2378 * Invoked when the vendor HAL detects a change to SBS mode. 2379 * SBS (Single Band Simultaneous) = Multiple interfaces are active on the same band, 2380 * different channels, different radios. 2381 * 2382 * @param band Band on which SBS is detected (specified by one of the 2383 * WifiScanner.WIFI_BAND_* constants) 2384 */ onSbs(int band)2385 void onSbs(int band); 2386 /** 2387 * Invoked when the vendor HAL detects a change to DBS mode. 2388 * DBS (Dual Band Simultaneous) = Multiple interfaces are active on the different bands, 2389 * different channels, different radios. 2390 */ onDbs()2391 void onDbs(); 2392 } 2393 2394 /** 2395 * Tests whether the HAL is running or not 2396 */ isHalStarted()2397 public boolean isHalStarted() { 2398 return mWifiVendorHal.isHalStarted(); 2399 } 2400 2401 // TODO: Change variable names to camel style. 2402 public static class ScanCapabilities { 2403 public int max_scan_cache_size; 2404 public int max_scan_buckets; 2405 public int max_ap_cache_per_scan; 2406 public int max_rssi_sample_size; 2407 public int max_scan_reporting_threshold; 2408 } 2409 2410 /** 2411 * Gets the scan capabilities 2412 * 2413 * @param ifaceName Name of the interface. 2414 * @param capabilities object to be filled in 2415 * @return true for success. false for failure 2416 */ getBgScanCapabilities( @onNull String ifaceName, ScanCapabilities capabilities)2417 public boolean getBgScanCapabilities( 2418 @NonNull String ifaceName, ScanCapabilities capabilities) { 2419 return mWifiVendorHal.getBgScanCapabilities(ifaceName, capabilities); 2420 } 2421 2422 public static class ChannelSettings { 2423 public int frequency; 2424 public int dwell_time_ms; 2425 public boolean passive; 2426 } 2427 2428 public static class BucketSettings { 2429 public int bucket; 2430 public int band; 2431 public int period_ms; 2432 public int max_period_ms; 2433 public int step_count; 2434 public int report_events; 2435 public int num_channels; 2436 public ChannelSettings[] channels; 2437 } 2438 2439 /** 2440 * Network parameters for hidden networks to be scanned for. 2441 */ 2442 public static class HiddenNetwork { 2443 public String ssid; 2444 2445 @Override equals(Object otherObj)2446 public boolean equals(Object otherObj) { 2447 if (this == otherObj) { 2448 return true; 2449 } else if (otherObj == null || getClass() != otherObj.getClass()) { 2450 return false; 2451 } 2452 HiddenNetwork other = (HiddenNetwork) otherObj; 2453 return Objects.equals(ssid, other.ssid); 2454 } 2455 2456 @Override hashCode()2457 public int hashCode() { 2458 return Objects.hash(ssid); 2459 } 2460 } 2461 2462 public static final int SCAN_TYPE_LOW_LATENCY = 0; 2463 public static final int SCAN_TYPE_LOW_POWER = 1; 2464 public static final int SCAN_TYPE_HIGH_ACCURACY = 2; 2465 2466 public static class ScanSettings { 2467 /** 2468 * Type of scan to perform. One of {@link ScanSettings#SCAN_TYPE_LOW_LATENCY}, 2469 * {@link ScanSettings#SCAN_TYPE_LOW_POWER} or {@link ScanSettings#SCAN_TYPE_HIGH_ACCURACY}. 2470 */ 2471 public int scanType; 2472 public int base_period_ms; 2473 public int max_ap_per_scan; 2474 public int report_threshold_percent; 2475 public int report_threshold_num_scans; 2476 public int num_buckets; 2477 /* Not used for bg scans. Only works for single scans. */ 2478 public HiddenNetwork[] hiddenNetworks; 2479 public BucketSettings[] buckets; 2480 } 2481 2482 /** 2483 * Network parameters to start PNO scan. 2484 */ 2485 public static class PnoNetwork { 2486 public String ssid; 2487 public byte flags; 2488 public byte auth_bit_field; 2489 public int[] frequencies; 2490 2491 @Override equals(Object otherObj)2492 public boolean equals(Object otherObj) { 2493 if (this == otherObj) { 2494 return true; 2495 } else if (otherObj == null || getClass() != otherObj.getClass()) { 2496 return false; 2497 } 2498 PnoNetwork other = (PnoNetwork) otherObj; 2499 return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags) 2500 && (auth_bit_field == other.auth_bit_field)) 2501 && Arrays.equals(frequencies, other.frequencies); 2502 } 2503 2504 @Override hashCode()2505 public int hashCode() { 2506 return Objects.hash(ssid, flags, auth_bit_field, frequencies); 2507 } 2508 } 2509 2510 /** 2511 * Parameters to start PNO scan. This holds the list of networks which are going to used for 2512 * PNO scan. 2513 */ 2514 public static class PnoSettings { 2515 public int min5GHzRssi; 2516 public int min24GHzRssi; 2517 public int initialScoreMax; 2518 public int currentConnectionBonus; 2519 public int sameNetworkBonus; 2520 public int secureBonus; 2521 public int band5GHzBonus; 2522 public int periodInMs; 2523 public boolean isConnected; 2524 public PnoNetwork[] networkList; 2525 } 2526 2527 public static interface ScanEventHandler { 2528 /** 2529 * Called for each AP as it is found with the entire contents of the beacon/probe response. 2530 * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified. 2531 */ onFullScanResult(ScanResult fullScanResult, int bucketsScanned)2532 void onFullScanResult(ScanResult fullScanResult, int bucketsScanned); 2533 /** 2534 * Callback on an event during a gscan scan. 2535 * See WifiNative.WIFI_SCAN_* for possible values. 2536 */ onScanStatus(int event)2537 void onScanStatus(int event); 2538 /** 2539 * Called with the current cached scan results when gscan is paused. 2540 */ onScanPaused(WifiScanner.ScanData[] data)2541 void onScanPaused(WifiScanner.ScanData[] data); 2542 /** 2543 * Called with the current cached scan results when gscan is resumed. 2544 */ onScanRestarted()2545 void onScanRestarted(); 2546 } 2547 2548 /** 2549 * Handler to notify the occurrence of various events during PNO scan. 2550 */ 2551 public interface PnoEventHandler { 2552 /** 2553 * Callback to notify when one of the shortlisted networks is found during PNO scan. 2554 * @param results List of Scan results received. 2555 */ onPnoNetworkFound(ScanResult[] results)2556 void onPnoNetworkFound(ScanResult[] results); 2557 2558 /** 2559 * Callback to notify when the PNO scan schedule fails. 2560 */ onPnoScanFailed()2561 void onPnoScanFailed(); 2562 } 2563 2564 public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0; 2565 public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1; 2566 public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2; 2567 public static final int WIFI_SCAN_FAILED = 3; 2568 2569 /** 2570 * Starts a background scan. 2571 * Any ongoing scan will be stopped first 2572 * 2573 * @param ifaceName Name of the interface. 2574 * @param settings to control the scan 2575 * @param eventHandler to call with the results 2576 * @return true for success 2577 */ startBgScan( @onNull String ifaceName, ScanSettings settings, ScanEventHandler eventHandler)2578 public boolean startBgScan( 2579 @NonNull String ifaceName, ScanSettings settings, ScanEventHandler eventHandler) { 2580 return mWifiVendorHal.startBgScan(ifaceName, settings, eventHandler); 2581 } 2582 2583 /** 2584 * Stops any ongoing backgound scan 2585 * @param ifaceName Name of the interface. 2586 */ stopBgScan(@onNull String ifaceName)2587 public void stopBgScan(@NonNull String ifaceName) { 2588 mWifiVendorHal.stopBgScan(ifaceName); 2589 } 2590 2591 /** 2592 * Pauses an ongoing backgound scan 2593 * @param ifaceName Name of the interface. 2594 */ pauseBgScan(@onNull String ifaceName)2595 public void pauseBgScan(@NonNull String ifaceName) { 2596 mWifiVendorHal.pauseBgScan(ifaceName); 2597 } 2598 2599 /** 2600 * Restarts a paused scan 2601 * @param ifaceName Name of the interface. 2602 */ restartBgScan(@onNull String ifaceName)2603 public void restartBgScan(@NonNull String ifaceName) { 2604 mWifiVendorHal.restartBgScan(ifaceName); 2605 } 2606 2607 /** 2608 * Gets the latest scan results received. 2609 * @param ifaceName Name of the interface. 2610 */ getBgScanResults(@onNull String ifaceName)2611 public WifiScanner.ScanData[] getBgScanResults(@NonNull String ifaceName) { 2612 return mWifiVendorHal.getBgScanResults(ifaceName); 2613 } 2614 2615 /** 2616 * Gets the latest link layer stats 2617 * @param ifaceName Name of the interface. 2618 */ getWifiLinkLayerStats(@onNull String ifaceName)2619 public WifiLinkLayerStats getWifiLinkLayerStats(@NonNull String ifaceName) { 2620 return mWifiVendorHal.getWifiLinkLayerStats(ifaceName); 2621 } 2622 2623 /** 2624 * Get the supported features 2625 * 2626 * @param ifaceName Name of the interface. 2627 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 2628 */ getSupportedFeatureSet(@onNull String ifaceName)2629 public long getSupportedFeatureSet(@NonNull String ifaceName) { 2630 synchronized (mLock) { 2631 Iface iface = mIfaceMgr.getIface(ifaceName); 2632 if (iface == null) { 2633 Log.e(TAG, "Could not get Iface object for interface " + ifaceName); 2634 return 0; 2635 } 2636 2637 return iface.featureSet; 2638 } 2639 } 2640 2641 /** 2642 * Get the supported features 2643 * 2644 * @param ifaceName Name of the interface. 2645 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 2646 */ getSupportedFeatureSetInternal(@onNull String ifaceName)2647 private long getSupportedFeatureSetInternal(@NonNull String ifaceName) { 2648 return mSupplicantStaIfaceHal.getAdvancedKeyMgmtCapabilities(ifaceName) 2649 | mWifiVendorHal.getSupportedFeatureSet(ifaceName); 2650 } 2651 2652 /** 2653 * Set the MAC OUI during scanning. 2654 * An OUI {Organizationally Unique Identifier} is a 24-bit number that 2655 * uniquely identifies a vendor or manufacturer. 2656 * 2657 * @param ifaceName Name of the interface. 2658 * @param oui OUI to set. 2659 * @return true for success 2660 */ setScanningMacOui(@onNull String ifaceName, byte[] oui)2661 public boolean setScanningMacOui(@NonNull String ifaceName, byte[] oui) { 2662 return mWifiVendorHal.setScanningMacOui(ifaceName, oui); 2663 } 2664 2665 /** 2666 * Get the APF (Android Packet Filter) capabilities of the device 2667 * @param ifaceName Name of the interface. 2668 */ getApfCapabilities(@onNull String ifaceName)2669 public ApfCapabilities getApfCapabilities(@NonNull String ifaceName) { 2670 return mWifiVendorHal.getApfCapabilities(ifaceName); 2671 } 2672 2673 /** 2674 * Installs an APF program on this iface, replacing any existing program. 2675 * 2676 * @param ifaceName Name of the interface 2677 * @param filter is the android packet filter program 2678 * @return true for success 2679 */ installPacketFilter(@onNull String ifaceName, byte[] filter)2680 public boolean installPacketFilter(@NonNull String ifaceName, byte[] filter) { 2681 return mWifiVendorHal.installPacketFilter(ifaceName, filter); 2682 } 2683 2684 /** 2685 * Reads the APF program and data buffer for this iface. 2686 * 2687 * @param ifaceName Name of the interface 2688 * @return the buffer returned by the driver, or null in case of an error 2689 */ readPacketFilter(@onNull String ifaceName)2690 public byte[] readPacketFilter(@NonNull String ifaceName) { 2691 return mWifiVendorHal.readPacketFilter(ifaceName); 2692 } 2693 2694 /** 2695 * Set country code for this AP iface. 2696 * @param ifaceName Name of the interface. 2697 * @param countryCode - two-letter country code (as ISO 3166) 2698 * @return true for success 2699 */ setCountryCodeHal(@onNull String ifaceName, String countryCode)2700 public boolean setCountryCodeHal(@NonNull String ifaceName, String countryCode) { 2701 return mWifiVendorHal.setCountryCodeHal(ifaceName, countryCode); 2702 } 2703 2704 //--------------------------------------------------------------------------------- 2705 /* Wifi Logger commands/events */ 2706 public static interface WifiLoggerEventHandler { onRingBufferData(RingBufferStatus status, byte[] buffer)2707 void onRingBufferData(RingBufferStatus status, byte[] buffer); onWifiAlert(int errorCode, byte[] buffer)2708 void onWifiAlert(int errorCode, byte[] buffer); 2709 } 2710 2711 /** 2712 * Registers the logger callback and enables alerts. 2713 * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked. 2714 * 2715 * @param handler Callback to be invoked. 2716 * @return true on success, false otherwise. 2717 */ setLoggingEventHandler(WifiLoggerEventHandler handler)2718 public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) { 2719 return mWifiVendorHal.setLoggingEventHandler(handler); 2720 } 2721 2722 /** 2723 * Control debug data collection 2724 * 2725 * @param verboseLevel 0 to 3, inclusive. 0 stops logging. 2726 * @param flags Ignored. 2727 * @param maxInterval Maximum interval between reports; ignore if 0. 2728 * @param minDataSize Minimum data size in buffer for report; ignore if 0. 2729 * @param ringName Name of the ring for which data collection is to start. 2730 * @return true for success, false otherwise. 2731 */ startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, int minDataSize, String ringName)2732 public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, 2733 int minDataSize, String ringName){ 2734 return mWifiVendorHal.startLoggingRingBuffer( 2735 verboseLevel, flags, maxInterval, minDataSize, ringName); 2736 } 2737 2738 /** 2739 * Logger features exposed. 2740 * This is a no-op now, will always return -1. 2741 * 2742 * @return true on success, false otherwise. 2743 */ getSupportedLoggerFeatureSet()2744 public int getSupportedLoggerFeatureSet() { 2745 return mWifiVendorHal.getSupportedLoggerFeatureSet(); 2746 } 2747 2748 /** 2749 * Stops all logging and resets the logger callback. 2750 * This stops both the alerts and ring buffer data collection. 2751 * @return true on success, false otherwise. 2752 */ resetLogHandler()2753 public boolean resetLogHandler() { 2754 return mWifiVendorHal.resetLogHandler(); 2755 } 2756 2757 /** 2758 * Vendor-provided wifi driver version string 2759 * 2760 * @return String returned from the HAL. 2761 */ getDriverVersion()2762 public String getDriverVersion() { 2763 return mWifiVendorHal.getDriverVersion(); 2764 } 2765 2766 /** 2767 * Vendor-provided wifi firmware version string 2768 * 2769 * @return String returned from the HAL. 2770 */ getFirmwareVersion()2771 public String getFirmwareVersion() { 2772 return mWifiVendorHal.getFirmwareVersion(); 2773 } 2774 2775 public static class RingBufferStatus{ 2776 String name; 2777 int flag; 2778 int ringBufferId; 2779 int ringBufferByteSize; 2780 int verboseLevel; 2781 int writtenBytes; 2782 int readBytes; 2783 int writtenRecords; 2784 2785 // Bit masks for interpreting |flag| 2786 public static final int HAS_BINARY_ENTRIES = (1 << 0); 2787 public static final int HAS_ASCII_ENTRIES = (1 << 1); 2788 public static final int HAS_PER_PACKET_ENTRIES = (1 << 2); 2789 2790 @Override toString()2791 public String toString() { 2792 return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId + 2793 " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel + 2794 " writtenBytes: " + writtenBytes + " readBytes: " + readBytes + 2795 " writtenRecords: " + writtenRecords; 2796 } 2797 } 2798 2799 /** 2800 * API to get the status of all ring buffers supported by driver 2801 */ getRingBufferStatus()2802 public RingBufferStatus[] getRingBufferStatus() { 2803 return mWifiVendorHal.getRingBufferStatus(); 2804 } 2805 2806 /** 2807 * Indicates to driver that all the data has to be uploaded urgently 2808 * 2809 * @param ringName Name of the ring buffer requested. 2810 * @return true on success, false otherwise. 2811 */ getRingBufferData(String ringName)2812 public boolean getRingBufferData(String ringName) { 2813 return mWifiVendorHal.getRingBufferData(ringName); 2814 } 2815 2816 /** 2817 * Request hal to flush ring buffers to files 2818 * 2819 * @return true on success, false otherwise. 2820 */ flushRingBufferData()2821 public boolean flushRingBufferData() { 2822 return mWifiVendorHal.flushRingBufferData(); 2823 } 2824 2825 /** 2826 * Request vendor debug info from the firmware 2827 * 2828 * @return Raw data obtained from the HAL. 2829 */ getFwMemoryDump()2830 public byte[] getFwMemoryDump() { 2831 return mWifiVendorHal.getFwMemoryDump(); 2832 } 2833 2834 /** 2835 * Request vendor debug info from the driver 2836 * 2837 * @return Raw data obtained from the HAL. 2838 */ getDriverStateDump()2839 public byte[] getDriverStateDump() { 2840 return mWifiVendorHal.getDriverStateDump(); 2841 } 2842 2843 //--------------------------------------------------------------------------------- 2844 /* Packet fate API */ 2845 2846 @Immutable 2847 abstract static class FateReport { 2848 final static int USEC_PER_MSEC = 1000; 2849 // The driver timestamp is a 32-bit counter, in microseconds. This field holds the 2850 // maximal value of a driver timestamp in milliseconds. 2851 final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000); 2852 final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS"); 2853 2854 final byte mFate; 2855 final long mDriverTimestampUSec; 2856 final byte mFrameType; 2857 final byte[] mFrameBytes; 2858 final long mEstimatedWallclockMSec; 2859 FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes)2860 FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 2861 mFate = fate; 2862 mDriverTimestampUSec = driverTimestampUSec; 2863 mEstimatedWallclockMSec = 2864 convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec); 2865 mFrameType = frameType; 2866 mFrameBytes = frameBytes; 2867 } 2868 toTableRowString()2869 public String toTableRowString() { 2870 StringWriter sw = new StringWriter(); 2871 PrintWriter pw = new PrintWriter(sw); 2872 FrameParser parser = new FrameParser(mFrameType, mFrameBytes); 2873 dateFormatter.setTimeZone(TimeZone.getDefault()); 2874 pw.format("%-15s %12s %-9s %-32s %-12s %-23s %s\n", 2875 mDriverTimestampUSec, 2876 dateFormatter.format(new Date(mEstimatedWallclockMSec)), 2877 directionToString(), fateToString(), parser.mMostSpecificProtocolString, 2878 parser.mTypeString, parser.mResultString); 2879 return sw.toString(); 2880 } 2881 toVerboseStringWithPiiAllowed()2882 public String toVerboseStringWithPiiAllowed() { 2883 StringWriter sw = new StringWriter(); 2884 PrintWriter pw = new PrintWriter(sw); 2885 FrameParser parser = new FrameParser(mFrameType, mFrameBytes); 2886 pw.format("Frame direction: %s\n", directionToString()); 2887 pw.format("Frame timestamp: %d\n", mDriverTimestampUSec); 2888 pw.format("Frame fate: %s\n", fateToString()); 2889 pw.format("Frame type: %s\n", frameTypeToString(mFrameType)); 2890 pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString); 2891 pw.format("Frame protocol type: %s\n", parser.mTypeString); 2892 pw.format("Frame length: %d\n", mFrameBytes.length); 2893 pw.append("Frame bytes"); 2894 pw.append(HexDump.dumpHexString(mFrameBytes)); // potentially contains PII 2895 pw.append("\n"); 2896 return sw.toString(); 2897 } 2898 2899 /* Returns a header to match the output of toTableRowString(). */ getTableHeader()2900 public static String getTableHeader() { 2901 StringWriter sw = new StringWriter(); 2902 PrintWriter pw = new PrintWriter(sw); 2903 pw.format("\n%-15s %-12s %-9s %-32s %-12s %-23s %s\n", 2904 "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result"); 2905 pw.format("%-15s %-12s %-9s %-32s %-12s %-23s %s\n", 2906 "---------", "--------", "---------", "----", "--------", "----", "------"); 2907 return sw.toString(); 2908 } 2909 directionToString()2910 protected abstract String directionToString(); 2911 fateToString()2912 protected abstract String fateToString(); 2913 frameTypeToString(byte frameType)2914 private static String frameTypeToString(byte frameType) { 2915 switch (frameType) { 2916 case WifiLoggerHal.FRAME_TYPE_UNKNOWN: 2917 return "unknown"; 2918 case WifiLoggerHal.FRAME_TYPE_ETHERNET_II: 2919 return "data"; 2920 case WifiLoggerHal.FRAME_TYPE_80211_MGMT: 2921 return "802.11 management"; 2922 default: 2923 return Byte.toString(frameType); 2924 } 2925 } 2926 2927 /** 2928 * Converts a driver timestamp to a wallclock time, based on the current 2929 * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of 2930 * microseconds, with the same base as BOOTTIME. 2931 */ convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec)2932 private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) { 2933 final long wallclockMillisNow = System.currentTimeMillis(); 2934 final long boottimeMillisNow = SystemClock.elapsedRealtime(); 2935 final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC; 2936 2937 long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC; 2938 if (boottimeTimestampMillis < driverTimestampMillis) { 2939 // The 32-bit microsecond count has wrapped between the time that the driver 2940 // recorded the packet, and the call to this function. Adjust the BOOTTIME 2941 // timestamp, to compensate. 2942 // 2943 // Note that overflow is not a concern here, since the result is less than 2944 // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above, 2945 // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since 2946 // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit 2947 // within a long. 2948 boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC; 2949 } 2950 2951 final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis; 2952 return wallclockMillisNow - millisSincePacketTimestamp; 2953 } 2954 } 2955 2956 /** 2957 * Represents the fate information for one outbound packet. 2958 */ 2959 @Immutable 2960 public static final class TxFateReport extends FateReport { TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes)2961 TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 2962 super(fate, driverTimestampUSec, frameType, frameBytes); 2963 } 2964 2965 @Override directionToString()2966 protected String directionToString() { 2967 return "TX"; 2968 } 2969 2970 @Override fateToString()2971 protected String fateToString() { 2972 switch (mFate) { 2973 case WifiLoggerHal.TX_PKT_FATE_ACKED: 2974 return "acked"; 2975 case WifiLoggerHal.TX_PKT_FATE_SENT: 2976 return "sent"; 2977 case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED: 2978 return "firmware queued"; 2979 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID: 2980 return "firmware dropped (invalid frame)"; 2981 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS: 2982 return "firmware dropped (no bufs)"; 2983 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER: 2984 return "firmware dropped (other)"; 2985 case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED: 2986 return "driver queued"; 2987 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID: 2988 return "driver dropped (invalid frame)"; 2989 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS: 2990 return "driver dropped (no bufs)"; 2991 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER: 2992 return "driver dropped (other)"; 2993 default: 2994 return Byte.toString(mFate); 2995 } 2996 } 2997 } 2998 2999 /** 3000 * Represents the fate information for one inbound packet. 3001 */ 3002 @Immutable 3003 public static final class RxFateReport extends FateReport { RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes)3004 RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) { 3005 super(fate, driverTimestampUSec, frameType, frameBytes); 3006 } 3007 3008 @Override directionToString()3009 protected String directionToString() { 3010 return "RX"; 3011 } 3012 3013 @Override fateToString()3014 protected String fateToString() { 3015 switch (mFate) { 3016 case WifiLoggerHal.RX_PKT_FATE_SUCCESS: 3017 return "success"; 3018 case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED: 3019 return "firmware queued"; 3020 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER: 3021 return "firmware dropped (filter)"; 3022 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID: 3023 return "firmware dropped (invalid frame)"; 3024 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS: 3025 return "firmware dropped (no bufs)"; 3026 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER: 3027 return "firmware dropped (other)"; 3028 case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED: 3029 return "driver queued"; 3030 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER: 3031 return "driver dropped (filter)"; 3032 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID: 3033 return "driver dropped (invalid frame)"; 3034 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS: 3035 return "driver dropped (no bufs)"; 3036 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER: 3037 return "driver dropped (other)"; 3038 default: 3039 return Byte.toString(mFate); 3040 } 3041 } 3042 } 3043 3044 /** 3045 * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started. 3046 * 3047 * @param ifaceName Name of the interface. 3048 * @return true for success, false otherwise. 3049 */ startPktFateMonitoring(@onNull String ifaceName)3050 public boolean startPktFateMonitoring(@NonNull String ifaceName) { 3051 return mWifiVendorHal.startPktFateMonitoring(ifaceName); 3052 } 3053 3054 /** 3055 * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started. 3056 * 3057 * @param ifaceName Name of the interface. 3058 * @return true for success, false otherwise. 3059 */ getTxPktFates(@onNull String ifaceName, TxFateReport[] reportBufs)3060 public boolean getTxPktFates(@NonNull String ifaceName, TxFateReport[] reportBufs) { 3061 return mWifiVendorHal.getTxPktFates(ifaceName, reportBufs); 3062 } 3063 3064 /** 3065 * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started. 3066 * @param ifaceName Name of the interface. 3067 */ getRxPktFates(@onNull String ifaceName, RxFateReport[] reportBufs)3068 public boolean getRxPktFates(@NonNull String ifaceName, RxFateReport[] reportBufs) { 3069 return mWifiVendorHal.getRxPktFates(ifaceName, reportBufs); 3070 } 3071 3072 /** 3073 * Get the tx packet counts for the interface. 3074 * 3075 * @param ifaceName Name of the interface. 3076 * @return tx packet counts 3077 */ getTxPackets(@onNull String ifaceName)3078 public long getTxPackets(@NonNull String ifaceName) { 3079 return TrafficStats.getTxPackets(ifaceName); 3080 } 3081 3082 /** 3083 * Get the rx packet counts for the interface. 3084 * 3085 * @param ifaceName Name of the interface 3086 * @return rx packet counts 3087 */ getRxPackets(@onNull String ifaceName)3088 public long getRxPackets(@NonNull String ifaceName) { 3089 return TrafficStats.getRxPackets(ifaceName); 3090 } 3091 3092 /** 3093 * Start sending the specified keep alive packets periodically. 3094 * 3095 * @param ifaceName Name of the interface. 3096 * @param slot Integer used to identify each request. 3097 * @param dstMac Destination MAC Address 3098 * @param packet Raw packet contents to send. 3099 * @param protocol The ethernet protocol type 3100 * @param period Period to use for sending these packets. 3101 * @return 0 for success, -1 for error 3102 */ startSendingOffloadedPacket(@onNull String ifaceName, int slot, byte[] dstMac, byte[] packet, int protocol, int period)3103 public int startSendingOffloadedPacket(@NonNull String ifaceName, int slot, 3104 byte[] dstMac, byte[] packet, int protocol, int period) { 3105 byte[] srcMac = NativeUtil.macAddressToByteArray(getMacAddress(ifaceName)); 3106 return mWifiVendorHal.startSendingOffloadedPacket( 3107 ifaceName, slot, srcMac, dstMac, packet, protocol, period); 3108 } 3109 3110 /** 3111 * Stop sending the specified keep alive packets. 3112 * 3113 * @param ifaceName Name of the interface. 3114 * @param slot id - same as startSendingOffloadedPacket call. 3115 * @return 0 for success, -1 for error 3116 */ stopSendingOffloadedPacket(@onNull String ifaceName, int slot)3117 public int stopSendingOffloadedPacket(@NonNull String ifaceName, int slot) { 3118 return mWifiVendorHal.stopSendingOffloadedPacket(ifaceName, slot); 3119 } 3120 3121 public static interface WifiRssiEventHandler { onRssiThresholdBreached(byte curRssi)3122 void onRssiThresholdBreached(byte curRssi); 3123 } 3124 3125 /** 3126 * Start RSSI monitoring on the currently connected access point. 3127 * 3128 * @param ifaceName Name of the interface. 3129 * @param maxRssi Maximum RSSI threshold. 3130 * @param minRssi Minimum RSSI threshold. 3131 * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi 3132 * @return 0 for success, -1 for failure 3133 */ startRssiMonitoring( @onNull String ifaceName, byte maxRssi, byte minRssi, WifiRssiEventHandler rssiEventHandler)3134 public int startRssiMonitoring( 3135 @NonNull String ifaceName, byte maxRssi, byte minRssi, 3136 WifiRssiEventHandler rssiEventHandler) { 3137 return mWifiVendorHal.startRssiMonitoring( 3138 ifaceName, maxRssi, minRssi, rssiEventHandler); 3139 } 3140 3141 /** 3142 * Stop RSSI monitoring on the currently connected access point. 3143 * 3144 * @param ifaceName Name of the interface. 3145 * @return 0 for success, -1 for failure 3146 */ stopRssiMonitoring(@onNull String ifaceName)3147 public int stopRssiMonitoring(@NonNull String ifaceName) { 3148 return mWifiVendorHal.stopRssiMonitoring(ifaceName); 3149 } 3150 3151 /** 3152 * Fetch the host wakeup reasons stats from wlan driver. 3153 * 3154 * @return the |WlanWakeReasonAndCounts| object retrieved from the wlan driver. 3155 */ getWlanWakeReasonCount()3156 public WlanWakeReasonAndCounts getWlanWakeReasonCount() { 3157 return mWifiVendorHal.getWlanWakeReasonCount(); 3158 } 3159 3160 /** 3161 * Enable/Disable Neighbour discovery offload functionality in the firmware. 3162 * 3163 * @param ifaceName Name of the interface. 3164 * @param enabled true to enable, false to disable. 3165 * @return true for success, false otherwise. 3166 */ configureNeighborDiscoveryOffload(@onNull String ifaceName, boolean enabled)3167 public boolean configureNeighborDiscoveryOffload(@NonNull String ifaceName, boolean enabled) { 3168 return mWifiVendorHal.configureNeighborDiscoveryOffload(ifaceName, enabled); 3169 } 3170 3171 // Firmware roaming control. 3172 3173 /** 3174 * Class to retrieve firmware roaming capability parameters. 3175 */ 3176 public static class RoamingCapabilities { 3177 public int maxBlocklistSize; 3178 public int maxAllowlistSize; 3179 } 3180 3181 /** 3182 * Query the firmware roaming capabilities. 3183 * @param ifaceName Name of the interface. 3184 * @return true for success, false otherwise. 3185 */ getRoamingCapabilities( @onNull String ifaceName, RoamingCapabilities capabilities)3186 public boolean getRoamingCapabilities( 3187 @NonNull String ifaceName, RoamingCapabilities capabilities) { 3188 return mWifiVendorHal.getRoamingCapabilities(ifaceName, capabilities); 3189 } 3190 3191 /** 3192 * Macros for controlling firmware roaming. 3193 */ 3194 public static final int DISABLE_FIRMWARE_ROAMING = 0; 3195 public static final int ENABLE_FIRMWARE_ROAMING = 1; 3196 3197 /** 3198 * Indicates success for enableFirmwareRoaming 3199 */ 3200 public static final int SET_FIRMWARE_ROAMING_SUCCESS = 0; 3201 3202 /** 3203 * Indicates failure for enableFirmwareRoaming 3204 */ 3205 public static final int SET_FIRMWARE_ROAMING_FAILURE = 1; 3206 3207 /** 3208 * Indicates temporary failure for enableFirmwareRoaming - try again later 3209 */ 3210 public static final int SET_FIRMWARE_ROAMING_BUSY = 2; 3211 3212 /** 3213 * Enable/disable firmware roaming. 3214 * 3215 * @param ifaceName Name of the interface. 3216 * @return SET_FIRMWARE_ROAMING_SUCCESS, SET_FIRMWARE_ROAMING_FAILURE, 3217 * or SET_FIRMWARE_ROAMING_BUSY 3218 */ enableFirmwareRoaming(@onNull String ifaceName, int state)3219 public int enableFirmwareRoaming(@NonNull String ifaceName, int state) { 3220 return mWifiVendorHal.enableFirmwareRoaming(ifaceName, state); 3221 } 3222 3223 /** 3224 * Class for specifying the roaming configurations. 3225 */ 3226 public static class RoamingConfig { 3227 public ArrayList<String> blocklistBssids; 3228 public ArrayList<String> allowlistSsids; 3229 } 3230 3231 /** 3232 * Set firmware roaming configurations. 3233 * @param ifaceName Name of the interface. 3234 */ configureRoaming(@onNull String ifaceName, RoamingConfig config)3235 public boolean configureRoaming(@NonNull String ifaceName, RoamingConfig config) { 3236 return mWifiVendorHal.configureRoaming(ifaceName, config); 3237 } 3238 3239 /** 3240 * Reset firmware roaming configuration. 3241 * @param ifaceName Name of the interface. 3242 */ resetRoamingConfiguration(@onNull String ifaceName)3243 public boolean resetRoamingConfiguration(@NonNull String ifaceName) { 3244 // Pass in an empty RoamingConfig object which translates to zero size 3245 // blacklist and whitelist to reset the firmware roaming configuration. 3246 return mWifiVendorHal.configureRoaming(ifaceName, new RoamingConfig()); 3247 } 3248 3249 /** 3250 * Select one of the pre-configured transmit power level scenarios or reset it back to normal. 3251 * Primarily used for meeting SAR requirements. 3252 * 3253 * @param sarInfo The collection of inputs used to select the SAR scenario. 3254 * @return true for success; false for failure or if the HAL version does not support this API. 3255 */ selectTxPowerScenario(SarInfo sarInfo)3256 public boolean selectTxPowerScenario(SarInfo sarInfo) { 3257 return mWifiVendorHal.selectTxPowerScenario(sarInfo); 3258 } 3259 3260 /******************************************************** 3261 * JNI operations 3262 ********************************************************/ 3263 /* Register native functions */ 3264 static { 3265 /* Native functions are defined in libwifi-service.so */ 3266 System.loadLibrary("wifi-service"); registerNatives()3267 registerNatives(); 3268 } 3269 registerNatives()3270 private static native int registerNatives(); 3271 /* kernel logging support */ readKernelLogNative()3272 private static native byte[] readKernelLogNative(); 3273 3274 /** 3275 * Fetches the latest kernel logs. 3276 */ readKernelLog()3277 public synchronized String readKernelLog() { 3278 byte[] bytes = readKernelLogNative(); 3279 if (bytes != null) { 3280 CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder(); 3281 try { 3282 CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes)); 3283 return decoded.toString(); 3284 } catch (CharacterCodingException cce) { 3285 return new String(bytes, StandardCharsets.ISO_8859_1); 3286 } 3287 } else { 3288 return "*** failed to read kernel log ***"; 3289 } 3290 } 3291 } 3292