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