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