SupplicantStaIfaceHal.java revision 2a1078dc3729bab248bbd28c8336749481e045cf
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 /** See ISupplicant.hal for documentation */ 1450 public boolean enableAutoReconnect(boolean enable) { 1451 synchronized (mLock) { 1452 final String methodStr = "enableAutoReconnect"; 1453 if (!checkSupplicantAndLogFailure(methodStr)) return false; 1454 try { 1455 SupplicantStatus status = mISupplicantStaIface.enableAutoReconnect(enable); 1456 return checkStatusAndLogFailure(status, methodStr); 1457 } catch (RemoteException e) { 1458 handleRemoteException(e, methodStr); 1459 return false; 1460 } 1461 } 1462 } 1463 1464 public static final int LOG_LEVEL_EXCESSIVE = ISupplicant.DebugLevel.EXCESSIVE; 1465 public static final int LOG_LEVEL_MSGDUMP = ISupplicant.DebugLevel.MSGDUMP; 1466 public static final int LOG_LEVEL_DEBUG = ISupplicant.DebugLevel.DEBUG; 1467 public static final int LOG_LEVEL_INFO = ISupplicant.DebugLevel.INFO; 1468 public static final int LOG_LEVEL_WARNING = ISupplicant.DebugLevel.WARNING; 1469 public static final int LOG_LEVEL_ERROR = ISupplicant.DebugLevel.ERROR; 1470 /** 1471 * Set the debug log level for wpa_supplicant 1472 * @param level One of the above {@link #LOG_LEVEL_EXCESSIVE} - {@link #LOG_LEVEL_ERROR} value. 1473 * @return true if request is sent successfully, false otherwise. 1474 */ 1475 public boolean setLogLevel(int level) { 1476 return setDebugParams(level, false, false); 1477 } 1478 1479 /** See ISupplicant.hal for documentation */ 1480 private boolean setDebugParams(int level, boolean showTimestamp, boolean showKeys) { 1481 synchronized (mLock) { 1482 final String methodStr = "setDebugParams"; 1483 if (!checkSupplicantAndLogFailure(methodStr)) return false; 1484 try { 1485 SupplicantStatus status = 1486 mISupplicant.setDebugParams(level, showTimestamp, showKeys); 1487 return checkStatusAndLogFailure(status, methodStr); 1488 } catch (RemoteException e) { 1489 handleRemoteException(e, methodStr); 1490 return false; 1491 } 1492 } 1493 } 1494 1495 /** 1496 * Set concurrency priority between P2P & STA operations. 1497 * 1498 * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations, 1499 * false otherwise. 1500 * @return true if request is sent successfully, false otherwise. 1501 */ 1502 public boolean setConcurrencyPriority(boolean isStaHigherPriority) { 1503 if (isStaHigherPriority) { 1504 return setConcurrencyPriority(IfaceType.STA); 1505 } else { 1506 return setConcurrencyPriority(IfaceType.P2P); 1507 } 1508 } 1509 1510 /** See ISupplicant.hal for documentation */ 1511 private boolean setConcurrencyPriority(int type) { 1512 synchronized (mLock) { 1513 final String methodStr = "setConcurrencyPriority"; 1514 if (!checkSupplicantAndLogFailure(methodStr)) return false; 1515 try { 1516 SupplicantStatus status = mISupplicant.setConcurrencyPriority(type); 1517 return checkStatusAndLogFailure(status, methodStr); 1518 } catch (RemoteException e) { 1519 handleRemoteException(e, methodStr); 1520 return false; 1521 } 1522 } 1523 } 1524 1525 /** 1526 * Returns false if Supplicant is null, and logs failure to call methodStr 1527 */ 1528 private boolean checkSupplicantAndLogFailure(final String methodStr) { 1529 if (mISupplicant == null) { 1530 Log.e(TAG, "Can't call " + methodStr + ", ISupplicant is null"); 1531 return false; 1532 } 1533 return true; 1534 } 1535 1536 /** 1537 * Returns false if SupplicantStaIface is null, and logs failure to call methodStr 1538 */ 1539 private boolean checkSupplicantStaIfaceAndLogFailure(final String methodStr) { 1540 if (mISupplicantStaIface == null) { 1541 Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaIface is null"); 1542 return false; 1543 } 1544 return true; 1545 } 1546 1547 /** 1548 * Returns true if provided status code is SUCCESS, logs debug message and returns false 1549 * otherwise 1550 */ 1551 private boolean checkStatusAndLogFailure(SupplicantStatus status, 1552 final String methodStr) { 1553 if (status.code != SupplicantStatusCode.SUCCESS) { 1554 Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed: " 1555 + supplicantStatusCodeToString(status.code) + ", " + status.debugMessage); 1556 return false; 1557 } else { 1558 if (mVerboseLoggingEnabled) { 1559 Log.d(TAG, "ISupplicantStaIface." + methodStr + " succeeded"); 1560 } 1561 return true; 1562 } 1563 } 1564 1565 /** 1566 * Helper function to log callbacks. 1567 */ 1568 private void logCallback(final String methodStr) { 1569 if (mVerboseLoggingEnabled) { 1570 Log.d(TAG, "ISupplicantStaIfaceCallback." + methodStr + " received"); 1571 } 1572 } 1573 1574 1575 private void handleRemoteException(RemoteException e, String methodStr) { 1576 supplicantServiceDiedHandler(); 1577 Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e); 1578 } 1579 1580 /** 1581 * Converts SupplicantStatus code values to strings for debug logging 1582 * TODO(b/34811152) Remove this, or make it more break resistance 1583 */ 1584 public static String supplicantStatusCodeToString(int code) { 1585 switch (code) { 1586 case 0: 1587 return "SUCCESS"; 1588 case 1: 1589 return "FAILURE_UNKNOWN"; 1590 case 2: 1591 return "FAILURE_ARGS_INVALID"; 1592 case 3: 1593 return "FAILURE_IFACE_INVALID"; 1594 case 4: 1595 return "FAILURE_IFACE_UNKNOWN"; 1596 case 5: 1597 return "FAILURE_IFACE_EXISTS"; 1598 case 6: 1599 return "FAILURE_IFACE_DISABLED"; 1600 case 7: 1601 return "FAILURE_IFACE_NOT_DISCONNECTED"; 1602 case 8: 1603 return "FAILURE_NETWORK_INVALID"; 1604 case 9: 1605 return "FAILURE_NETWORK_UNKNOWN"; 1606 default: 1607 return "??? UNKNOWN_CODE"; 1608 } 1609 } 1610 1611 1612 /** 1613 * Converts the Wps config method string to the equivalent enum value. 1614 */ 1615 private static short stringToWpsConfigMethod(String configMethod) { 1616 switch (configMethod) { 1617 case "usba": 1618 return WpsConfigMethods.USBA; 1619 case "ethernet": 1620 return WpsConfigMethods.ETHERNET; 1621 case "label": 1622 return WpsConfigMethods.LABEL; 1623 case "display": 1624 return WpsConfigMethods.DISPLAY; 1625 case "int_nfc_token": 1626 return WpsConfigMethods.INT_NFC_TOKEN; 1627 case "ext_nfc_token": 1628 return WpsConfigMethods.EXT_NFC_TOKEN; 1629 case "nfc_interface": 1630 return WpsConfigMethods.NFC_INTERFACE; 1631 case "push_button": 1632 return WpsConfigMethods.PUSHBUTTON; 1633 case "keypad": 1634 return WpsConfigMethods.KEYPAD; 1635 case "virtual_push_button": 1636 return WpsConfigMethods.VIRT_PUSHBUTTON; 1637 case "physical_push_button": 1638 return WpsConfigMethods.PHY_PUSHBUTTON; 1639 case "p2ps": 1640 return WpsConfigMethods.P2PS; 1641 case "virtual_display": 1642 return WpsConfigMethods.VIRT_DISPLAY; 1643 case "physical_display": 1644 return WpsConfigMethods.PHY_DISPLAY; 1645 default: 1646 throw new IllegalArgumentException( 1647 "Invalid WPS config method: " + configMethod); 1648 } 1649 } 1650 1651 /** 1652 * Converts the supplicant state received from HIDL to the equivalent framework state. 1653 */ 1654 private static SupplicantState supplicantHidlStateToFrameworkState(int state) { 1655 switch (state) { 1656 case ISupplicantStaIfaceCallback.State.DISCONNECTED: 1657 return SupplicantState.DISCONNECTED; 1658 case ISupplicantStaIfaceCallback.State.IFACE_DISABLED: 1659 return SupplicantState.INTERFACE_DISABLED; 1660 case ISupplicantStaIfaceCallback.State.INACTIVE: 1661 return SupplicantState.INACTIVE; 1662 case ISupplicantStaIfaceCallback.State.SCANNING: 1663 return SupplicantState.SCANNING; 1664 case ISupplicantStaIfaceCallback.State.AUTHENTICATING: 1665 return SupplicantState.AUTHENTICATING; 1666 case ISupplicantStaIfaceCallback.State.ASSOCIATING: 1667 return SupplicantState.ASSOCIATING; 1668 case ISupplicantStaIfaceCallback.State.ASSOCIATED: 1669 return SupplicantState.ASSOCIATED; 1670 case ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE: 1671 return SupplicantState.FOUR_WAY_HANDSHAKE; 1672 case ISupplicantStaIfaceCallback.State.GROUP_HANDSHAKE: 1673 return SupplicantState.GROUP_HANDSHAKE; 1674 case ISupplicantStaIfaceCallback.State.COMPLETED: 1675 return SupplicantState.COMPLETED; 1676 default: 1677 throw new IllegalArgumentException("Invalid state: " + state); 1678 } 1679 } 1680 1681 private static class Mutable<E> { 1682 public E value; 1683 1684 Mutable() { 1685 value = null; 1686 } 1687 1688 Mutable(E value) { 1689 this.value = value; 1690 } 1691 } 1692 1693 private class SupplicantStaIfaceHalCallback extends ISupplicantStaIfaceCallback.Stub { 1694 private static final int WLAN_REASON_IE_IN_4WAY_DIFFERS = 17; // IEEE 802.11i 1695 private boolean mStateIsFourway = false; // Used to help check for PSK password mismatch 1696 1697 /** 1698 * Parses the provided payload into an ANQP element. 1699 * 1700 * @param infoID Element type. 1701 * @param payload Raw payload bytes. 1702 * @return AnqpElement instance on success, null on failure. 1703 */ 1704 private ANQPElement parseAnqpElement(Constants.ANQPElementType infoID, 1705 ArrayList<Byte> payload) { 1706 try { 1707 return Constants.getANQPElementID(infoID) != null 1708 ? ANQPParser.parseElement( 1709 infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))) 1710 : ANQPParser.parseHS20Element( 1711 infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))); 1712 } catch (IOException | BufferUnderflowException e) { 1713 Log.e(TAG, "Failed parsing ANQP element payload: " + infoID, e); 1714 return null; 1715 } 1716 } 1717 1718 /** 1719 * Parse the ANQP element data and add to the provided elements map if successful. 1720 * 1721 * @param elementsMap Map to add the parsed out element to. 1722 * @param infoID Element type. 1723 * @param payload Raw payload bytes. 1724 */ 1725 private void addAnqpElementToMap(Map<Constants.ANQPElementType, ANQPElement> elementsMap, 1726 Constants.ANQPElementType infoID, 1727 ArrayList<Byte> payload) { 1728 if (payload == null || payload.isEmpty()) return; 1729 ANQPElement element = parseAnqpElement(infoID, payload); 1730 if (element != null) { 1731 elementsMap.put(infoID, element); 1732 } 1733 } 1734 1735 @Override 1736 public void onNetworkAdded(int id) { 1737 logCallback("onNetworkAdded"); 1738 } 1739 1740 @Override 1741 public void onNetworkRemoved(int id) { 1742 logCallback("onNetworkRemoved"); 1743 } 1744 1745 @Override 1746 public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, 1747 ArrayList<Byte> ssid) { 1748 logCallback("onStateChanged"); 1749 synchronized (mLock) { 1750 SupplicantState newSupplicantState = supplicantHidlStateToFrameworkState(newState); 1751 WifiSsid wifiSsid = 1752 WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid)); 1753 String bssidStr = NativeUtil.macAddressFromByteArray(bssid); 1754 mWifiMonitor.broadcastSupplicantStateChangeEvent( 1755 mIfaceName, mFrameworkNetworkId, wifiSsid, bssidStr, newSupplicantState); 1756 if (newSupplicantState == SupplicantState.ASSOCIATED) { 1757 mWifiMonitor.broadcastAssociationSuccesfulEvent(mIfaceName, bssidStr); 1758 } else if (newSupplicantState == SupplicantState.COMPLETED) { 1759 mWifiMonitor.broadcastNetworkConnectionEvent( 1760 mIfaceName, mFrameworkNetworkId, bssidStr); 1761 } 1762 mStateIsFourway = (newState == ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE); 1763 } 1764 } 1765 1766 @Override 1767 public void onAnqpQueryDone(byte[/* 6 */] bssid, 1768 ISupplicantStaIfaceCallback.AnqpData data, 1769 ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) { 1770 logCallback("onAnqpQueryDone"); 1771 synchronized (mLock) { 1772 Map<Constants.ANQPElementType, ANQPElement> elementsMap = new HashMap<>(); 1773 addAnqpElementToMap(elementsMap, ANQPVenueName, data.venueName); 1774 addAnqpElementToMap(elementsMap, ANQPRoamingConsortium, data.roamingConsortium); 1775 addAnqpElementToMap( 1776 elementsMap, ANQPIPAddrAvailability, data.ipAddrTypeAvailability); 1777 addAnqpElementToMap(elementsMap, ANQPNAIRealm, data.naiRealm); 1778 addAnqpElementToMap(elementsMap, ANQP3GPPNetwork, data.anqp3gppCellularNetwork); 1779 addAnqpElementToMap(elementsMap, ANQPDomName, data.domainName); 1780 addAnqpElementToMap(elementsMap, HSFriendlyName, hs20Data.operatorFriendlyName); 1781 addAnqpElementToMap(elementsMap, HSWANMetrics, hs20Data.wanMetrics); 1782 addAnqpElementToMap(elementsMap, HSConnCapability, hs20Data.connectionCapability); 1783 addAnqpElementToMap(elementsMap, HSOSUProviders, hs20Data.osuProvidersList); 1784 mWifiMonitor.broadcastAnqpDoneEvent( 1785 mIfaceName, new AnqpEvent(NativeUtil.macAddressToLong(bssid), elementsMap)); 1786 } 1787 } 1788 1789 @Override 1790 public void onHs20IconQueryDone(byte[/* 6 */] bssid, String fileName, 1791 ArrayList<Byte> data) { 1792 logCallback("onHs20IconQueryDone"); 1793 synchronized (mLock) { 1794 mWifiMonitor.broadcastIconDoneEvent( 1795 mIfaceName, 1796 new IconEvent(NativeUtil.macAddressToLong(bssid), fileName, data.size(), 1797 NativeUtil.byteArrayFromArrayList(data))); 1798 } 1799 } 1800 1801 @Override 1802 public void onHs20SubscriptionRemediation(byte[/* 6 */] bssid, byte osuMethod, String url) { 1803 logCallback("onHs20SubscriptionRemediation"); 1804 synchronized (mLock) { 1805 mWifiMonitor.broadcastWnmEvent( 1806 mIfaceName, 1807 new WnmData(NativeUtil.macAddressToLong(bssid), url, osuMethod)); 1808 } 1809 } 1810 1811 @Override 1812 public void onHs20DeauthImminentNotice(byte[/* 6 */] bssid, int reasonCode, 1813 int reAuthDelayInSec, String url) { 1814 logCallback("onHs20DeauthImminentNotice"); 1815 synchronized (mLock) { 1816 mWifiMonitor.broadcastWnmEvent( 1817 mIfaceName, 1818 new WnmData(NativeUtil.macAddressToLong(bssid), url, 1819 reasonCode == WnmData.ESS, reAuthDelayInSec)); 1820 } 1821 } 1822 1823 @Override 1824 public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int reasonCode) { 1825 logCallback("onDisconnected"); 1826 synchronized (mLock) { 1827 if (mVerboseLoggingEnabled) { 1828 Log.e(TAG, "onDisconnected 4way=" + mStateIsFourway 1829 + " locallyGenerated=" + locallyGenerated 1830 + " reasonCode=" + reasonCode); 1831 } 1832 if (mStateIsFourway 1833 && (!locallyGenerated || reasonCode != WLAN_REASON_IE_IN_4WAY_DIFFERS)) { 1834 mWifiMonitor.broadcastAuthenticationFailureEvent( 1835 mIfaceName, WifiMonitor.AUTHENTICATION_FAILURE_REASON_WRONG_PSWD); 1836 } 1837 mWifiMonitor.broadcastNetworkDisconnectionEvent( 1838 mIfaceName, locallyGenerated ? 1 : 0, reasonCode, 1839 NativeUtil.macAddressFromByteArray(bssid)); 1840 } 1841 } 1842 1843 @Override 1844 public void onAssociationRejected(byte[/* 6 */] bssid, int statusCode, boolean timedOut) { 1845 logCallback("onAssociationRejected"); 1846 synchronized (mLock) { 1847 mWifiMonitor.broadcastAssociationRejectionEvent(mIfaceName, statusCode, timedOut, 1848 NativeUtil.macAddressFromByteArray(bssid)); 1849 } 1850 } 1851 1852 @Override 1853 public void onAuthenticationTimeout(byte[/* 6 */] bssid) { 1854 logCallback("onAuthenticationTimeout"); 1855 synchronized (mLock) { 1856 mWifiMonitor.broadcastAuthenticationFailureEvent( 1857 mIfaceName, WifiMonitor.AUTHENTICATION_FAILURE_REASON_TIMEOUT); 1858 } 1859 } 1860 1861 @Override 1862 public void onEapFailure() { 1863 logCallback("onEapFailure"); 1864 synchronized (mLock) { 1865 mWifiMonitor.broadcastAuthenticationFailureEvent( 1866 mIfaceName, WifiMonitor.AUTHENTICATION_FAILURE_REASON_EAP_FAILURE); 1867 } 1868 } 1869 1870 @Override 1871 public void onWpsEventSuccess() { 1872 logCallback("onWpsEventSuccess"); 1873 synchronized (mLock) { 1874 mWifiMonitor.broadcastWpsSuccessEvent(mIfaceName); 1875 } 1876 } 1877 1878 @Override 1879 public void onWpsEventFail(byte[/* 6 */] bssid, short configError, short errorInd) { 1880 logCallback("onWpsEventFail"); 1881 synchronized (mLock) { 1882 if (configError == WpsConfigError.MSG_TIMEOUT 1883 && errorInd == WpsErrorIndication.NO_ERROR) { 1884 mWifiMonitor.broadcastWpsTimeoutEvent(mIfaceName); 1885 } else { 1886 mWifiMonitor.broadcastWpsFailEvent(mIfaceName, configError, errorInd); 1887 } 1888 } 1889 } 1890 1891 @Override 1892 public void onWpsEventPbcOverlap() { 1893 logCallback("onWpsEventPbcOverlap"); 1894 synchronized (mLock) { 1895 mWifiMonitor.broadcastWpsOverlapEvent(mIfaceName); 1896 } 1897 } 1898 1899 @Override 1900 public void onExtRadioWorkStart(int id) { 1901 logCallback("onExtRadioWorkStart"); 1902 } 1903 1904 @Override 1905 public void onExtRadioWorkTimeout(int id) { 1906 logCallback("onExtRadioWorkTimeout"); 1907 } 1908 } 1909 1910 private void logd(String s) { 1911 Log.d(TAG, s); 1912 } 1913 1914 private void logi(String s) { 1915 Log.i(TAG, s); 1916 } 1917 1918 private void loge(String s) { 1919 Log.e(TAG, s); 1920 } 1921} 1922