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