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