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