SupplicantStaIfaceHal.java revision dd2434e5075a5459d6daad3ae3adfbd06f67344a
1/* 2 * Copyright (C) 2017 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 */ 16package com.android.server.wifi; 17 18import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQP3GPPNetwork; 19import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPDomName; 20import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPIPAddrAvailability; 21import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPNAIRealm; 22import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPRoamingConsortium; 23import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPVenueName; 24import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSConnCapability; 25import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSFriendlyName; 26import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSOSUProviders; 27import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSWANMetrics; 28 29import android.content.Context; 30import android.hardware.wifi.supplicant.V1_0.ISupplicant; 31import android.hardware.wifi.supplicant.V1_0.ISupplicantIface; 32import android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork; 33import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface; 34import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; 35import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; 36import android.hardware.wifi.supplicant.V1_0.IfaceType; 37import android.hardware.wifi.supplicant.V1_0.SupplicantStatus; 38import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; 39import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; 40import android.hidl.manager.V1_0.IServiceManager; 41import android.hidl.manager.V1_0.IServiceNotification; 42import android.net.IpConfiguration; 43import android.net.wifi.SupplicantState; 44import android.net.wifi.WifiConfiguration; 45import android.net.wifi.WifiSsid; 46import android.os.RemoteException; 47import android.util.Log; 48import android.util.SparseArray; 49 50import com.android.server.wifi.hotspot2.AnqpEvent; 51import com.android.server.wifi.hotspot2.IconEvent; 52import com.android.server.wifi.hotspot2.WnmData; 53import com.android.server.wifi.hotspot2.anqp.ANQPElement; 54import com.android.server.wifi.hotspot2.anqp.ANQPParser; 55import com.android.server.wifi.hotspot2.anqp.Constants; 56import com.android.server.wifi.util.NativeUtil; 57 58import java.io.IOException; 59import java.nio.BufferUnderflowException; 60import java.nio.ByteBuffer; 61import java.nio.ByteOrder; 62import java.util.ArrayList; 63import java.util.HashMap; 64import java.util.List; 65import java.util.Map; 66import java.util.regex.Matcher; 67import java.util.regex.Pattern; 68 69/** 70 * Hal calls for bring up/shut down of the supplicant daemon and for 71 * sending requests to the supplicant daemon 72 */ 73public class SupplicantStaIfaceHal { 74 private static final String TAG = "SupplicantStaIfaceHal"; 75 /** 76 * Regex pattern for extracting the wps device type bytes. 77 * Matches a strings like the following: "<categ>-<OUI>-<subcateg>"; 78 */ 79 private static final Pattern WPS_DEVICE_TYPE_PATTERN = 80 Pattern.compile("^(\\d{1,2})-([0-9a-fA-F]{8})-(\\d{1,2})$"); 81 82 private boolean mVerboseLoggingEnabled = false; 83 private IServiceManager mIServiceManager = null; 84 // Supplicant HAL interface objects 85 private ISupplicant mISupplicant; 86 private ISupplicantStaIface mISupplicantStaIface; 87 private ISupplicantStaIfaceCallback mISupplicantStaIfaceCallback; 88 private final IServiceNotification mServiceNotificationCallback = 89 new IServiceNotification.Stub() { 90 public void onRegistration(String fqName, String name, boolean preexisting) { 91 synchronized (mLock) { 92 if (mVerboseLoggingEnabled) { 93 Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName 94 + ", " + name + " preexisting=" + preexisting); 95 } 96 if (!initSupplicantService() || !initSupplicantStaIface()) { 97 Log.e(TAG, "initalizing ISupplicantIfaces failed."); 98 supplicantServiceDiedHandler(); 99 } else { 100 Log.i(TAG, "Completed initialization of ISupplicant interfaces."); 101 } 102 } 103 } 104 }; 105 private String mIfaceName; 106 // Currently configured network in wpa_supplicant 107 private SupplicantStaNetworkHal mCurrentNetwork; 108 // Currently configured network's framework network Id. 109 private int mFrameworkNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 110 private final Object mLock = new Object(); 111 private final Context mContext; 112 private final WifiMonitor mWifiMonitor; 113 114 public SupplicantStaIfaceHal(Context context, WifiMonitor monitor) { 115 mContext = context; 116 mWifiMonitor = monitor; 117 mISupplicantStaIfaceCallback = new SupplicantStaIfaceHalCallback(); 118 } 119 120 /** 121 * Enable/Disable verbose logging. 122 * 123 * @param enable true to enable, false to disable. 124 */ 125 void enableVerboseLogging(boolean enable) { 126 mVerboseLoggingEnabled = enable; 127 } 128 129 private boolean linkToServiceManagerDeath() { 130 if (mIServiceManager == null) return false; 131 try { 132 if (!mIServiceManager.linkToDeath(cookie -> { 133 Log.w(TAG, "IServiceManager died: cookie=" + cookie); 134 synchronized (mLock) { 135 supplicantServiceDiedHandler(); 136 mIServiceManager = null; // Will need to register a new ServiceNotification 137 } 138 }, 0)) { 139 Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); 140 supplicantServiceDiedHandler(); 141 mIServiceManager = null; // Will need to register a new ServiceNotification 142 return false; 143 } 144 } catch (RemoteException e) { 145 Log.e(TAG, "IServiceManager.linkToDeath exception", e); 146 return false; 147 } 148 return true; 149 } 150 151 /** 152 * Registers a service notification for the ISupplicant service, which triggers intialization of 153 * the ISupplicantStaIface 154 * @return true if the service notification was successfully registered 155 */ 156 public boolean initialize() { 157 if (mVerboseLoggingEnabled) Log.i(TAG, "Registering ISupplicant service ready callback."); 158 synchronized (mLock) { 159 mISupplicant = null; 160 mISupplicantStaIface = null; 161 if (mIServiceManager != null) { 162 // Already have an IServiceManager and serviceNotification registered, don't 163 // don't register another. 164 return true; 165 } 166 try { 167 mIServiceManager = getServiceManagerMockable(); 168 if (mIServiceManager == null) { 169 Log.e(TAG, "Failed to get HIDL Service Manager"); 170 return false; 171 } 172 if (!linkToServiceManagerDeath()) { 173 return false; 174 } 175 /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it 176 exists */ 177 if (!mIServiceManager.registerForNotifications( 178 ISupplicant.kInterfaceName, "", mServiceNotificationCallback)) { 179 Log.e(TAG, "Failed to register for notifications to " 180 + ISupplicant.kInterfaceName); 181 mIServiceManager = null; // Will need to register a new ServiceNotification 182 return false; 183 } 184 } catch (RemoteException e) { 185 Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: " 186 + e); 187 supplicantServiceDiedHandler(); 188 } 189 return true; 190 } 191 } 192 193 private boolean linkToSupplicantDeath() { 194 if (mISupplicant == null) return false; 195 try { 196 if (!mISupplicant.linkToDeath(cookie -> { 197 Log.w(TAG, "ISupplicant died: cookie=" + cookie); 198 synchronized (mLock) { 199 supplicantServiceDiedHandler(); 200 } 201 }, 0)) { 202 Log.wtf(TAG, "Error on linkToDeath on ISupplicant"); 203 supplicantServiceDiedHandler(); 204 return false; 205 } 206 } catch (RemoteException e) { 207 Log.e(TAG, "ISupplicant.linkToDeath exception", e); 208 return false; 209 } 210 return true; 211 } 212 213 private boolean initSupplicantService() { 214 synchronized (mLock) { 215 try { 216 mISupplicant = getSupplicantMockable(); 217 } catch (RemoteException e) { 218 Log.e(TAG, "ISupplicant.getService exception: " + e); 219 return false; 220 } 221 if (mISupplicant == null) { 222 Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup"); 223 return false; 224 } 225 if (!linkToSupplicantDeath()) { 226 return false; 227 } 228 } 229 return true; 230 } 231 232 private boolean linkToSupplicantStaIfaceDeath() { 233 if (mISupplicantStaIface == null) return false; 234 try { 235 if (!mISupplicantStaIface.linkToDeath(cookie -> { 236 Log.w(TAG, "ISupplicantStaIface died: cookie=" + cookie); 237 synchronized (mLock) { 238 supplicantServiceDiedHandler(); 239 } 240 }, 0)) { 241 Log.wtf(TAG, "Error on linkToDeath on ISupplicantStaIface"); 242 supplicantServiceDiedHandler(); 243 return false; 244 } 245 } catch (RemoteException e) { 246 Log.e(TAG, "ISupplicantStaIface.linkToDeath exception", e); 247 return false; 248 } 249 return true; 250 } 251 252 private boolean initSupplicantStaIface() { 253 synchronized (mLock) { 254 /** List all supplicant Ifaces */ 255 final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>(); 256 try { 257 mISupplicant.listInterfaces((SupplicantStatus status, 258 ArrayList<ISupplicant.IfaceInfo> ifaces) -> { 259 if (status.code != SupplicantStatusCode.SUCCESS) { 260 Log.e(TAG, "Getting Supplicant Interfaces failed: " + status.code); 261 return; 262 } 263 supplicantIfaces.addAll(ifaces); 264 }); 265 } catch (RemoteException e) { 266 Log.e(TAG, "ISupplicant.listInterfaces exception: " + e); 267 return false; 268 } 269 if (supplicantIfaces.size() == 0) { 270 Log.e(TAG, "Got zero HIDL supplicant ifaces. Stopping supplicant HIDL startup."); 271 return false; 272 } 273 Mutable<ISupplicantIface> supplicantIface = new Mutable<>(); 274 Mutable<String> ifaceName = new Mutable<>(); 275 for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) { 276 if (ifaceInfo.type == IfaceType.STA) { 277 try { 278 mISupplicant.getInterface(ifaceInfo, 279 (SupplicantStatus status, ISupplicantIface iface) -> { 280 if (status.code != SupplicantStatusCode.SUCCESS) { 281 Log.e(TAG, "Failed to get ISupplicantIface " + status.code); 282 return; 283 } 284 supplicantIface.value = iface; 285 }); 286 } catch (RemoteException e) { 287 Log.e(TAG, "ISupplicant.getInterface exception: " + e); 288 return false; 289 } 290 ifaceName.value = ifaceInfo.name; 291 break; 292 } 293 } 294 if (supplicantIface.value == null) { 295 Log.e(TAG, "initSupplicantStaIface got null iface"); 296 return false; 297 } 298 mISupplicantStaIface = getStaIfaceMockable(supplicantIface.value); 299 mIfaceName = ifaceName.value; 300 if (!linkToSupplicantStaIfaceDeath()) { 301 return false; 302 } 303 if (!registerCallback(mISupplicantStaIfaceCallback)) { 304 return false; 305 } 306 return true; 307 } 308 } 309 310 private void supplicantServiceDiedHandler() { 311 synchronized (mLock) { 312 mISupplicant = null; 313 mISupplicantStaIface = null; 314 mWifiMonitor.broadcastSupplicantDisconnectionEvent(mIfaceName); 315 } 316 } 317 318 /** 319 * Signals whether Initialization completed successfully. 320 */ 321 public boolean isInitializationStarted() { 322 return mIServiceManager != null; 323 } 324 325 /** 326 * Signals whether Initialization completed successfully. 327 */ 328 public boolean isInitializationComplete() { 329 return mISupplicantStaIface != null; 330 } 331 332 /** 333 * Wrapper functions to access static HAL methods, created to be mockable in unit tests 334 */ 335 protected IServiceManager getServiceManagerMockable() throws RemoteException { 336 return IServiceManager.getService(); 337 } 338 339 protected ISupplicant getSupplicantMockable() throws RemoteException { 340 return ISupplicant.getService(); 341 } 342 343 protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) { 344 return ISupplicantStaIface.asInterface(iface.asBinder()); 345 } 346 347 /** 348 * Add a network configuration to wpa_supplicant. 349 * 350 * @param config Config corresponding to the network. 351 * @return SupplicantStaNetwork of the added network in wpa_supplicant. 352 */ 353 private SupplicantStaNetworkHal addNetwork(WifiConfiguration config) { 354 logi("addSupplicantStaNetwork via HIDL"); 355 if (config == null) { 356 loge("Cannot add NULL network!"); 357 return null; 358 } 359 SupplicantStaNetworkHal network = addNetwork(); 360 if (network == null) { 361 loge("Failed to add a network!"); 362 return null; 363 } 364 if (!network.saveWifiConfiguration(config)) { 365 loge("Failed to save variables for: " + config.configKey()); 366 if (!removeAllNetworks()) { 367 loge("Failed to remove all networks on failure."); 368 } 369 return null; 370 } 371 return network; 372 } 373 374 /** 375 * Add the provided network configuration to wpa_supplicant and initiate connection to it. 376 * This method does the following: 377 * 1. Triggers disconnect command to wpa_supplicant (if |shouldDisconnect| is true). 378 * 2. Remove any existing network in wpa_supplicant. 379 * 3. Add a new network to wpa_supplicant. 380 * 4. Save the provided configuration to wpa_supplicant. 381 * 5. Select the new network in wpa_supplicant. 382 * 383 * @param config WifiConfiguration parameters for the provided network. 384 * @param shouldDisconnect whether to trigger a disconnection or not. 385 * @return {@code true} if it succeeds, {@code false} otherwise 386 */ 387 public boolean connectToNetwork(WifiConfiguration config, boolean shouldDisconnect) { 388 mFrameworkNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 389 mCurrentNetwork = null; 390 logd("connectToNetwork " + config.configKey() 391 + " (shouldDisconnect " + shouldDisconnect + ")"); 392 if (shouldDisconnect && !disconnect()) { 393 loge("Failed to trigger disconnect"); 394 return false; 395 } 396 if (!removeAllNetworks()) { 397 loge("Failed to remove existing networks"); 398 return false; 399 } 400 mCurrentNetwork = addNetwork(config); 401 if (mCurrentNetwork == null) { 402 loge("Failed to add/save network configuration: " + config.configKey()); 403 return false; 404 } 405 if (!mCurrentNetwork.select()) { 406 loge("Failed to select network configuration: " + config.configKey()); 407 return false; 408 } 409 mFrameworkNetworkId = config.networkId; 410 return true; 411 } 412 413 /** 414 * Initiates roaming to the already configured network in wpa_supplicant. If the network 415 * configuration provided does not match the already configured network, then this triggers 416 * a new connection attempt (instead of roam). 417 * 1. First check if we're attempting to connect to the same network as we currently have 418 * configured. 419 * 2. Set the new bssid for the network in wpa_supplicant. 420 * 3. Trigger reassociate command to wpa_supplicant. 421 * 422 * @param config WifiConfiguration parameters for the provided network. 423 * @return {@code true} if it succeeds, {@code false} otherwise 424 */ 425 public boolean roamToNetwork(WifiConfiguration config) { 426 if (mFrameworkNetworkId != config.networkId || mCurrentNetwork == null) { 427 Log.w(TAG, "Cannot roam to a different network, initiate new connection. " 428 + "Current network ID: " + mFrameworkNetworkId); 429 return connectToNetwork(config, false); 430 } 431 String bssid = config.getNetworkSelectionStatus().getNetworkSelectionBSSID(); 432 logd("roamToNetwork" + config.configKey() + " (bssid " + bssid + ")"); 433 if (!mCurrentNetwork.setBssid(bssid)) { 434 loge("Failed to set new bssid on network: " + config.configKey()); 435 return false; 436 } 437 if (!reassociate()) { 438 loge("Failed to trigger reassociate"); 439 return false; 440 } 441 return true; 442 } 443 444 /** 445 * Load all the configured networks from wpa_supplicant. 446 * 447 * @param configs Map of configuration key to configuration objects corresponding to all 448 * the networks. 449 * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf 450 * @return true if succeeds, false otherwise. 451 */ 452 public boolean loadNetworks(Map<String, WifiConfiguration> configs, 453 SparseArray<Map<String, String>> networkExtras) { 454 List<Integer> networkIds = listNetworks(); 455 if (networkIds == null) { 456 Log.e(TAG, "Failed to list networks"); 457 return false; 458 } 459 for (Integer networkId : networkIds) { 460 SupplicantStaNetworkHal network = getNetwork(networkId); 461 if (network == null) { 462 Log.e(TAG, "Failed to get network with ID: " + networkId); 463 return false; 464 } 465 WifiConfiguration config = new WifiConfiguration(); 466 Map<String, String> networkExtra = new HashMap<>(); 467 if (!network.loadWifiConfiguration(config, networkExtra)) { 468 Log.e(TAG, "Failed to load wifi configuration for network with ID: " + networkId); 469 return false; 470 } 471 // Set the default IP assignments. 472 config.setIpAssignment(IpConfiguration.IpAssignment.DHCP); 473 config.setProxySettings(IpConfiguration.ProxySettings.NONE); 474 475 networkExtras.put(networkId, networkExtra); 476 String configKey = networkExtra.get(SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY); 477 final WifiConfiguration duplicateConfig = configs.put(configKey, config); 478 if (duplicateConfig != null) { 479 // The network is already known. Overwrite the duplicate entry. 480 Log.i(TAG, "Replacing duplicate network: " + duplicateConfig.networkId); 481 removeNetwork(duplicateConfig.networkId); 482 networkExtras.remove(duplicateConfig.networkId); 483 } 484 } 485 return true; 486 } 487 488 /** 489 * Remove all networks from supplicant 490 */ 491 public boolean removeAllNetworks() { 492 synchronized (mLock) { 493 ArrayList<Integer> networks = listNetworks(); 494 if (networks == null) { 495 Log.e(TAG, "removeAllNetworks failed, got null networks"); 496 return false; 497 } 498 for (int id : networks) { 499 if (!removeNetwork(id)) { 500 Log.e(TAG, "removeAllNetworks failed to remove network: " + id); 501 return false; 502 } 503 } 504 } 505 return true; 506 } 507 508 /** 509 * Set the currently configured network's bssid. 510 * 511 * @param bssidStr Bssid to set in the form of "XX:XX:XX:XX:XX:XX" 512 * @return true if succeeds, false otherwise. 513 */ 514 public boolean setCurrentNetworkBssid(String bssidStr) { 515 if (mCurrentNetwork == null) return false; 516 return mCurrentNetwork.setBssid(bssidStr); 517 } 518 519 /** 520 * Get the currently configured network's WPS NFC token. 521 * 522 * @return Hex string corresponding to the WPS NFC token. 523 */ 524 public String getCurrentNetworkWpsNfcConfigurationToken() { 525 if (mCurrentNetwork == null) return null; 526 return mCurrentNetwork.getWpsNfcConfigurationToken(); 527 } 528 529 /** 530 * Send the eap identity response for the currently configured network. 531 * 532 * @param identityStr String to send. 533 * @return true if succeeds, false otherwise. 534 */ 535 public boolean sendCurrentNetworkEapIdentityResponse(String identityStr) { 536 if (mCurrentNetwork == null) return false; 537 return mCurrentNetwork.sendNetworkEapIdentityResponse(identityStr); 538 } 539 540 /** 541 * Send the eap sim gsm auth response for the currently configured network. 542 * 543 * @param paramsStr String to send. 544 * @return true if succeeds, false otherwise. 545 */ 546 public boolean sendCurrentNetworkEapSimGsmAuthResponse(String paramsStr) { 547 if (mCurrentNetwork == null) return false; 548 return mCurrentNetwork.sendNetworkEapSimGsmAuthResponse(paramsStr); 549 } 550 551 /** 552 * Send the eap sim gsm auth failure for the currently configured network. 553 * 554 * @return true if succeeds, false otherwise. 555 */ 556 public boolean sendCurrentNetworkEapSimGsmAuthFailure() { 557 if (mCurrentNetwork == null) return false; 558 return mCurrentNetwork.sendNetworkEapSimGsmAuthFailure(); 559 } 560 561 /** 562 * Send the eap sim umts auth response for the currently configured network. 563 * 564 * @param paramsStr String to send. 565 * @return true if succeeds, false otherwise. 566 */ 567 public boolean sendCurrentNetworkEapSimUmtsAuthResponse(String paramsStr) { 568 if (mCurrentNetwork == null) return false; 569 return mCurrentNetwork.sendNetworkEapSimUmtsAuthResponse(paramsStr); 570 } 571 572 /** 573 * Send the eap sim umts auts response for the currently configured network. 574 * 575 * @param paramsStr String to send. 576 * @return true if succeeds, false otherwise. 577 */ 578 public boolean sendCurrentNetworkEapSimUmtsAutsResponse(String paramsStr) { 579 if (mCurrentNetwork == null) return false; 580 return mCurrentNetwork.sendNetworkEapSimUmtsAutsResponse(paramsStr); 581 } 582 583 /** 584 * Send the eap sim umts auth failure for the currently configured network. 585 * 586 * @return true if succeeds, false otherwise. 587 */ 588 public boolean sendCurrentNetworkEapSimUmtsAuthFailure() { 589 if (mCurrentNetwork == null) return false; 590 return mCurrentNetwork.sendNetworkEapSimUmtsAuthFailure(); 591 } 592 593 /** 594 * Adds a new network. 595 * 596 * @return The ISupplicantNetwork object for the new network, or null if the call fails 597 */ 598 private SupplicantStaNetworkHal addNetwork() { 599 synchronized (mLock) { 600 final String methodStr = "addNetwork"; 601 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 602 Mutable<ISupplicantNetwork> newNetwork = new Mutable<>(); 603 try { 604 mISupplicantStaIface.addNetwork((SupplicantStatus status, 605 ISupplicantNetwork network) -> { 606 if (checkStatusAndLogFailure(status, methodStr)) { 607 newNetwork.value = network; 608 } 609 }); 610 } catch (RemoteException e) { 611 handleRemoteException(e, methodStr); 612 } 613 if (newNetwork.value != null) { 614 return getStaNetworkMockable( 615 ISupplicantStaNetwork.asInterface(newNetwork.value.asBinder())); 616 } else { 617 return null; 618 } 619 } 620 } 621 622 /** 623 * Remove network from supplicant with network Id 624 * 625 * @return true if request is sent successfully, false otherwise. 626 */ 627 private boolean removeNetwork(int id) { 628 synchronized (mLock) { 629 final String methodStr = "removeNetwork"; 630 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 631 try { 632 SupplicantStatus status = mISupplicantStaIface.removeNetwork(id); 633 return checkStatusAndLogFailure(status, methodStr); 634 } catch (RemoteException e) { 635 handleRemoteException(e, methodStr); 636 return false; 637 } 638 } 639 } 640 641 /** 642 * Use this to mock the creation of SupplicantStaNetworkHal instance. 643 * 644 * @param iSupplicantStaNetwork ISupplicantStaNetwork instance retrieved from HIDL. 645 * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if 646 * the call fails 647 */ 648 protected SupplicantStaNetworkHal getStaNetworkMockable( 649 ISupplicantStaNetwork iSupplicantStaNetwork) { 650 SupplicantStaNetworkHal network = 651 new SupplicantStaNetworkHal(iSupplicantStaNetwork, mIfaceName, mContext, 652 mWifiMonitor); 653 if (network != null) { 654 network.enableVerboseLogging(mVerboseLoggingEnabled); 655 } 656 return network; 657 } 658 659 /** 660 * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if 661 * the call fails 662 */ 663 private SupplicantStaNetworkHal getNetwork(int id) { 664 synchronized (mLock) { 665 final String methodStr = "getNetwork"; 666 Mutable<ISupplicantNetwork> gotNetwork = new Mutable<>(); 667 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 668 try { 669 mISupplicantStaIface.getNetwork(id, (SupplicantStatus status, 670 ISupplicantNetwork network) -> { 671 if (checkStatusAndLogFailure(status, methodStr)) { 672 gotNetwork.value = network; 673 } 674 }); 675 } catch (RemoteException e) { 676 handleRemoteException(e, methodStr); 677 } 678 if (gotNetwork.value != null) { 679 return getStaNetworkMockable( 680 ISupplicantStaNetwork.asInterface(gotNetwork.value.asBinder())); 681 } else { 682 return null; 683 } 684 } 685 } 686 687 /** See ISupplicantStaNetwork.hal for documentation */ 688 private boolean registerCallback(ISupplicantStaIfaceCallback callback) { 689 synchronized (mLock) { 690 final String methodStr = "registerCallback"; 691 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 692 try { 693 SupplicantStatus status = mISupplicantStaIface.registerCallback(callback); 694 return checkStatusAndLogFailure(status, methodStr); 695 } catch (RemoteException e) { 696 handleRemoteException(e, methodStr); 697 return false; 698 } 699 } 700 } 701 702 /** 703 * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns 704 * null if the call fails 705 */ 706 private java.util.ArrayList<Integer> listNetworks() { 707 synchronized (mLock) { 708 final String methodStr = "listNetworks"; 709 Mutable<ArrayList<Integer>> networkIdList = new Mutable<>(); 710 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 711 try { 712 mISupplicantStaIface.listNetworks((SupplicantStatus status, 713 java.util.ArrayList<Integer> networkIds) -> { 714 if (checkStatusAndLogFailure(status, methodStr)) { 715 networkIdList.value = networkIds; 716 } 717 }); 718 } catch (RemoteException e) { 719 handleRemoteException(e, methodStr); 720 } 721 return networkIdList.value; 722 } 723 } 724 725 /** 726 * Set WPS device name. 727 * 728 * @param name String to be set. 729 * @return true if request is sent successfully, false otherwise. 730 */ 731 public boolean setWpsDeviceName(String name) { 732 synchronized (mLock) { 733 final String methodStr = "setWpsDeviceName"; 734 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 735 try { 736 SupplicantStatus status = mISupplicantStaIface.setWpsDeviceName(name); 737 return checkStatusAndLogFailure(status, methodStr); 738 } catch (RemoteException e) { 739 handleRemoteException(e, methodStr); 740 return false; 741 } 742 } 743 } 744 745 /** 746 * Set WPS device type. 747 * 748 * @param typeStr Type specified as a string. Used format: <categ>-<OUI>-<subcateg> 749 * @return true if request is sent successfully, false otherwise. 750 */ 751 public boolean setWpsDeviceType(String typeStr) { 752 Matcher match = WPS_DEVICE_TYPE_PATTERN.matcher(typeStr); 753 if (!match.find() || match.groupCount() != 3) { 754 Log.e(TAG, "Malformed WPS device type " + typeStr); 755 return false; 756 } 757 short categ = Short.parseShort(match.group(1)); 758 byte[] oui = NativeUtil.hexStringToByteArray(match.group(2)); 759 short subCateg = Short.parseShort(match.group(3)); 760 761 byte[] bytes = new byte[8]; 762 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); 763 byteBuffer.putShort(categ); 764 byteBuffer.put(oui); 765 byteBuffer.putShort(subCateg); 766 return setWpsDeviceType(bytes); 767 } 768 769 private boolean setWpsDeviceType(byte[/* 8 */] type) { 770 synchronized (mLock) { 771 final String methodStr = "setWpsDeviceType"; 772 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 773 try { 774 SupplicantStatus status = mISupplicantStaIface.setWpsDeviceType(type); 775 return checkStatusAndLogFailure(status, methodStr); 776 } catch (RemoteException e) { 777 handleRemoteException(e, methodStr); 778 return false; 779 } 780 } 781 } 782 783 /** 784 * Set WPS manufacturer. 785 * 786 * @param manufacturer String to be set. 787 * @return true if request is sent successfully, false otherwise. 788 */ 789 public boolean setWpsManufacturer(String manufacturer) { 790 synchronized (mLock) { 791 final String methodStr = "setWpsManufacturer"; 792 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 793 try { 794 SupplicantStatus status = mISupplicantStaIface.setWpsManufacturer(manufacturer); 795 return checkStatusAndLogFailure(status, methodStr); 796 } catch (RemoteException e) { 797 handleRemoteException(e, methodStr); 798 return false; 799 } 800 } 801 } 802 803 /** 804 * Set WPS model name. 805 * 806 * @param modelName String to be set. 807 * @return true if request is sent successfully, false otherwise. 808 */ 809 public boolean setWpsModelName(String modelName) { 810 synchronized (mLock) { 811 final String methodStr = "setWpsModelName"; 812 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 813 try { 814 SupplicantStatus status = mISupplicantStaIface.setWpsModelName(modelName); 815 return checkStatusAndLogFailure(status, methodStr); 816 } catch (RemoteException e) { 817 handleRemoteException(e, methodStr); 818 return false; 819 } 820 } 821 } 822 823 /** 824 * Set WPS model number. 825 * 826 * @param modelNumber String to be set. 827 * @return true if request is sent successfully, false otherwise. 828 */ 829 public boolean setWpsModelNumber(String modelNumber) { 830 synchronized (mLock) { 831 final String methodStr = "setWpsModelNumber"; 832 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 833 try { 834 SupplicantStatus status = mISupplicantStaIface.setWpsModelNumber(modelNumber); 835 return checkStatusAndLogFailure(status, methodStr); 836 } catch (RemoteException e) { 837 handleRemoteException(e, methodStr); 838 return false; 839 } 840 } 841 } 842 843 /** 844 * Set WPS serial number. 845 * 846 * @param serialNumber String to be set. 847 * @return true if request is sent successfully, false otherwise. 848 */ 849 public boolean setWpsSerialNumber(String serialNumber) { 850 synchronized (mLock) { 851 final String methodStr = "setWpsSerialNumber"; 852 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 853 try { 854 SupplicantStatus status = mISupplicantStaIface.setWpsSerialNumber(serialNumber); 855 return checkStatusAndLogFailure(status, methodStr); 856 } catch (RemoteException e) { 857 handleRemoteException(e, methodStr); 858 return false; 859 } 860 } 861 } 862 863 /** 864 * Set WPS config methods 865 * 866 * @param configMethodsStr List of config methods. 867 * @return true if request is sent successfully, false otherwise. 868 */ 869 public boolean setWpsConfigMethods(String configMethodsStr) { 870 short configMethodsMask = 0; 871 String[] configMethodsStrArr = configMethodsStr.split("\\s+"); 872 for (int i = 0; i < configMethodsStrArr.length; i++) { 873 configMethodsMask |= stringToWpsConfigMethod(configMethodsStrArr[i]); 874 } 875 return setWpsConfigMethods(configMethodsMask); 876 } 877 878 private boolean setWpsConfigMethods(short configMethods) { 879 synchronized (mLock) { 880 final String methodStr = "setWpsConfigMethods"; 881 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 882 try { 883 SupplicantStatus status = mISupplicantStaIface.setWpsConfigMethods(configMethods); 884 return checkStatusAndLogFailure(status, methodStr); 885 } catch (RemoteException e) { 886 handleRemoteException(e, methodStr); 887 return false; 888 } 889 } 890 } 891 892 /** 893 * Trigger a reassociation even if the iface is currently connected. 894 * 895 * @return true if request is sent successfully, false otherwise. 896 */ 897 public boolean reassociate() { 898 synchronized (mLock) { 899 final String methodStr = "reassociate"; 900 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 901 try { 902 SupplicantStatus status = mISupplicantStaIface.reassociate(); 903 return checkStatusAndLogFailure(status, methodStr); 904 } catch (RemoteException e) { 905 handleRemoteException(e, methodStr); 906 return false; 907 } 908 } 909 } 910 911 /** 912 * Trigger a reconnection if the iface is disconnected. 913 * 914 * @return true if request is sent successfully, false otherwise. 915 */ 916 public boolean reconnect() { 917 synchronized (mLock) { 918 final String methodStr = "reconnect"; 919 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 920 try { 921 SupplicantStatus status = mISupplicantStaIface.reconnect(); 922 return checkStatusAndLogFailure(status, methodStr); 923 } catch (RemoteException e) { 924 handleRemoteException(e, methodStr); 925 return false; 926 } 927 } 928 } 929 930 /** 931 * Trigger a disconnection from the currently connected network. 932 * 933 * @return true if request is sent successfully, false otherwise. 934 */ 935 public boolean disconnect() { 936 synchronized (mLock) { 937 final String methodStr = "disconnect"; 938 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 939 try { 940 SupplicantStatus status = mISupplicantStaIface.disconnect(); 941 return checkStatusAndLogFailure(status, methodStr); 942 } catch (RemoteException e) { 943 handleRemoteException(e, methodStr); 944 return false; 945 } 946 } 947 } 948 949 /** 950 * Enable or disable power save mode. 951 * 952 * @param enable true to enable, false to disable. 953 * @return true if request is sent successfully, false otherwise. 954 */ 955 public boolean setPowerSave(boolean enable) { 956 synchronized (mLock) { 957 final String methodStr = "setPowerSave"; 958 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 959 try { 960 SupplicantStatus status = mISupplicantStaIface.setPowerSave(enable); 961 return checkStatusAndLogFailure(status, methodStr); 962 } catch (RemoteException e) { 963 handleRemoteException(e, methodStr); 964 return false; 965 } 966 } 967 } 968 969 /** 970 * Initiate TDLS discover with the specified AP. 971 * 972 * @param macAddress MAC Address of the AP. 973 * @return true if request is sent successfully, false otherwise. 974 */ 975 public boolean initiateTdlsDiscover(String macAddress) { 976 return initiateTdlsDiscover(NativeUtil.macAddressToByteArray(macAddress)); 977 } 978 /** See ISupplicantStaIface.hal for documentation */ 979 private boolean initiateTdlsDiscover(byte[/* 6 */] macAddress) { 980 synchronized (mLock) { 981 final String methodStr = "initiateTdlsDiscover"; 982 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 983 try { 984 SupplicantStatus status = mISupplicantStaIface.initiateTdlsDiscover(macAddress); 985 return checkStatusAndLogFailure(status, methodStr); 986 } catch (RemoteException e) { 987 handleRemoteException(e, methodStr); 988 return false; 989 } 990 } 991 } 992 993 /** 994 * Initiate TDLS setup with the specified AP. 995 * 996 * @param macAddress MAC Address of the AP. 997 * @return true if request is sent successfully, false otherwise. 998 */ 999 public boolean initiateTdlsSetup(String macAddress) { 1000 return initiateTdlsSetup(NativeUtil.macAddressToByteArray(macAddress)); 1001 } 1002 /** See ISupplicantStaIface.hal for documentation */ 1003 private boolean initiateTdlsSetup(byte[/* 6 */] macAddress) { 1004 synchronized (mLock) { 1005 final String methodStr = "initiateTdlsSetup"; 1006 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1007 try { 1008 SupplicantStatus status = mISupplicantStaIface.initiateTdlsSetup(macAddress); 1009 return checkStatusAndLogFailure(status, methodStr); 1010 } catch (RemoteException e) { 1011 handleRemoteException(e, methodStr); 1012 return false; 1013 } 1014 } 1015 } 1016 1017 /** 1018 * Initiate TDLS teardown with the specified AP. 1019 * @param macAddress MAC Address of the AP. 1020 * @return true if request is sent successfully, false otherwise. 1021 */ 1022 public boolean initiateTdlsTeardown(String macAddress) { 1023 return initiateTdlsTeardown(NativeUtil.macAddressToByteArray(macAddress)); 1024 } 1025 1026 /** See ISupplicantStaIface.hal for documentation */ 1027 private boolean initiateTdlsTeardown(byte[/* 6 */] macAddress) { 1028 synchronized (mLock) { 1029 final String methodStr = "initiateTdlsTeardown"; 1030 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1031 try { 1032 SupplicantStatus status = mISupplicantStaIface.initiateTdlsTeardown(macAddress); 1033 return checkStatusAndLogFailure(status, methodStr); 1034 } catch (RemoteException e) { 1035 handleRemoteException(e, methodStr); 1036 return false; 1037 } 1038 } 1039 } 1040 1041 /** 1042 * Request the specified ANQP elements |elements| from the specified AP |bssid|. 1043 * 1044 * @param bssid BSSID of the AP 1045 * @param infoElements ANQP elements to be queried. Refer to ISupplicantStaIface.AnqpInfoId. 1046 * @param hs20SubTypes HS subtypes to be queried. Refer to ISupplicantStaIface.Hs20AnqpSubTypes. 1047 * @return true if request is sent successfully, false otherwise. 1048 */ 1049 public boolean initiateAnqpQuery(String bssid, ArrayList<Short> infoElements, 1050 ArrayList<Integer> hs20SubTypes) { 1051 return initiateAnqpQuery( 1052 NativeUtil.macAddressToByteArray(bssid), infoElements, hs20SubTypes); 1053 } 1054 1055 /** See ISupplicantStaIface.hal for documentation */ 1056 private boolean initiateAnqpQuery(byte[/* 6 */] macAddress, 1057 java.util.ArrayList<Short> infoElements, java.util.ArrayList<Integer> subTypes) { 1058 synchronized (mLock) { 1059 final String methodStr = "initiateAnqpQuery"; 1060 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1061 try { 1062 SupplicantStatus status = mISupplicantStaIface.initiateAnqpQuery(macAddress, 1063 infoElements, subTypes); 1064 return checkStatusAndLogFailure(status, methodStr); 1065 } catch (RemoteException e) { 1066 handleRemoteException(e, methodStr); 1067 return false; 1068 } 1069 } 1070 } 1071 1072 /** 1073 * Request the specified ANQP ICON from the specified AP |bssid|. 1074 * 1075 * @param bssid BSSID of the AP 1076 * @param fileName Name of the file to request. 1077 * @return true if request is sent successfully, false otherwise. 1078 */ 1079 public boolean initiateHs20IconQuery(String bssid, String fileName) { 1080 return initiateHs20IconQuery(NativeUtil.macAddressToByteArray(bssid), fileName); 1081 } 1082 1083 /** See ISupplicantStaIface.hal for documentation */ 1084 private boolean initiateHs20IconQuery(byte[/* 6 */] macAddress, String fileName) { 1085 synchronized (mLock) { 1086 final String methodStr = "initiateHs20IconQuery"; 1087 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1088 try { 1089 SupplicantStatus status = mISupplicantStaIface.initiateHs20IconQuery(macAddress, 1090 fileName); 1091 return checkStatusAndLogFailure(status, methodStr); 1092 } catch (RemoteException e) { 1093 handleRemoteException(e, methodStr); 1094 return false; 1095 } 1096 } 1097 } 1098 1099 /** 1100 * Makes a callback to HIDL to getMacAddress from supplicant 1101 * 1102 * @return string containing the MAC address, or null on a failed call 1103 */ 1104 public String getMacAddress() { 1105 synchronized (mLock) { 1106 final String methodStr = "getMacAddress"; 1107 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 1108 Mutable<String> gotMac = new Mutable<>(); 1109 try { 1110 mISupplicantStaIface.getMacAddress((SupplicantStatus status, 1111 byte[/* 6 */] macAddr) -> { 1112 if (checkStatusAndLogFailure(status, methodStr)) { 1113 gotMac.value = NativeUtil.macAddressFromByteArray(macAddr); 1114 } 1115 }); 1116 } catch (RemoteException e) { 1117 handleRemoteException(e, methodStr); 1118 } 1119 return gotMac.value; 1120 } 1121 } 1122 1123 /** 1124 * Start using the added RX filters. 1125 * 1126 * @return true if request is sent successfully, false otherwise. 1127 */ 1128 public boolean startRxFilter() { 1129 synchronized (mLock) { 1130 final String methodStr = "startRxFilter"; 1131 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1132 try { 1133 SupplicantStatus status = mISupplicantStaIface.startRxFilter(); 1134 return checkStatusAndLogFailure(status, methodStr); 1135 } catch (RemoteException e) { 1136 handleRemoteException(e, methodStr); 1137 return false; 1138 } 1139 } 1140 } 1141 1142 /** 1143 * Stop using the added RX filters. 1144 * 1145 * @return true if request is sent successfully, false otherwise. 1146 */ 1147 public boolean stopRxFilter() { 1148 synchronized (mLock) { 1149 final String methodStr = "stopRxFilter"; 1150 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1151 try { 1152 SupplicantStatus status = mISupplicantStaIface.stopRxFilter(); 1153 return checkStatusAndLogFailure(status, methodStr); 1154 } catch (RemoteException e) { 1155 handleRemoteException(e, methodStr); 1156 return false; 1157 } 1158 } 1159 } 1160 1161 public static final byte RX_FILTER_TYPE_V4_MULTICAST = 1162 ISupplicantStaIface.RxFilterType.V6_MULTICAST; 1163 public static final byte RX_FILTER_TYPE_V6_MULTICAST = 1164 ISupplicantStaIface.RxFilterType.V6_MULTICAST; 1165 /** 1166 * Add an RX filter. 1167 * 1168 * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or 1169 * {@link #RX_FILTER_TYPE_V6_MULTICAST} values. 1170 * @return true if request is sent successfully, false otherwise. 1171 */ 1172 public boolean addRxFilter(byte type) { 1173 synchronized (mLock) { 1174 final String methodStr = "addRxFilter"; 1175 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1176 try { 1177 SupplicantStatus status = mISupplicantStaIface.addRxFilter(type); 1178 return checkStatusAndLogFailure(status, methodStr); 1179 } catch (RemoteException e) { 1180 handleRemoteException(e, methodStr); 1181 return false; 1182 } 1183 } 1184 } 1185 1186 /** 1187 * Remove an RX filter. 1188 * 1189 * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or 1190 * {@link #RX_FILTER_TYPE_V6_MULTICAST} values. 1191 * @return true if request is sent successfully, false otherwise. 1192 */ 1193 public boolean removeRxFilter(byte type) { 1194 synchronized (mLock) { 1195 final String methodStr = "removeRxFilter"; 1196 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1197 try { 1198 SupplicantStatus status = mISupplicantStaIface.removeRxFilter(type); 1199 return checkStatusAndLogFailure(status, methodStr); 1200 } catch (RemoteException e) { 1201 handleRemoteException(e, methodStr); 1202 return false; 1203 } 1204 } 1205 } 1206 1207 public static final byte BT_COEX_MODE_ENABLED = ISupplicantStaIface.BtCoexistenceMode.ENABLED; 1208 public static final byte BT_COEX_MODE_DISABLED = ISupplicantStaIface.BtCoexistenceMode.DISABLED; 1209 public static final byte BT_COEX_MODE_SENSE = ISupplicantStaIface.BtCoexistenceMode.SENSE; 1210 /** 1211 * Set Bt co existense mode. 1212 * 1213 * @param mode one of the above {@link #BT_COEX_MODE_ENABLED}, {@link #BT_COEX_MODE_DISABLED} 1214 * or {@link #BT_COEX_MODE_SENSE} values. 1215 * @return true if request is sent successfully, false otherwise. 1216 */ 1217 public boolean setBtCoexistenceMode(byte mode) { 1218 synchronized (mLock) { 1219 final String methodStr = "setBtCoexistenceMode"; 1220 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1221 try { 1222 SupplicantStatus status = mISupplicantStaIface.setBtCoexistenceMode(mode); 1223 return checkStatusAndLogFailure(status, methodStr); 1224 } catch (RemoteException e) { 1225 handleRemoteException(e, methodStr); 1226 return false; 1227 } 1228 } 1229 } 1230 1231 /** Enable or disable BT coexistence mode. 1232 * 1233 * @param enable true to enable, false to disable. 1234 * @return true if request is sent successfully, false otherwise. 1235 */ 1236 public boolean setBtCoexistenceScanModeEnabled(boolean enable) { 1237 synchronized (mLock) { 1238 final String methodStr = "setBtCoexistenceScanModeEnabled"; 1239 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1240 try { 1241 SupplicantStatus status = 1242 mISupplicantStaIface.setBtCoexistenceScanModeEnabled(enable); 1243 return checkStatusAndLogFailure(status, methodStr); 1244 } catch (RemoteException e) { 1245 handleRemoteException(e, methodStr); 1246 return false; 1247 } 1248 } 1249 } 1250 1251 /** 1252 * Enable or disable suspend mode optimizations. 1253 * 1254 * @param enable true to enable, false otherwise. 1255 * @return true if request is sent successfully, false otherwise. 1256 */ 1257 public boolean setSuspendModeEnabled(boolean enable) { 1258 synchronized (mLock) { 1259 final String methodStr = "setSuspendModeEnabled"; 1260 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1261 try { 1262 SupplicantStatus status = mISupplicantStaIface.setSuspendModeEnabled(enable); 1263 return checkStatusAndLogFailure(status, methodStr); 1264 } catch (RemoteException e) { 1265 handleRemoteException(e, methodStr); 1266 return false; 1267 } 1268 } 1269 } 1270 1271 /** 1272 * Set country code. 1273 * 1274 * @param codeStr 2 byte ASCII string. For ex: US, CA. 1275 * @return true if request is sent successfully, false otherwise. 1276 */ 1277 public boolean setCountryCode(String codeStr) { 1278 return setCountryCode(NativeUtil.stringToByteArray(codeStr)); 1279 } 1280 1281 /** See ISupplicantStaIface.hal for documentation */ 1282 private boolean setCountryCode(byte[/* 2 */] code) { 1283 synchronized (mLock) { 1284 final String methodStr = "setCountryCode"; 1285 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1286 try { 1287 SupplicantStatus status = mISupplicantStaIface.setCountryCode(code); 1288 return checkStatusAndLogFailure(status, methodStr); 1289 } catch (RemoteException e) { 1290 handleRemoteException(e, methodStr); 1291 return false; 1292 } 1293 } 1294 } 1295 1296 /** 1297 * Start WPS pin registrar operation with the specified peer and pin. 1298 * 1299 * @param bssidStr BSSID of the peer. 1300 * @param pin Pin to be used. 1301 * @return true if request is sent successfully, false otherwise. 1302 */ 1303 public boolean startWpsRegistrar(String bssidStr, String pin) { 1304 return startWpsRegistrar(NativeUtil.macAddressToByteArray(bssidStr), pin); 1305 } 1306 1307 /** See ISupplicantStaIface.hal for documentation */ 1308 private boolean startWpsRegistrar(byte[/* 6 */] bssid, String pin) { 1309 synchronized (mLock) { 1310 final String methodStr = "startWpsRegistrar"; 1311 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1312 try { 1313 SupplicantStatus status = mISupplicantStaIface.startWpsRegistrar(bssid, pin); 1314 return checkStatusAndLogFailure(status, methodStr); 1315 } catch (RemoteException e) { 1316 handleRemoteException(e, methodStr); 1317 return false; 1318 } 1319 } 1320 } 1321 1322 /** 1323 * Start WPS pin display operation with the specified peer. 1324 * 1325 * @param bssidStr BSSID of the peer. 1326 * @return true if request is sent successfully, false otherwise. 1327 */ 1328 public boolean startWpsPbc(String bssidStr) { 1329 return startWpsPbc(NativeUtil.macAddressToByteArray(bssidStr)); 1330 } 1331 1332 /** See ISupplicantStaIface.hal for documentation */ 1333 private boolean startWpsPbc(byte[/* 6 */] bssid) { 1334 synchronized (mLock) { 1335 final String methodStr = "startWpsPbc"; 1336 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1337 try { 1338 SupplicantStatus status = mISupplicantStaIface.startWpsPbc(bssid); 1339 return checkStatusAndLogFailure(status, methodStr); 1340 } catch (RemoteException e) { 1341 handleRemoteException(e, methodStr); 1342 return false; 1343 } 1344 } 1345 } 1346 1347 /** 1348 * Start WPS pin keypad operation with the specified pin. 1349 * 1350 * @param pin Pin to be used. 1351 * @return true if request is sent successfully, false otherwise. 1352 */ 1353 public boolean startWpsPinKeypad(String pin) { 1354 synchronized (mLock) { 1355 final String methodStr = "startWpsPinKeypad"; 1356 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1357 try { 1358 SupplicantStatus status = mISupplicantStaIface.startWpsPinKeypad(pin); 1359 return checkStatusAndLogFailure(status, methodStr); 1360 } catch (RemoteException e) { 1361 handleRemoteException(e, methodStr); 1362 return false; 1363 } 1364 } 1365 } 1366 1367 /** 1368 * Start WPS pin display operation with the specified peer. 1369 * 1370 * @param bssidStr BSSID of the peer. 1371 * @return new pin generated on success, null otherwise. 1372 */ 1373 public String startWpsPinDisplay(String bssidStr) { 1374 return startWpsPinDisplay(NativeUtil.macAddressToByteArray(bssidStr)); 1375 } 1376 1377 /** See ISupplicantStaIface.hal for documentation */ 1378 private String startWpsPinDisplay(byte[/* 6 */] bssid) { 1379 synchronized (mLock) { 1380 final String methodStr = "startWpsPinDisplay"; 1381 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 1382 final Mutable<String> gotPin = new Mutable<>(); 1383 try { 1384 mISupplicantStaIface.startWpsPinDisplay(bssid, 1385 (SupplicantStatus status, String pin) -> { 1386 if (checkStatusAndLogFailure(status, methodStr)) { 1387 gotPin.value = pin; 1388 } 1389 }); 1390 } catch (RemoteException e) { 1391 handleRemoteException(e, methodStr); 1392 } 1393 return gotPin.value; 1394 } 1395 } 1396 1397 /** 1398 * Cancels any ongoing WPS requests. 1399 * 1400 * @return true if request is sent successfully, false otherwise. 1401 */ 1402 public boolean cancelWps() { 1403 synchronized (mLock) { 1404 final String methodStr = "cancelWps"; 1405 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1406 try { 1407 SupplicantStatus status = mISupplicantStaIface.cancelWps(); 1408 return checkStatusAndLogFailure(status, methodStr); 1409 } catch (RemoteException e) { 1410 handleRemoteException(e, methodStr); 1411 return false; 1412 } 1413 } 1414 } 1415 1416 /** 1417 * Sets whether to use external sim for SIM/USIM processing. 1418 * 1419 * @param useExternalSim true to enable, false otherwise. 1420 * @return true if request is sent successfully, false otherwise. 1421 */ 1422 public boolean setExternalSim(boolean useExternalSim) { 1423 synchronized (mLock) { 1424 final String methodStr = "setExternalSim"; 1425 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1426 try { 1427 SupplicantStatus status = mISupplicantStaIface.setExternalSim(useExternalSim); 1428 return checkStatusAndLogFailure(status, methodStr); 1429 } catch (RemoteException e) { 1430 handleRemoteException(e, methodStr); 1431 return false; 1432 } 1433 } 1434 } 1435 1436 public static final int LOG_LEVEL_EXCESSIVE = ISupplicant.DebugLevel.EXCESSIVE; 1437 public static final int LOG_LEVEL_MSGDUMP = ISupplicant.DebugLevel.MSGDUMP; 1438 public static final int LOG_LEVEL_DEBUG = ISupplicant.DebugLevel.DEBUG; 1439 public static final int LOG_LEVEL_INFO = ISupplicant.DebugLevel.INFO; 1440 public static final int LOG_LEVEL_WARNING = ISupplicant.DebugLevel.WARNING; 1441 public static final int LOG_LEVEL_ERROR = ISupplicant.DebugLevel.ERROR; 1442 /** 1443 * Set the debug log level for wpa_supplicant 1444 * @param level One of the above {@link #LOG_LEVEL_EXCESSIVE} - {@link #LOG_LEVEL_ERROR} value. 1445 * @return true if request is sent successfully, false otherwise. 1446 */ 1447 public boolean setLogLevel(int level) { 1448 return setDebugParams(level, false, false); 1449 } 1450 1451 /** See ISupplicant.hal for documentation */ 1452 private boolean setDebugParams(int level, boolean showTimestamp, boolean showKeys) { 1453 synchronized (mLock) { 1454 final String methodStr = "setDebugParams"; 1455 if (!checkSupplicantAndLogFailure(methodStr)) return false; 1456 try { 1457 SupplicantStatus status = 1458 mISupplicant.setDebugParams(level, showTimestamp, showKeys); 1459 return checkStatusAndLogFailure(status, methodStr); 1460 } catch (RemoteException e) { 1461 handleRemoteException(e, methodStr); 1462 return false; 1463 } 1464 } 1465 } 1466 1467 /** 1468 * Set concurrency priority between P2P & STA operations. 1469 * 1470 * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations, 1471 * false otherwise. 1472 * @return true if request is sent successfully, false otherwise. 1473 */ 1474 public boolean setConcurrencyPriority(boolean isStaHigherPriority) { 1475 if (isStaHigherPriority) { 1476 return setConcurrencyPriority(IfaceType.STA); 1477 } else { 1478 return setConcurrencyPriority(IfaceType.P2P); 1479 } 1480 } 1481 1482 /** See ISupplicant.hal for documentation */ 1483 private boolean setConcurrencyPriority(int type) { 1484 synchronized (mLock) { 1485 final String methodStr = "setConcurrencyPriority"; 1486 if (!checkSupplicantAndLogFailure(methodStr)) return false; 1487 try { 1488 SupplicantStatus status = mISupplicant.setConcurrencyPriority(type); 1489 return checkStatusAndLogFailure(status, methodStr); 1490 } catch (RemoteException e) { 1491 handleRemoteException(e, methodStr); 1492 return false; 1493 } 1494 } 1495 } 1496 1497 /** 1498 * Returns false if Supplicant is null, and logs failure to call methodStr 1499 */ 1500 private boolean checkSupplicantAndLogFailure(final String methodStr) { 1501 if (mISupplicant == null) { 1502 Log.e(TAG, "Can't call " + methodStr + ", ISupplicant is null"); 1503 return false; 1504 } 1505 return true; 1506 } 1507 1508 /** 1509 * Returns false if SupplicantStaIface is null, and logs failure to call methodStr 1510 */ 1511 private boolean checkSupplicantStaIfaceAndLogFailure(final String methodStr) { 1512 if (mISupplicantStaIface == null) { 1513 Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaIface is null"); 1514 return false; 1515 } 1516 return true; 1517 } 1518 1519 /** 1520 * Returns true if provided status code is SUCCESS, logs debug message and returns false 1521 * otherwise 1522 */ 1523 private boolean checkStatusAndLogFailure(SupplicantStatus status, 1524 final String methodStr) { 1525 if (status.code != SupplicantStatusCode.SUCCESS) { 1526 Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed: " 1527 + supplicantStatusCodeToString(status.code) + ", " + status.debugMessage); 1528 return false; 1529 } else { 1530 if (mVerboseLoggingEnabled) { 1531 Log.d(TAG, "ISupplicantStaIface." + methodStr + " succeeded"); 1532 } 1533 return true; 1534 } 1535 } 1536 1537 /** 1538 * Helper function to log callbacks. 1539 */ 1540 private void logCallback(final String methodStr) { 1541 if (mVerboseLoggingEnabled) { 1542 Log.d(TAG, "ISupplicantStaIfaceCallback." + methodStr + " received"); 1543 } 1544 } 1545 1546 1547 private void handleRemoteException(RemoteException e, String methodStr) { 1548 supplicantServiceDiedHandler(); 1549 Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e); 1550 } 1551 1552 /** 1553 * Converts SupplicantStatus code values to strings for debug logging 1554 * TODO(b/34811152) Remove this, or make it more break resistance 1555 */ 1556 public static String supplicantStatusCodeToString(int code) { 1557 switch (code) { 1558 case 0: 1559 return "SUCCESS"; 1560 case 1: 1561 return "FAILURE_UNKNOWN"; 1562 case 2: 1563 return "FAILURE_ARGS_INVALID"; 1564 case 3: 1565 return "FAILURE_IFACE_INVALID"; 1566 case 4: 1567 return "FAILURE_IFACE_UNKNOWN"; 1568 case 5: 1569 return "FAILURE_IFACE_EXISTS"; 1570 case 6: 1571 return "FAILURE_IFACE_DISABLED"; 1572 case 7: 1573 return "FAILURE_IFACE_NOT_DISCONNECTED"; 1574 case 8: 1575 return "FAILURE_NETWORK_INVALID"; 1576 case 9: 1577 return "FAILURE_NETWORK_UNKNOWN"; 1578 default: 1579 return "??? UNKNOWN_CODE"; 1580 } 1581 } 1582 1583 1584 /** 1585 * Converts the Wps config method string to the equivalent enum value. 1586 */ 1587 private static short stringToWpsConfigMethod(String configMethod) { 1588 switch (configMethod) { 1589 case "usba": 1590 return WpsConfigMethods.USBA; 1591 case "ethernet": 1592 return WpsConfigMethods.ETHERNET; 1593 case "label": 1594 return WpsConfigMethods.LABEL; 1595 case "display": 1596 return WpsConfigMethods.DISPLAY; 1597 case "int_nfc_token": 1598 return WpsConfigMethods.INT_NFC_TOKEN; 1599 case "ext_nfc_token": 1600 return WpsConfigMethods.EXT_NFC_TOKEN; 1601 case "nfc_interface": 1602 return WpsConfigMethods.NFC_INTERFACE; 1603 case "push_button": 1604 return WpsConfigMethods.PUSHBUTTON; 1605 case "keypad": 1606 return WpsConfigMethods.KEYPAD; 1607 case "virtual_push_button": 1608 return WpsConfigMethods.VIRT_PUSHBUTTON; 1609 case "physical_push_button": 1610 return WpsConfigMethods.PHY_PUSHBUTTON; 1611 case "p2ps": 1612 return WpsConfigMethods.P2PS; 1613 case "virtual_display": 1614 return WpsConfigMethods.VIRT_DISPLAY; 1615 case "physical_display": 1616 return WpsConfigMethods.PHY_DISPLAY; 1617 default: 1618 throw new IllegalArgumentException( 1619 "Invalid WPS config method: " + configMethod); 1620 } 1621 } 1622 1623 /** 1624 * Converts the supplicant state received from HIDL to the equivalent framework state. 1625 */ 1626 private static SupplicantState supplicantHidlStateToFrameworkState(int state) { 1627 switch (state) { 1628 case ISupplicantStaIfaceCallback.State.DISCONNECTED: 1629 return SupplicantState.DISCONNECTED; 1630 case ISupplicantStaIfaceCallback.State.IFACE_DISABLED: 1631 return SupplicantState.INTERFACE_DISABLED; 1632 case ISupplicantStaIfaceCallback.State.INACTIVE: 1633 return SupplicantState.INACTIVE; 1634 case ISupplicantStaIfaceCallback.State.SCANNING: 1635 return SupplicantState.SCANNING; 1636 case ISupplicantStaIfaceCallback.State.AUTHENTICATING: 1637 return SupplicantState.AUTHENTICATING; 1638 case ISupplicantStaIfaceCallback.State.ASSOCIATING: 1639 return SupplicantState.ASSOCIATING; 1640 case ISupplicantStaIfaceCallback.State.ASSOCIATED: 1641 return SupplicantState.ASSOCIATED; 1642 case ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE: 1643 return SupplicantState.FOUR_WAY_HANDSHAKE; 1644 case ISupplicantStaIfaceCallback.State.GROUP_HANDSHAKE: 1645 return SupplicantState.GROUP_HANDSHAKE; 1646 case ISupplicantStaIfaceCallback.State.COMPLETED: 1647 return SupplicantState.COMPLETED; 1648 default: 1649 throw new IllegalArgumentException("Invalid state: " + state); 1650 } 1651 } 1652 1653 private static class Mutable<E> { 1654 public E value; 1655 1656 Mutable() { 1657 value = null; 1658 } 1659 1660 Mutable(E value) { 1661 this.value = value; 1662 } 1663 } 1664 1665 private class SupplicantStaIfaceHalCallback extends ISupplicantStaIfaceCallback.Stub { 1666 /** 1667 * Parses the provided payload into an ANQP element. 1668 * 1669 * @param infoID Element type. 1670 * @param payload Raw payload bytes. 1671 * @return AnqpElement instance on success, null on failure. 1672 */ 1673 private ANQPElement parseAnqpElement(Constants.ANQPElementType infoID, 1674 ArrayList<Byte> payload) { 1675 try { 1676 return Constants.getANQPElementID(infoID) != null 1677 ? ANQPParser.parseElement( 1678 infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))) 1679 : ANQPParser.parseHS20Element( 1680 infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))); 1681 } catch (IOException | BufferUnderflowException e) { 1682 Log.e(TAG, "Failed parsing ANQP element payload: " + infoID, e); 1683 return null; 1684 } 1685 } 1686 1687 /** 1688 * Parse the ANQP element data and add to the provided elements map if successful. 1689 * 1690 * @param elementsMap Map to add the parsed out element to. 1691 * @param infoID Element type. 1692 * @param payload Raw payload bytes. 1693 */ 1694 private void addAnqpElementToMap(Map<Constants.ANQPElementType, ANQPElement> elementsMap, 1695 Constants.ANQPElementType infoID, 1696 ArrayList<Byte> payload) { 1697 if (payload == null || payload.isEmpty()) return; 1698 ANQPElement element = parseAnqpElement(infoID, payload); 1699 if (element != null) { 1700 elementsMap.put(infoID, element); 1701 } 1702 } 1703 1704 /** 1705 * Helper utility to convert the bssid bytes to long. 1706 */ 1707 private Long toLongBssid(byte[] bssidBytes) { 1708 try { 1709 return ByteBufferReader.readInteger( 1710 ByteBuffer.wrap(bssidBytes), ByteOrder.BIG_ENDIAN, bssidBytes.length); 1711 } catch (BufferUnderflowException | IllegalArgumentException e) { 1712 return 0L; 1713 } 1714 } 1715 1716 @Override 1717 public void onNetworkAdded(int id) { 1718 logCallback("onNetworkAdded"); 1719 } 1720 1721 @Override 1722 public void onNetworkRemoved(int id) { 1723 logCallback("onNetworkRemoved"); 1724 } 1725 1726 @Override 1727 public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, 1728 ArrayList<Byte> ssid) { 1729 logCallback("onStateChanged"); 1730 synchronized (mLock) { 1731 SupplicantState newSupplicantState = supplicantHidlStateToFrameworkState(newState); 1732 WifiSsid wifiSsid = 1733 WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid)); 1734 String bssidStr = NativeUtil.macAddressFromByteArray(bssid); 1735 mWifiMonitor.broadcastSupplicantStateChangeEvent( 1736 mIfaceName, mFrameworkNetworkId, wifiSsid, bssidStr, newSupplicantState); 1737 if (newSupplicantState == SupplicantState.ASSOCIATED) { 1738 mWifiMonitor.broadcastAssociationSuccesfulEvent(mIfaceName, bssidStr); 1739 } else if (newSupplicantState == SupplicantState.COMPLETED) { 1740 mWifiMonitor.broadcastNetworkConnectionEvent( 1741 mIfaceName, mFrameworkNetworkId, bssidStr); 1742 } 1743 } 1744 } 1745 1746 @Override 1747 public void onAnqpQueryDone(byte[/* 6 */] bssid, 1748 ISupplicantStaIfaceCallback.AnqpData data, 1749 ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) { 1750 logCallback("onAnqpQueryDone"); 1751 synchronized (mLock) { 1752 Map<Constants.ANQPElementType, ANQPElement> elementsMap = new HashMap<>(); 1753 addAnqpElementToMap(elementsMap, ANQPVenueName, data.venueName); 1754 addAnqpElementToMap(elementsMap, ANQPRoamingConsortium, data.roamingConsortium); 1755 addAnqpElementToMap( 1756 elementsMap, ANQPIPAddrAvailability, data.ipAddrTypeAvailability); 1757 addAnqpElementToMap(elementsMap, ANQPNAIRealm, data.naiRealm); 1758 addAnqpElementToMap(elementsMap, ANQP3GPPNetwork, data.anqp3gppCellularNetwork); 1759 addAnqpElementToMap(elementsMap, ANQPDomName, data.domainName); 1760 addAnqpElementToMap(elementsMap, HSFriendlyName, hs20Data.operatorFriendlyName); 1761 addAnqpElementToMap(elementsMap, HSWANMetrics, hs20Data.wanMetrics); 1762 addAnqpElementToMap(elementsMap, HSConnCapability, hs20Data.connectionCapability); 1763 addAnqpElementToMap(elementsMap, HSOSUProviders, hs20Data.osuProvidersList); 1764 mWifiMonitor.broadcastAnqpDoneEvent( 1765 mIfaceName, new AnqpEvent(toLongBssid(bssid), elementsMap)); 1766 } 1767 } 1768 1769 @Override 1770 public void onHs20IconQueryDone(byte[/* 6 */] bssid, String fileName, 1771 ArrayList<Byte> data) { 1772 logCallback("onHs20IconQueryDone"); 1773 synchronized (mLock) { 1774 mWifiMonitor.broadcastIconDoneEvent( 1775 mIfaceName, 1776 new IconEvent(toLongBssid(bssid), fileName, data.size(), 1777 NativeUtil.byteArrayFromArrayList(data))); 1778 } 1779 } 1780 1781 @Override 1782 public void onHs20SubscriptionRemediation(byte[/* 6 */] bssid, byte osuMethod, String url) { 1783 logCallback("onHs20SubscriptionRemediation"); 1784 synchronized (mLock) { 1785 mWifiMonitor.broadcastWnmEvent( 1786 mIfaceName, new WnmData(toLongBssid(bssid), url, osuMethod)); 1787 } 1788 } 1789 1790 @Override 1791 public void onHs20DeauthImminentNotice(byte[/* 6 */] bssid, int reasonCode, 1792 int reAuthDelayInSec, String url) { 1793 logCallback("onHs20DeauthImminentNotice"); 1794 synchronized (mLock) { 1795 mWifiMonitor.broadcastWnmEvent( 1796 mIfaceName, 1797 new WnmData(toLongBssid(bssid), url, reasonCode == WnmData.ESS, 1798 reAuthDelayInSec)); 1799 } 1800 } 1801 1802 @Override 1803 public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int reasonCode) { 1804 logCallback("onDisconnected"); 1805 synchronized (mLock) { 1806 mWifiMonitor.broadcastNetworkDisconnectionEvent( 1807 mIfaceName, locallyGenerated ? 1 : 0, reasonCode, 1808 NativeUtil.macAddressFromByteArray(bssid)); 1809 } 1810 } 1811 1812 @Override 1813 public void onAssociationRejected(byte[/* 6 */] bssid, int statusCode) { 1814 logCallback("onAssociationRejected"); 1815 synchronized (mLock) { 1816 // TODO(b/35464954): Need to figure out when to trigger 1817 // |WifiMonitor.AUTHENTICATION_FAILURE_REASON_WRONG_PSWD| 1818 mWifiMonitor.broadcastAssociationRejectionEvent(mIfaceName, statusCode, 1819 NativeUtil.macAddressFromByteArray(bssid)); 1820 } 1821 } 1822 1823 @Override 1824 public void onAuthenticationTimeout(byte[/* 6 */] bssid) { 1825 logCallback("onAuthenticationTimeout"); 1826 synchronized (mLock) { 1827 mWifiMonitor.broadcastAuthenticationFailureEvent( 1828 mIfaceName, WifiMonitor.AUTHENTICATION_FAILURE_REASON_TIMEOUT); 1829 } 1830 } 1831 1832 @Override 1833 public void onEapFailure() { 1834 logCallback("onEapFailure"); 1835 synchronized (mLock) { 1836 mWifiMonitor.broadcastAuthenticationFailureEvent( 1837 mIfaceName, WifiMonitor.AUTHENTICATION_FAILURE_REASON_EAP_FAILURE); 1838 } 1839 } 1840 1841 @Override 1842 public void onWpsEventSuccess() { 1843 logCallback("onWpsEventSuccess"); 1844 synchronized (mLock) { 1845 mWifiMonitor.broadcastWpsSuccessEvent(mIfaceName); 1846 } 1847 } 1848 1849 @Override 1850 public void onWpsEventFail(byte[/* 6 */] bssid, short configError, short errorInd) { 1851 logCallback("onWpsEventFail"); 1852 synchronized (mLock) { 1853 if (configError == WpsConfigError.MSG_TIMEOUT 1854 && errorInd == WpsErrorIndication.NO_ERROR) { 1855 mWifiMonitor.broadcastWpsTimeoutEvent(mIfaceName); 1856 } else { 1857 mWifiMonitor.broadcastWpsFailEvent(mIfaceName, configError, errorInd); 1858 } 1859 } 1860 } 1861 1862 @Override 1863 public void onWpsEventPbcOverlap() { 1864 logCallback("onWpsEventPbcOverlap"); 1865 synchronized (mLock) { 1866 mWifiMonitor.broadcastWpsOverlapEvent(mIfaceName); 1867 } 1868 } 1869 1870 @Override 1871 public void onExtRadioWorkStart(int id) { 1872 logCallback("onExtRadioWorkStart"); 1873 } 1874 1875 @Override 1876 public void onExtRadioWorkTimeout(int id) { 1877 logCallback("onExtRadioWorkTimeout"); 1878 } 1879 } 1880 1881 private void logd(String s) { 1882 Log.d(TAG, s); 1883 } 1884 1885 private void logi(String s) { 1886 Log.i(TAG, s); 1887 } 1888 1889 private void loge(String s) { 1890 Log.e(TAG, s); 1891 } 1892} 1893