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