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