SupplicantStaIfaceHal.java revision 913bcdf2c0c37a04735e7401037e729496aae021
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.text.TextUtils; 48import android.util.Log; 49import android.util.SparseArray; 50 51import com.android.server.wifi.hotspot2.AnqpEvent; 52import com.android.server.wifi.hotspot2.IconEvent; 53import com.android.server.wifi.hotspot2.WnmData; 54import com.android.server.wifi.hotspot2.anqp.ANQPElement; 55import com.android.server.wifi.hotspot2.anqp.ANQPParser; 56import com.android.server.wifi.hotspot2.anqp.Constants; 57import com.android.server.wifi.util.NativeUtil; 58 59import java.io.IOException; 60import java.nio.BufferUnderflowException; 61import java.nio.ByteBuffer; 62import java.nio.ByteOrder; 63import java.util.ArrayList; 64import java.util.HashMap; 65import java.util.List; 66import java.util.Map; 67import java.util.regex.Matcher; 68import java.util.regex.Pattern; 69 70/** 71 * Hal calls for bring up/shut down of the supplicant daemon and for 72 * sending requests to the supplicant daemon 73 */ 74public class SupplicantStaIfaceHal { 75 private static final String TAG = "SupplicantStaIfaceHal"; 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(); 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 boolean loadSuccess = false; 469 try { 470 loadSuccess = network.loadWifiConfiguration(config, networkExtra); 471 } catch (IllegalArgumentException e) { 472 Log.wtf(TAG, "Exception while loading config params: " + config, e); 473 } 474 if (!loadSuccess) { 475 Log.e(TAG, "Failed to load wifi configuration for network with ID: " + networkId 476 + ". Skipping..."); 477 continue; 478 } 479 // Set the default IP assignments. 480 config.setIpAssignment(IpConfiguration.IpAssignment.DHCP); 481 config.setProxySettings(IpConfiguration.ProxySettings.NONE); 482 483 networkExtras.put(networkId, networkExtra); 484 String configKey = networkExtra.get(SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY); 485 final WifiConfiguration duplicateConfig = configs.put(configKey, config); 486 if (duplicateConfig != null) { 487 // The network is already known. Overwrite the duplicate entry. 488 Log.i(TAG, "Replacing duplicate network: " + duplicateConfig.networkId); 489 removeNetwork(duplicateConfig.networkId); 490 networkExtras.remove(duplicateConfig.networkId); 491 } 492 } 493 return true; 494 } 495 496 /** 497 * Remove all networks from supplicant 498 */ 499 public boolean removeAllNetworks() { 500 synchronized (mLock) { 501 ArrayList<Integer> networks = listNetworks(); 502 if (networks == null) { 503 Log.e(TAG, "removeAllNetworks failed, got null networks"); 504 return false; 505 } 506 for (int id : networks) { 507 if (!removeNetwork(id)) { 508 Log.e(TAG, "removeAllNetworks failed to remove network: " + id); 509 return false; 510 } 511 } 512 } 513 return true; 514 } 515 516 /** 517 * Set the currently configured network's bssid. 518 * 519 * @param bssidStr Bssid to set in the form of "XX:XX:XX:XX:XX:XX" 520 * @return true if succeeds, false otherwise. 521 */ 522 public boolean setCurrentNetworkBssid(String bssidStr) { 523 if (mCurrentNetwork == null) return false; 524 return mCurrentNetwork.setBssid(bssidStr); 525 } 526 527 /** 528 * Get the currently configured network's WPS NFC token. 529 * 530 * @return Hex string corresponding to the WPS NFC token. 531 */ 532 public String getCurrentNetworkWpsNfcConfigurationToken() { 533 if (mCurrentNetwork == null) return null; 534 return mCurrentNetwork.getWpsNfcConfigurationToken(); 535 } 536 537 /** 538 * Send the eap identity response for the currently configured network. 539 * 540 * @param identityStr String to send. 541 * @return true if succeeds, false otherwise. 542 */ 543 public boolean sendCurrentNetworkEapIdentityResponse(String identityStr) { 544 if (mCurrentNetwork == null) return false; 545 return mCurrentNetwork.sendNetworkEapIdentityResponse(identityStr); 546 } 547 548 /** 549 * Send the eap sim gsm auth response for the currently configured network. 550 * 551 * @param paramsStr String to send. 552 * @return true if succeeds, false otherwise. 553 */ 554 public boolean sendCurrentNetworkEapSimGsmAuthResponse(String paramsStr) { 555 if (mCurrentNetwork == null) return false; 556 return mCurrentNetwork.sendNetworkEapSimGsmAuthResponse(paramsStr); 557 } 558 559 /** 560 * Send the eap sim gsm auth failure for the currently configured network. 561 * 562 * @return true if succeeds, false otherwise. 563 */ 564 public boolean sendCurrentNetworkEapSimGsmAuthFailure() { 565 if (mCurrentNetwork == null) return false; 566 return mCurrentNetwork.sendNetworkEapSimGsmAuthFailure(); 567 } 568 569 /** 570 * Send the eap sim umts auth response for the currently configured network. 571 * 572 * @param paramsStr String to send. 573 * @return true if succeeds, false otherwise. 574 */ 575 public boolean sendCurrentNetworkEapSimUmtsAuthResponse(String paramsStr) { 576 if (mCurrentNetwork == null) return false; 577 return mCurrentNetwork.sendNetworkEapSimUmtsAuthResponse(paramsStr); 578 } 579 580 /** 581 * Send the eap sim umts auts response for the currently configured network. 582 * 583 * @param paramsStr String to send. 584 * @return true if succeeds, false otherwise. 585 */ 586 public boolean sendCurrentNetworkEapSimUmtsAutsResponse(String paramsStr) { 587 if (mCurrentNetwork == null) return false; 588 return mCurrentNetwork.sendNetworkEapSimUmtsAutsResponse(paramsStr); 589 } 590 591 /** 592 * Send the eap sim umts auth failure for the currently configured network. 593 * 594 * @return true if succeeds, false otherwise. 595 */ 596 public boolean sendCurrentNetworkEapSimUmtsAuthFailure() { 597 if (mCurrentNetwork == null) return false; 598 return mCurrentNetwork.sendNetworkEapSimUmtsAuthFailure(); 599 } 600 601 /** 602 * Adds a new network. 603 * 604 * @return The ISupplicantNetwork object for the new network, or null if the call fails 605 */ 606 private SupplicantStaNetworkHal addNetwork() { 607 synchronized (mLock) { 608 final String methodStr = "addNetwork"; 609 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 610 Mutable<ISupplicantNetwork> newNetwork = new Mutable<>(); 611 try { 612 mISupplicantStaIface.addNetwork((SupplicantStatus status, 613 ISupplicantNetwork network) -> { 614 if (checkStatusAndLogFailure(status, methodStr)) { 615 newNetwork.value = network; 616 } 617 }); 618 } catch (RemoteException e) { 619 handleRemoteException(e, methodStr); 620 } 621 if (newNetwork.value != null) { 622 return getStaNetworkMockable( 623 ISupplicantStaNetwork.asInterface(newNetwork.value.asBinder())); 624 } else { 625 return null; 626 } 627 } 628 } 629 630 /** 631 * Remove network from supplicant with network Id 632 * 633 * @return true if request is sent successfully, false otherwise. 634 */ 635 private boolean removeNetwork(int id) { 636 synchronized (mLock) { 637 final String methodStr = "removeNetwork"; 638 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 639 try { 640 SupplicantStatus status = mISupplicantStaIface.removeNetwork(id); 641 return checkStatusAndLogFailure(status, methodStr); 642 } catch (RemoteException e) { 643 handleRemoteException(e, methodStr); 644 return false; 645 } 646 } 647 } 648 649 /** 650 * Use this to mock the creation of SupplicantStaNetworkHal instance. 651 * 652 * @param iSupplicantStaNetwork ISupplicantStaNetwork instance retrieved from HIDL. 653 * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if 654 * the call fails 655 */ 656 protected SupplicantStaNetworkHal getStaNetworkMockable( 657 ISupplicantStaNetwork iSupplicantStaNetwork) { 658 SupplicantStaNetworkHal network = 659 new SupplicantStaNetworkHal(iSupplicantStaNetwork, mIfaceName, mContext, 660 mWifiMonitor); 661 if (network != null) { 662 network.enableVerboseLogging(mVerboseLoggingEnabled); 663 } 664 return network; 665 } 666 667 /** 668 * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if 669 * the call fails 670 */ 671 private SupplicantStaNetworkHal getNetwork(int id) { 672 synchronized (mLock) { 673 final String methodStr = "getNetwork"; 674 Mutable<ISupplicantNetwork> gotNetwork = new Mutable<>(); 675 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 676 try { 677 mISupplicantStaIface.getNetwork(id, (SupplicantStatus status, 678 ISupplicantNetwork network) -> { 679 if (checkStatusAndLogFailure(status, methodStr)) { 680 gotNetwork.value = network; 681 } 682 }); 683 } catch (RemoteException e) { 684 handleRemoteException(e, methodStr); 685 } 686 if (gotNetwork.value != null) { 687 return getStaNetworkMockable( 688 ISupplicantStaNetwork.asInterface(gotNetwork.value.asBinder())); 689 } else { 690 return null; 691 } 692 } 693 } 694 695 /** See ISupplicantStaNetwork.hal for documentation */ 696 private boolean registerCallback(ISupplicantStaIfaceCallback callback) { 697 synchronized (mLock) { 698 final String methodStr = "registerCallback"; 699 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 700 try { 701 SupplicantStatus status = mISupplicantStaIface.registerCallback(callback); 702 return checkStatusAndLogFailure(status, methodStr); 703 } catch (RemoteException e) { 704 handleRemoteException(e, methodStr); 705 return false; 706 } 707 } 708 } 709 710 /** 711 * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns 712 * null if the call fails 713 */ 714 private java.util.ArrayList<Integer> listNetworks() { 715 synchronized (mLock) { 716 final String methodStr = "listNetworks"; 717 Mutable<ArrayList<Integer>> networkIdList = new Mutable<>(); 718 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 719 try { 720 mISupplicantStaIface.listNetworks((SupplicantStatus status, 721 java.util.ArrayList<Integer> networkIds) -> { 722 if (checkStatusAndLogFailure(status, methodStr)) { 723 networkIdList.value = networkIds; 724 } 725 }); 726 } catch (RemoteException e) { 727 handleRemoteException(e, methodStr); 728 } 729 return networkIdList.value; 730 } 731 } 732 733 /** 734 * Set WPS device name. 735 * 736 * @param name String to be set. 737 * @return true if request is sent successfully, false otherwise. 738 */ 739 public boolean setWpsDeviceName(String name) { 740 synchronized (mLock) { 741 final String methodStr = "setWpsDeviceName"; 742 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 743 try { 744 SupplicantStatus status = mISupplicantStaIface.setWpsDeviceName(name); 745 return checkStatusAndLogFailure(status, methodStr); 746 } catch (RemoteException e) { 747 handleRemoteException(e, methodStr); 748 return false; 749 } 750 } 751 } 752 753 /** 754 * Set WPS device type. 755 * 756 * @param typeStr Type specified as a string. Used format: <categ>-<OUI>-<subcateg> 757 * @return true if request is sent successfully, false otherwise. 758 */ 759 public boolean setWpsDeviceType(String typeStr) { 760 Matcher match = WPS_DEVICE_TYPE_PATTERN.matcher(typeStr); 761 if (!match.find() || match.groupCount() != 3) { 762 Log.e(TAG, "Malformed WPS device type " + typeStr); 763 return false; 764 } 765 short categ = Short.parseShort(match.group(1)); 766 byte[] oui = NativeUtil.hexStringToByteArray(match.group(2)); 767 short subCateg = Short.parseShort(match.group(3)); 768 769 byte[] bytes = new byte[8]; 770 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); 771 byteBuffer.putShort(categ); 772 byteBuffer.put(oui); 773 byteBuffer.putShort(subCateg); 774 return setWpsDeviceType(bytes); 775 } 776 777 private boolean setWpsDeviceType(byte[/* 8 */] type) { 778 synchronized (mLock) { 779 final String methodStr = "setWpsDeviceType"; 780 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 781 try { 782 SupplicantStatus status = mISupplicantStaIface.setWpsDeviceType(type); 783 return checkStatusAndLogFailure(status, methodStr); 784 } catch (RemoteException e) { 785 handleRemoteException(e, methodStr); 786 return false; 787 } 788 } 789 } 790 791 /** 792 * Set WPS manufacturer. 793 * 794 * @param manufacturer String to be set. 795 * @return true if request is sent successfully, false otherwise. 796 */ 797 public boolean setWpsManufacturer(String manufacturer) { 798 synchronized (mLock) { 799 final String methodStr = "setWpsManufacturer"; 800 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 801 try { 802 SupplicantStatus status = mISupplicantStaIface.setWpsManufacturer(manufacturer); 803 return checkStatusAndLogFailure(status, methodStr); 804 } catch (RemoteException e) { 805 handleRemoteException(e, methodStr); 806 return false; 807 } 808 } 809 } 810 811 /** 812 * Set WPS model name. 813 * 814 * @param modelName String to be set. 815 * @return true if request is sent successfully, false otherwise. 816 */ 817 public boolean setWpsModelName(String modelName) { 818 synchronized (mLock) { 819 final String methodStr = "setWpsModelName"; 820 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 821 try { 822 SupplicantStatus status = mISupplicantStaIface.setWpsModelName(modelName); 823 return checkStatusAndLogFailure(status, methodStr); 824 } catch (RemoteException e) { 825 handleRemoteException(e, methodStr); 826 return false; 827 } 828 } 829 } 830 831 /** 832 * Set WPS model number. 833 * 834 * @param modelNumber String to be set. 835 * @return true if request is sent successfully, false otherwise. 836 */ 837 public boolean setWpsModelNumber(String modelNumber) { 838 synchronized (mLock) { 839 final String methodStr = "setWpsModelNumber"; 840 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 841 try { 842 SupplicantStatus status = mISupplicantStaIface.setWpsModelNumber(modelNumber); 843 return checkStatusAndLogFailure(status, methodStr); 844 } catch (RemoteException e) { 845 handleRemoteException(e, methodStr); 846 return false; 847 } 848 } 849 } 850 851 /** 852 * Set WPS serial number. 853 * 854 * @param serialNumber String to be set. 855 * @return true if request is sent successfully, false otherwise. 856 */ 857 public boolean setWpsSerialNumber(String serialNumber) { 858 synchronized (mLock) { 859 final String methodStr = "setWpsSerialNumber"; 860 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 861 try { 862 SupplicantStatus status = mISupplicantStaIface.setWpsSerialNumber(serialNumber); 863 return checkStatusAndLogFailure(status, methodStr); 864 } catch (RemoteException e) { 865 handleRemoteException(e, methodStr); 866 return false; 867 } 868 } 869 } 870 871 /** 872 * Set WPS config methods 873 * 874 * @param configMethodsStr List of config methods. 875 * @return true if request is sent successfully, false otherwise. 876 */ 877 public boolean setWpsConfigMethods(String configMethodsStr) { 878 short configMethodsMask = 0; 879 String[] configMethodsStrArr = configMethodsStr.split("\\s+"); 880 for (int i = 0; i < configMethodsStrArr.length; i++) { 881 configMethodsMask |= stringToWpsConfigMethod(configMethodsStrArr[i]); 882 } 883 return setWpsConfigMethods(configMethodsMask); 884 } 885 886 private boolean setWpsConfigMethods(short configMethods) { 887 synchronized (mLock) { 888 final String methodStr = "setWpsConfigMethods"; 889 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 890 try { 891 SupplicantStatus status = mISupplicantStaIface.setWpsConfigMethods(configMethods); 892 return checkStatusAndLogFailure(status, methodStr); 893 } catch (RemoteException e) { 894 handleRemoteException(e, methodStr); 895 return false; 896 } 897 } 898 } 899 900 /** 901 * Trigger a reassociation even if the iface is currently connected. 902 * 903 * @return true if request is sent successfully, false otherwise. 904 */ 905 public boolean reassociate() { 906 synchronized (mLock) { 907 final String methodStr = "reassociate"; 908 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 909 try { 910 SupplicantStatus status = mISupplicantStaIface.reassociate(); 911 return checkStatusAndLogFailure(status, methodStr); 912 } catch (RemoteException e) { 913 handleRemoteException(e, methodStr); 914 return false; 915 } 916 } 917 } 918 919 /** 920 * Trigger a reconnection if the iface is disconnected. 921 * 922 * @return true if request is sent successfully, false otherwise. 923 */ 924 public boolean reconnect() { 925 synchronized (mLock) { 926 final String methodStr = "reconnect"; 927 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 928 try { 929 SupplicantStatus status = mISupplicantStaIface.reconnect(); 930 return checkStatusAndLogFailure(status, methodStr); 931 } catch (RemoteException e) { 932 handleRemoteException(e, methodStr); 933 return false; 934 } 935 } 936 } 937 938 /** 939 * Trigger a disconnection from the currently connected network. 940 * 941 * @return true if request is sent successfully, false otherwise. 942 */ 943 public boolean disconnect() { 944 synchronized (mLock) { 945 final String methodStr = "disconnect"; 946 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 947 try { 948 SupplicantStatus status = mISupplicantStaIface.disconnect(); 949 return checkStatusAndLogFailure(status, methodStr); 950 } catch (RemoteException e) { 951 handleRemoteException(e, methodStr); 952 return false; 953 } 954 } 955 } 956 957 /** 958 * Enable or disable power save mode. 959 * 960 * @param enable true to enable, false to disable. 961 * @return true if request is sent successfully, false otherwise. 962 */ 963 public boolean setPowerSave(boolean enable) { 964 synchronized (mLock) { 965 final String methodStr = "setPowerSave"; 966 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 967 try { 968 SupplicantStatus status = mISupplicantStaIface.setPowerSave(enable); 969 return checkStatusAndLogFailure(status, methodStr); 970 } catch (RemoteException e) { 971 handleRemoteException(e, methodStr); 972 return false; 973 } 974 } 975 } 976 977 /** 978 * Initiate TDLS discover with the specified AP. 979 * 980 * @param macAddress MAC Address of the AP. 981 * @return true if request is sent successfully, false otherwise. 982 */ 983 public boolean initiateTdlsDiscover(String macAddress) { 984 return initiateTdlsDiscover(NativeUtil.macAddressToByteArray(macAddress)); 985 } 986 /** See ISupplicantStaIface.hal for documentation */ 987 private boolean initiateTdlsDiscover(byte[/* 6 */] macAddress) { 988 synchronized (mLock) { 989 final String methodStr = "initiateTdlsDiscover"; 990 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 991 try { 992 SupplicantStatus status = mISupplicantStaIface.initiateTdlsDiscover(macAddress); 993 return checkStatusAndLogFailure(status, methodStr); 994 } catch (RemoteException e) { 995 handleRemoteException(e, methodStr); 996 return false; 997 } 998 } 999 } 1000 1001 /** 1002 * Initiate TDLS setup with the specified AP. 1003 * 1004 * @param macAddress MAC Address of the AP. 1005 * @return true if request is sent successfully, false otherwise. 1006 */ 1007 public boolean initiateTdlsSetup(String macAddress) { 1008 return initiateTdlsSetup(NativeUtil.macAddressToByteArray(macAddress)); 1009 } 1010 /** See ISupplicantStaIface.hal for documentation */ 1011 private boolean initiateTdlsSetup(byte[/* 6 */] macAddress) { 1012 synchronized (mLock) { 1013 final String methodStr = "initiateTdlsSetup"; 1014 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1015 try { 1016 SupplicantStatus status = mISupplicantStaIface.initiateTdlsSetup(macAddress); 1017 return checkStatusAndLogFailure(status, methodStr); 1018 } catch (RemoteException e) { 1019 handleRemoteException(e, methodStr); 1020 return false; 1021 } 1022 } 1023 } 1024 1025 /** 1026 * Initiate TDLS teardown with the specified AP. 1027 * @param macAddress MAC Address of the AP. 1028 * @return true if request is sent successfully, false otherwise. 1029 */ 1030 public boolean initiateTdlsTeardown(String macAddress) { 1031 return initiateTdlsTeardown(NativeUtil.macAddressToByteArray(macAddress)); 1032 } 1033 1034 /** See ISupplicantStaIface.hal for documentation */ 1035 private boolean initiateTdlsTeardown(byte[/* 6 */] macAddress) { 1036 synchronized (mLock) { 1037 final String methodStr = "initiateTdlsTeardown"; 1038 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1039 try { 1040 SupplicantStatus status = mISupplicantStaIface.initiateTdlsTeardown(macAddress); 1041 return checkStatusAndLogFailure(status, methodStr); 1042 } catch (RemoteException e) { 1043 handleRemoteException(e, methodStr); 1044 return false; 1045 } 1046 } 1047 } 1048 1049 /** 1050 * Request the specified ANQP elements |elements| from the specified AP |bssid|. 1051 * 1052 * @param bssid BSSID of the AP 1053 * @param infoElements ANQP elements to be queried. Refer to ISupplicantStaIface.AnqpInfoId. 1054 * @param hs20SubTypes HS subtypes to be queried. Refer to ISupplicantStaIface.Hs20AnqpSubTypes. 1055 * @return true if request is sent successfully, false otherwise. 1056 */ 1057 public boolean initiateAnqpQuery(String bssid, ArrayList<Short> infoElements, 1058 ArrayList<Integer> hs20SubTypes) { 1059 return initiateAnqpQuery( 1060 NativeUtil.macAddressToByteArray(bssid), infoElements, hs20SubTypes); 1061 } 1062 1063 /** See ISupplicantStaIface.hal for documentation */ 1064 private boolean initiateAnqpQuery(byte[/* 6 */] macAddress, 1065 java.util.ArrayList<Short> infoElements, java.util.ArrayList<Integer> subTypes) { 1066 synchronized (mLock) { 1067 final String methodStr = "initiateAnqpQuery"; 1068 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1069 try { 1070 SupplicantStatus status = mISupplicantStaIface.initiateAnqpQuery(macAddress, 1071 infoElements, subTypes); 1072 return checkStatusAndLogFailure(status, methodStr); 1073 } catch (RemoteException e) { 1074 handleRemoteException(e, methodStr); 1075 return false; 1076 } 1077 } 1078 } 1079 1080 /** 1081 * Request the specified ANQP ICON from the specified AP |bssid|. 1082 * 1083 * @param bssid BSSID of the AP 1084 * @param fileName Name of the file to request. 1085 * @return true if request is sent successfully, false otherwise. 1086 */ 1087 public boolean initiateHs20IconQuery(String bssid, String fileName) { 1088 return initiateHs20IconQuery(NativeUtil.macAddressToByteArray(bssid), fileName); 1089 } 1090 1091 /** See ISupplicantStaIface.hal for documentation */ 1092 private boolean initiateHs20IconQuery(byte[/* 6 */] macAddress, String fileName) { 1093 synchronized (mLock) { 1094 final String methodStr = "initiateHs20IconQuery"; 1095 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1096 try { 1097 SupplicantStatus status = mISupplicantStaIface.initiateHs20IconQuery(macAddress, 1098 fileName); 1099 return checkStatusAndLogFailure(status, methodStr); 1100 } catch (RemoteException e) { 1101 handleRemoteException(e, methodStr); 1102 return false; 1103 } 1104 } 1105 } 1106 1107 /** 1108 * Makes a callback to HIDL to getMacAddress from supplicant 1109 * 1110 * @return string containing the MAC address, or null on a failed call 1111 */ 1112 public String getMacAddress() { 1113 synchronized (mLock) { 1114 final String methodStr = "getMacAddress"; 1115 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 1116 Mutable<String> gotMac = new Mutable<>(); 1117 try { 1118 mISupplicantStaIface.getMacAddress((SupplicantStatus status, 1119 byte[/* 6 */] macAddr) -> { 1120 if (checkStatusAndLogFailure(status, methodStr)) { 1121 gotMac.value = NativeUtil.macAddressFromByteArray(macAddr); 1122 } 1123 }); 1124 } catch (RemoteException e) { 1125 handleRemoteException(e, methodStr); 1126 } 1127 return gotMac.value; 1128 } 1129 } 1130 1131 /** 1132 * Start using the added RX filters. 1133 * 1134 * @return true if request is sent successfully, false otherwise. 1135 */ 1136 public boolean startRxFilter() { 1137 synchronized (mLock) { 1138 final String methodStr = "startRxFilter"; 1139 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1140 try { 1141 SupplicantStatus status = mISupplicantStaIface.startRxFilter(); 1142 return checkStatusAndLogFailure(status, methodStr); 1143 } catch (RemoteException e) { 1144 handleRemoteException(e, methodStr); 1145 return false; 1146 } 1147 } 1148 } 1149 1150 /** 1151 * Stop using the added RX filters. 1152 * 1153 * @return true if request is sent successfully, false otherwise. 1154 */ 1155 public boolean stopRxFilter() { 1156 synchronized (mLock) { 1157 final String methodStr = "stopRxFilter"; 1158 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1159 try { 1160 SupplicantStatus status = mISupplicantStaIface.stopRxFilter(); 1161 return checkStatusAndLogFailure(status, methodStr); 1162 } catch (RemoteException e) { 1163 handleRemoteException(e, methodStr); 1164 return false; 1165 } 1166 } 1167 } 1168 1169 public static final byte RX_FILTER_TYPE_V4_MULTICAST = 1170 ISupplicantStaIface.RxFilterType.V6_MULTICAST; 1171 public static final byte RX_FILTER_TYPE_V6_MULTICAST = 1172 ISupplicantStaIface.RxFilterType.V6_MULTICAST; 1173 /** 1174 * Add an RX filter. 1175 * 1176 * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or 1177 * {@link #RX_FILTER_TYPE_V6_MULTICAST} values. 1178 * @return true if request is sent successfully, false otherwise. 1179 */ 1180 public boolean addRxFilter(byte type) { 1181 synchronized (mLock) { 1182 final String methodStr = "addRxFilter"; 1183 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1184 try { 1185 SupplicantStatus status = mISupplicantStaIface.addRxFilter(type); 1186 return checkStatusAndLogFailure(status, methodStr); 1187 } catch (RemoteException e) { 1188 handleRemoteException(e, methodStr); 1189 return false; 1190 } 1191 } 1192 } 1193 1194 /** 1195 * Remove an RX filter. 1196 * 1197 * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or 1198 * {@link #RX_FILTER_TYPE_V6_MULTICAST} values. 1199 * @return true if request is sent successfully, false otherwise. 1200 */ 1201 public boolean removeRxFilter(byte type) { 1202 synchronized (mLock) { 1203 final String methodStr = "removeRxFilter"; 1204 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1205 try { 1206 SupplicantStatus status = mISupplicantStaIface.removeRxFilter(type); 1207 return checkStatusAndLogFailure(status, methodStr); 1208 } catch (RemoteException e) { 1209 handleRemoteException(e, methodStr); 1210 return false; 1211 } 1212 } 1213 } 1214 1215 public static final byte BT_COEX_MODE_ENABLED = ISupplicantStaIface.BtCoexistenceMode.ENABLED; 1216 public static final byte BT_COEX_MODE_DISABLED = ISupplicantStaIface.BtCoexistenceMode.DISABLED; 1217 public static final byte BT_COEX_MODE_SENSE = ISupplicantStaIface.BtCoexistenceMode.SENSE; 1218 /** 1219 * Set Bt co existense mode. 1220 * 1221 * @param mode one of the above {@link #BT_COEX_MODE_ENABLED}, {@link #BT_COEX_MODE_DISABLED} 1222 * or {@link #BT_COEX_MODE_SENSE} values. 1223 * @return true if request is sent successfully, false otherwise. 1224 */ 1225 public boolean setBtCoexistenceMode(byte mode) { 1226 synchronized (mLock) { 1227 final String methodStr = "setBtCoexistenceMode"; 1228 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1229 try { 1230 SupplicantStatus status = mISupplicantStaIface.setBtCoexistenceMode(mode); 1231 return checkStatusAndLogFailure(status, methodStr); 1232 } catch (RemoteException e) { 1233 handleRemoteException(e, methodStr); 1234 return false; 1235 } 1236 } 1237 } 1238 1239 /** Enable or disable BT coexistence mode. 1240 * 1241 * @param enable true to enable, false to disable. 1242 * @return true if request is sent successfully, false otherwise. 1243 */ 1244 public boolean setBtCoexistenceScanModeEnabled(boolean enable) { 1245 synchronized (mLock) { 1246 final String methodStr = "setBtCoexistenceScanModeEnabled"; 1247 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1248 try { 1249 SupplicantStatus status = 1250 mISupplicantStaIface.setBtCoexistenceScanModeEnabled(enable); 1251 return checkStatusAndLogFailure(status, methodStr); 1252 } catch (RemoteException e) { 1253 handleRemoteException(e, methodStr); 1254 return false; 1255 } 1256 } 1257 } 1258 1259 /** 1260 * Enable or disable suspend mode optimizations. 1261 * 1262 * @param enable true to enable, false otherwise. 1263 * @return true if request is sent successfully, false otherwise. 1264 */ 1265 public boolean setSuspendModeEnabled(boolean enable) { 1266 synchronized (mLock) { 1267 final String methodStr = "setSuspendModeEnabled"; 1268 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1269 try { 1270 SupplicantStatus status = mISupplicantStaIface.setSuspendModeEnabled(enable); 1271 return checkStatusAndLogFailure(status, methodStr); 1272 } catch (RemoteException e) { 1273 handleRemoteException(e, methodStr); 1274 return false; 1275 } 1276 } 1277 } 1278 1279 /** 1280 * Set country code. 1281 * 1282 * @param codeStr 2 byte ASCII string. For ex: US, CA. 1283 * @return true if request is sent successfully, false otherwise. 1284 */ 1285 public boolean setCountryCode(String codeStr) { 1286 if (TextUtils.isEmpty(codeStr)) return false; 1287 return setCountryCode(NativeUtil.stringToByteArray(codeStr)); 1288 } 1289 1290 /** See ISupplicantStaIface.hal for documentation */ 1291 private boolean setCountryCode(byte[/* 2 */] code) { 1292 synchronized (mLock) { 1293 final String methodStr = "setCountryCode"; 1294 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1295 try { 1296 SupplicantStatus status = mISupplicantStaIface.setCountryCode(code); 1297 return checkStatusAndLogFailure(status, methodStr); 1298 } catch (RemoteException e) { 1299 handleRemoteException(e, methodStr); 1300 return false; 1301 } 1302 } 1303 } 1304 1305 /** 1306 * Start WPS pin registrar operation with the specified peer and pin. 1307 * 1308 * @param bssidStr BSSID of the peer. 1309 * @param pin Pin to be used. 1310 * @return true if request is sent successfully, false otherwise. 1311 */ 1312 public boolean startWpsRegistrar(String bssidStr, String pin) { 1313 if (TextUtils.isEmpty(bssidStr) || TextUtils.isEmpty(pin)) return false; 1314 return startWpsRegistrar(NativeUtil.macAddressToByteArray(bssidStr), pin); 1315 } 1316 1317 /** See ISupplicantStaIface.hal for documentation */ 1318 private boolean startWpsRegistrar(byte[/* 6 */] bssid, String pin) { 1319 synchronized (mLock) { 1320 final String methodStr = "startWpsRegistrar"; 1321 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1322 try { 1323 SupplicantStatus status = mISupplicantStaIface.startWpsRegistrar(bssid, pin); 1324 return checkStatusAndLogFailure(status, methodStr); 1325 } catch (RemoteException e) { 1326 handleRemoteException(e, methodStr); 1327 return false; 1328 } 1329 } 1330 } 1331 1332 /** 1333 * Start WPS pin display operation with the specified peer. 1334 * 1335 * @param bssidStr BSSID of the peer. 1336 * @return true if request is sent successfully, false otherwise. 1337 */ 1338 public boolean startWpsPbc(String bssidStr) { 1339 if (TextUtils.isEmpty(bssidStr)) return false; 1340 return startWpsPbc(NativeUtil.macAddressToByteArray(bssidStr)); 1341 } 1342 1343 /** See ISupplicantStaIface.hal for documentation */ 1344 private boolean startWpsPbc(byte[/* 6 */] bssid) { 1345 synchronized (mLock) { 1346 final String methodStr = "startWpsPbc"; 1347 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1348 try { 1349 SupplicantStatus status = mISupplicantStaIface.startWpsPbc(bssid); 1350 return checkStatusAndLogFailure(status, methodStr); 1351 } catch (RemoteException e) { 1352 handleRemoteException(e, methodStr); 1353 return false; 1354 } 1355 } 1356 } 1357 1358 /** 1359 * Start WPS pin keypad operation with the specified pin. 1360 * 1361 * @param pin Pin to be used. 1362 * @return true if request is sent successfully, false otherwise. 1363 */ 1364 public boolean startWpsPinKeypad(String pin) { 1365 if (TextUtils.isEmpty(pin)) return false; 1366 synchronized (mLock) { 1367 final String methodStr = "startWpsPinKeypad"; 1368 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1369 try { 1370 SupplicantStatus status = mISupplicantStaIface.startWpsPinKeypad(pin); 1371 return checkStatusAndLogFailure(status, methodStr); 1372 } catch (RemoteException e) { 1373 handleRemoteException(e, methodStr); 1374 return false; 1375 } 1376 } 1377 } 1378 1379 /** 1380 * Start WPS pin display operation with the specified peer. 1381 * 1382 * @param bssidStr BSSID of the peer. 1383 * @return new pin generated on success, null otherwise. 1384 */ 1385 public String startWpsPinDisplay(String bssidStr) { 1386 if (TextUtils.isEmpty(bssidStr)) return null; 1387 return startWpsPinDisplay(NativeUtil.macAddressToByteArray(bssidStr)); 1388 } 1389 1390 /** See ISupplicantStaIface.hal for documentation */ 1391 private String startWpsPinDisplay(byte[/* 6 */] bssid) { 1392 synchronized (mLock) { 1393 final String methodStr = "startWpsPinDisplay"; 1394 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 1395 final Mutable<String> gotPin = new Mutable<>(); 1396 try { 1397 mISupplicantStaIface.startWpsPinDisplay(bssid, 1398 (SupplicantStatus status, String pin) -> { 1399 if (checkStatusAndLogFailure(status, methodStr)) { 1400 gotPin.value = pin; 1401 } 1402 }); 1403 } catch (RemoteException e) { 1404 handleRemoteException(e, methodStr); 1405 } 1406 return gotPin.value; 1407 } 1408 } 1409 1410 /** 1411 * Cancels any ongoing WPS requests. 1412 * 1413 * @return true if request is sent successfully, false otherwise. 1414 */ 1415 public boolean cancelWps() { 1416 synchronized (mLock) { 1417 final String methodStr = "cancelWps"; 1418 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1419 try { 1420 SupplicantStatus status = mISupplicantStaIface.cancelWps(); 1421 return checkStatusAndLogFailure(status, methodStr); 1422 } catch (RemoteException e) { 1423 handleRemoteException(e, methodStr); 1424 return false; 1425 } 1426 } 1427 } 1428 1429 /** 1430 * Sets whether to use external sim for SIM/USIM processing. 1431 * 1432 * @param useExternalSim true to enable, false otherwise. 1433 * @return true if request is sent successfully, false otherwise. 1434 */ 1435 public boolean setExternalSim(boolean useExternalSim) { 1436 synchronized (mLock) { 1437 final String methodStr = "setExternalSim"; 1438 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1439 try { 1440 SupplicantStatus status = mISupplicantStaIface.setExternalSim(useExternalSim); 1441 return checkStatusAndLogFailure(status, methodStr); 1442 } catch (RemoteException e) { 1443 handleRemoteException(e, methodStr); 1444 return false; 1445 } 1446 } 1447 } 1448 1449 public static final int LOG_LEVEL_EXCESSIVE = ISupplicant.DebugLevel.EXCESSIVE; 1450 public static final int LOG_LEVEL_MSGDUMP = ISupplicant.DebugLevel.MSGDUMP; 1451 public static final int LOG_LEVEL_DEBUG = ISupplicant.DebugLevel.DEBUG; 1452 public static final int LOG_LEVEL_INFO = ISupplicant.DebugLevel.INFO; 1453 public static final int LOG_LEVEL_WARNING = ISupplicant.DebugLevel.WARNING; 1454 public static final int LOG_LEVEL_ERROR = ISupplicant.DebugLevel.ERROR; 1455 /** 1456 * Set the debug log level for wpa_supplicant 1457 * @param level One of the above {@link #LOG_LEVEL_EXCESSIVE} - {@link #LOG_LEVEL_ERROR} value. 1458 * @return true if request is sent successfully, false otherwise. 1459 */ 1460 public boolean setLogLevel(int level) { 1461 return setDebugParams(level, false, false); 1462 } 1463 1464 /** See ISupplicant.hal for documentation */ 1465 private boolean setDebugParams(int level, boolean showTimestamp, boolean showKeys) { 1466 synchronized (mLock) { 1467 final String methodStr = "setDebugParams"; 1468 if (!checkSupplicantAndLogFailure(methodStr)) return false; 1469 try { 1470 SupplicantStatus status = 1471 mISupplicant.setDebugParams(level, showTimestamp, showKeys); 1472 return checkStatusAndLogFailure(status, methodStr); 1473 } catch (RemoteException e) { 1474 handleRemoteException(e, methodStr); 1475 return false; 1476 } 1477 } 1478 } 1479 1480 /** 1481 * Set concurrency priority between P2P & STA operations. 1482 * 1483 * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations, 1484 * false otherwise. 1485 * @return true if request is sent successfully, false otherwise. 1486 */ 1487 public boolean setConcurrencyPriority(boolean isStaHigherPriority) { 1488 if (isStaHigherPriority) { 1489 return setConcurrencyPriority(IfaceType.STA); 1490 } else { 1491 return setConcurrencyPriority(IfaceType.P2P); 1492 } 1493 } 1494 1495 /** See ISupplicant.hal for documentation */ 1496 private boolean setConcurrencyPriority(int type) { 1497 synchronized (mLock) { 1498 final String methodStr = "setConcurrencyPriority"; 1499 if (!checkSupplicantAndLogFailure(methodStr)) return false; 1500 try { 1501 SupplicantStatus status = mISupplicant.setConcurrencyPriority(type); 1502 return checkStatusAndLogFailure(status, methodStr); 1503 } catch (RemoteException e) { 1504 handleRemoteException(e, methodStr); 1505 return false; 1506 } 1507 } 1508 } 1509 1510 /** 1511 * Returns false if Supplicant is null, and logs failure to call methodStr 1512 */ 1513 private boolean checkSupplicantAndLogFailure(final String methodStr) { 1514 if (mISupplicant == null) { 1515 Log.e(TAG, "Can't call " + methodStr + ", ISupplicant is null"); 1516 return false; 1517 } 1518 return true; 1519 } 1520 1521 /** 1522 * Returns false if SupplicantStaIface is null, and logs failure to call methodStr 1523 */ 1524 private boolean checkSupplicantStaIfaceAndLogFailure(final String methodStr) { 1525 if (mISupplicantStaIface == null) { 1526 Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaIface is null"); 1527 return false; 1528 } 1529 return true; 1530 } 1531 1532 /** 1533 * Returns true if provided status code is SUCCESS, logs debug message and returns false 1534 * otherwise 1535 */ 1536 private boolean checkStatusAndLogFailure(SupplicantStatus status, 1537 final String methodStr) { 1538 if (status.code != SupplicantStatusCode.SUCCESS) { 1539 Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed: " 1540 + supplicantStatusCodeToString(status.code) + ", " + status.debugMessage); 1541 return false; 1542 } else { 1543 if (mVerboseLoggingEnabled) { 1544 Log.d(TAG, "ISupplicantStaIface." + methodStr + " succeeded"); 1545 } 1546 return true; 1547 } 1548 } 1549 1550 /** 1551 * Helper function to log callbacks. 1552 */ 1553 private void logCallback(final String methodStr) { 1554 if (mVerboseLoggingEnabled) { 1555 Log.d(TAG, "ISupplicantStaIfaceCallback." + methodStr + " received"); 1556 } 1557 } 1558 1559 1560 private void handleRemoteException(RemoteException e, String methodStr) { 1561 supplicantServiceDiedHandler(); 1562 Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e); 1563 } 1564 1565 /** 1566 * Converts SupplicantStatus code values to strings for debug logging 1567 * TODO(b/34811152) Remove this, or make it more break resistance 1568 */ 1569 public static String supplicantStatusCodeToString(int code) { 1570 switch (code) { 1571 case 0: 1572 return "SUCCESS"; 1573 case 1: 1574 return "FAILURE_UNKNOWN"; 1575 case 2: 1576 return "FAILURE_ARGS_INVALID"; 1577 case 3: 1578 return "FAILURE_IFACE_INVALID"; 1579 case 4: 1580 return "FAILURE_IFACE_UNKNOWN"; 1581 case 5: 1582 return "FAILURE_IFACE_EXISTS"; 1583 case 6: 1584 return "FAILURE_IFACE_DISABLED"; 1585 case 7: 1586 return "FAILURE_IFACE_NOT_DISCONNECTED"; 1587 case 8: 1588 return "FAILURE_NETWORK_INVALID"; 1589 case 9: 1590 return "FAILURE_NETWORK_UNKNOWN"; 1591 default: 1592 return "??? UNKNOWN_CODE"; 1593 } 1594 } 1595 1596 1597 /** 1598 * Converts the Wps config method string to the equivalent enum value. 1599 */ 1600 private static short stringToWpsConfigMethod(String configMethod) { 1601 switch (configMethod) { 1602 case "usba": 1603 return WpsConfigMethods.USBA; 1604 case "ethernet": 1605 return WpsConfigMethods.ETHERNET; 1606 case "label": 1607 return WpsConfigMethods.LABEL; 1608 case "display": 1609 return WpsConfigMethods.DISPLAY; 1610 case "int_nfc_token": 1611 return WpsConfigMethods.INT_NFC_TOKEN; 1612 case "ext_nfc_token": 1613 return WpsConfigMethods.EXT_NFC_TOKEN; 1614 case "nfc_interface": 1615 return WpsConfigMethods.NFC_INTERFACE; 1616 case "push_button": 1617 return WpsConfigMethods.PUSHBUTTON; 1618 case "keypad": 1619 return WpsConfigMethods.KEYPAD; 1620 case "virtual_push_button": 1621 return WpsConfigMethods.VIRT_PUSHBUTTON; 1622 case "physical_push_button": 1623 return WpsConfigMethods.PHY_PUSHBUTTON; 1624 case "p2ps": 1625 return WpsConfigMethods.P2PS; 1626 case "virtual_display": 1627 return WpsConfigMethods.VIRT_DISPLAY; 1628 case "physical_display": 1629 return WpsConfigMethods.PHY_DISPLAY; 1630 default: 1631 throw new IllegalArgumentException( 1632 "Invalid WPS config method: " + configMethod); 1633 } 1634 } 1635 1636 /** 1637 * Converts the supplicant state received from HIDL to the equivalent framework state. 1638 */ 1639 private static SupplicantState supplicantHidlStateToFrameworkState(int state) { 1640 switch (state) { 1641 case ISupplicantStaIfaceCallback.State.DISCONNECTED: 1642 return SupplicantState.DISCONNECTED; 1643 case ISupplicantStaIfaceCallback.State.IFACE_DISABLED: 1644 return SupplicantState.INTERFACE_DISABLED; 1645 case ISupplicantStaIfaceCallback.State.INACTIVE: 1646 return SupplicantState.INACTIVE; 1647 case ISupplicantStaIfaceCallback.State.SCANNING: 1648 return SupplicantState.SCANNING; 1649 case ISupplicantStaIfaceCallback.State.AUTHENTICATING: 1650 return SupplicantState.AUTHENTICATING; 1651 case ISupplicantStaIfaceCallback.State.ASSOCIATING: 1652 return SupplicantState.ASSOCIATING; 1653 case ISupplicantStaIfaceCallback.State.ASSOCIATED: 1654 return SupplicantState.ASSOCIATED; 1655 case ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE: 1656 return SupplicantState.FOUR_WAY_HANDSHAKE; 1657 case ISupplicantStaIfaceCallback.State.GROUP_HANDSHAKE: 1658 return SupplicantState.GROUP_HANDSHAKE; 1659 case ISupplicantStaIfaceCallback.State.COMPLETED: 1660 return SupplicantState.COMPLETED; 1661 default: 1662 throw new IllegalArgumentException("Invalid state: " + state); 1663 } 1664 } 1665 1666 private static class Mutable<E> { 1667 public E value; 1668 1669 Mutable() { 1670 value = null; 1671 } 1672 1673 Mutable(E value) { 1674 this.value = value; 1675 } 1676 } 1677 1678 private class SupplicantStaIfaceHalCallback extends ISupplicantStaIfaceCallback.Stub { 1679 /** 1680 * Parses the provided payload into an ANQP element. 1681 * 1682 * @param infoID Element type. 1683 * @param payload Raw payload bytes. 1684 * @return AnqpElement instance on success, null on failure. 1685 */ 1686 private ANQPElement parseAnqpElement(Constants.ANQPElementType infoID, 1687 ArrayList<Byte> payload) { 1688 try { 1689 return Constants.getANQPElementID(infoID) != null 1690 ? ANQPParser.parseElement( 1691 infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))) 1692 : ANQPParser.parseHS20Element( 1693 infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))); 1694 } catch (IOException | BufferUnderflowException e) { 1695 Log.e(TAG, "Failed parsing ANQP element payload: " + infoID, e); 1696 return null; 1697 } 1698 } 1699 1700 /** 1701 * Parse the ANQP element data and add to the provided elements map if successful. 1702 * 1703 * @param elementsMap Map to add the parsed out element to. 1704 * @param infoID Element type. 1705 * @param payload Raw payload bytes. 1706 */ 1707 private void addAnqpElementToMap(Map<Constants.ANQPElementType, ANQPElement> elementsMap, 1708 Constants.ANQPElementType infoID, 1709 ArrayList<Byte> payload) { 1710 if (payload == null || payload.isEmpty()) return; 1711 ANQPElement element = parseAnqpElement(infoID, payload); 1712 if (element != null) { 1713 elementsMap.put(infoID, element); 1714 } 1715 } 1716 1717 /** 1718 * Helper utility to convert the bssid bytes to long. 1719 */ 1720 private Long toLongBssid(byte[] bssidBytes) { 1721 try { 1722 return ByteBufferReader.readInteger( 1723 ByteBuffer.wrap(bssidBytes), ByteOrder.BIG_ENDIAN, bssidBytes.length); 1724 } catch (BufferUnderflowException | IllegalArgumentException e) { 1725 return 0L; 1726 } 1727 } 1728 1729 @Override 1730 public void onNetworkAdded(int id) { 1731 logCallback("onNetworkAdded"); 1732 } 1733 1734 @Override 1735 public void onNetworkRemoved(int id) { 1736 logCallback("onNetworkRemoved"); 1737 } 1738 1739 @Override 1740 public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, 1741 ArrayList<Byte> ssid) { 1742 logCallback("onStateChanged"); 1743 synchronized (mLock) { 1744 SupplicantState newSupplicantState = supplicantHidlStateToFrameworkState(newState); 1745 WifiSsid wifiSsid = 1746 WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid)); 1747 String bssidStr = NativeUtil.macAddressFromByteArray(bssid); 1748 mWifiMonitor.broadcastSupplicantStateChangeEvent( 1749 mIfaceName, mFrameworkNetworkId, wifiSsid, bssidStr, newSupplicantState); 1750 if (newSupplicantState == SupplicantState.ASSOCIATED) { 1751 mWifiMonitor.broadcastAssociationSuccesfulEvent(mIfaceName, bssidStr); 1752 } else if (newSupplicantState == SupplicantState.COMPLETED) { 1753 mWifiMonitor.broadcastNetworkConnectionEvent( 1754 mIfaceName, mFrameworkNetworkId, bssidStr); 1755 } 1756 } 1757 } 1758 1759 @Override 1760 public void onAnqpQueryDone(byte[/* 6 */] bssid, 1761 ISupplicantStaIfaceCallback.AnqpData data, 1762 ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) { 1763 logCallback("onAnqpQueryDone"); 1764 synchronized (mLock) { 1765 Map<Constants.ANQPElementType, ANQPElement> elementsMap = new HashMap<>(); 1766 addAnqpElementToMap(elementsMap, ANQPVenueName, data.venueName); 1767 addAnqpElementToMap(elementsMap, ANQPRoamingConsortium, data.roamingConsortium); 1768 addAnqpElementToMap( 1769 elementsMap, ANQPIPAddrAvailability, data.ipAddrTypeAvailability); 1770 addAnqpElementToMap(elementsMap, ANQPNAIRealm, data.naiRealm); 1771 addAnqpElementToMap(elementsMap, ANQP3GPPNetwork, data.anqp3gppCellularNetwork); 1772 addAnqpElementToMap(elementsMap, ANQPDomName, data.domainName); 1773 addAnqpElementToMap(elementsMap, HSFriendlyName, hs20Data.operatorFriendlyName); 1774 addAnqpElementToMap(elementsMap, HSWANMetrics, hs20Data.wanMetrics); 1775 addAnqpElementToMap(elementsMap, HSConnCapability, hs20Data.connectionCapability); 1776 addAnqpElementToMap(elementsMap, HSOSUProviders, hs20Data.osuProvidersList); 1777 mWifiMonitor.broadcastAnqpDoneEvent( 1778 mIfaceName, new AnqpEvent(toLongBssid(bssid), elementsMap)); 1779 } 1780 } 1781 1782 @Override 1783 public void onHs20IconQueryDone(byte[/* 6 */] bssid, String fileName, 1784 ArrayList<Byte> data) { 1785 logCallback("onHs20IconQueryDone"); 1786 synchronized (mLock) { 1787 mWifiMonitor.broadcastIconDoneEvent( 1788 mIfaceName, 1789 new IconEvent(toLongBssid(bssid), fileName, data.size(), 1790 NativeUtil.byteArrayFromArrayList(data))); 1791 } 1792 } 1793 1794 @Override 1795 public void onHs20SubscriptionRemediation(byte[/* 6 */] bssid, byte osuMethod, String url) { 1796 logCallback("onHs20SubscriptionRemediation"); 1797 synchronized (mLock) { 1798 mWifiMonitor.broadcastWnmEvent( 1799 mIfaceName, new WnmData(toLongBssid(bssid), url, osuMethod)); 1800 } 1801 } 1802 1803 @Override 1804 public void onHs20DeauthImminentNotice(byte[/* 6 */] bssid, int reasonCode, 1805 int reAuthDelayInSec, String url) { 1806 logCallback("onHs20DeauthImminentNotice"); 1807 synchronized (mLock) { 1808 mWifiMonitor.broadcastWnmEvent( 1809 mIfaceName, 1810 new WnmData(toLongBssid(bssid), url, reasonCode == WnmData.ESS, 1811 reAuthDelayInSec)); 1812 } 1813 } 1814 1815 @Override 1816 public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int reasonCode) { 1817 logCallback("onDisconnected"); 1818 synchronized (mLock) { 1819 mWifiMonitor.broadcastNetworkDisconnectionEvent( 1820 mIfaceName, locallyGenerated ? 1 : 0, reasonCode, 1821 NativeUtil.macAddressFromByteArray(bssid)); 1822 } 1823 } 1824 1825 @Override 1826 public void onAssociationRejected(byte[/* 6 */] bssid, int statusCode) { 1827 logCallback("onAssociationRejected"); 1828 synchronized (mLock) { 1829 // TODO(b/35464954): Need to figure out when to trigger 1830 // |WifiMonitor.AUTHENTICATION_FAILURE_REASON_WRONG_PSWD| 1831 mWifiMonitor.broadcastAssociationRejectionEvent(mIfaceName, statusCode, 1832 NativeUtil.macAddressFromByteArray(bssid)); 1833 } 1834 } 1835 1836 @Override 1837 public void onAuthenticationTimeout(byte[/* 6 */] bssid) { 1838 logCallback("onAuthenticationTimeout"); 1839 synchronized (mLock) { 1840 mWifiMonitor.broadcastAuthenticationFailureEvent( 1841 mIfaceName, WifiMonitor.AUTHENTICATION_FAILURE_REASON_TIMEOUT); 1842 } 1843 } 1844 1845 @Override 1846 public void onEapFailure() { 1847 logCallback("onEapFailure"); 1848 synchronized (mLock) { 1849 mWifiMonitor.broadcastAuthenticationFailureEvent( 1850 mIfaceName, WifiMonitor.AUTHENTICATION_FAILURE_REASON_EAP_FAILURE); 1851 } 1852 } 1853 1854 @Override 1855 public void onWpsEventSuccess() { 1856 logCallback("onWpsEventSuccess"); 1857 synchronized (mLock) { 1858 mWifiMonitor.broadcastWpsSuccessEvent(mIfaceName); 1859 } 1860 } 1861 1862 @Override 1863 public void onWpsEventFail(byte[/* 6 */] bssid, short configError, short errorInd) { 1864 logCallback("onWpsEventFail"); 1865 synchronized (mLock) { 1866 if (configError == WpsConfigError.MSG_TIMEOUT 1867 && errorInd == WpsErrorIndication.NO_ERROR) { 1868 mWifiMonitor.broadcastWpsTimeoutEvent(mIfaceName); 1869 } else { 1870 mWifiMonitor.broadcastWpsFailEvent(mIfaceName, configError, errorInd); 1871 } 1872 } 1873 } 1874 1875 @Override 1876 public void onWpsEventPbcOverlap() { 1877 logCallback("onWpsEventPbcOverlap"); 1878 synchronized (mLock) { 1879 mWifiMonitor.broadcastWpsOverlapEvent(mIfaceName); 1880 } 1881 } 1882 1883 @Override 1884 public void onExtRadioWorkStart(int id) { 1885 logCallback("onExtRadioWorkStart"); 1886 } 1887 1888 @Override 1889 public void onExtRadioWorkTimeout(int id) { 1890 logCallback("onExtRadioWorkTimeout"); 1891 } 1892 } 1893 1894 private void logd(String s) { 1895 Log.d(TAG, s); 1896 } 1897 1898 private void logi(String s) { 1899 Log.i(TAG, s); 1900 } 1901 1902 private void loge(String s) { 1903 Log.e(TAG, s); 1904 } 1905} 1906