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