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