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