SupplicantStaIfaceHal.java revision 5f39baacf16b55c5551574bd1d973cdb14f70c45
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.server.wifi; 17 18import android.content.Context; 19import android.hardware.wifi.supplicant.V1_0.ISupplicant; 20import android.hardware.wifi.supplicant.V1_0.ISupplicantIface; 21import android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork; 22import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface; 23import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; 24import android.hardware.wifi.supplicant.V1_0.IfaceType; 25import android.hardware.wifi.supplicant.V1_0.SupplicantStatus; 26import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; 27import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; 28import android.hidl.manager.V1_0.IServiceManager; 29import android.hidl.manager.V1_0.IServiceNotification; 30import android.net.IpConfiguration; 31import android.net.wifi.WifiConfiguration; 32import android.os.RemoteException; 33import android.util.Log; 34import android.util.SparseArray; 35 36import com.android.server.wifi.util.NativeUtil; 37 38import java.nio.ByteBuffer; 39import java.nio.ByteOrder; 40import java.util.ArrayList; 41import java.util.HashMap; 42import java.util.List; 43import java.util.Map; 44import java.util.regex.Matcher; 45import java.util.regex.Pattern; 46 47/** 48 * Hal calls for bring up/shut down of the supplicant daemon and for 49 * sending requests to the supplicant daemon 50 */ 51public class SupplicantStaIfaceHal { 52 private static final boolean DBG = false; 53 private static final String TAG = "SupplicantStaIfaceHal"; 54 private static final String SERVICE_MANAGER_NAME = "manager"; 55 /** 56 * Regex pattern for extracting the wps device type bytes. 57 * Matches a strings like the following: "<categ>-<OUI>-<subcateg>"; 58 */ 59 private static final Pattern WPS_DEVICE_TYPE_PATTERN = 60 Pattern.compile("^(\\d{1,2})-([0-9a-fA-F]{8})-(\\d{1,2})$"); 61 62 private IServiceManager mIServiceManager = null; 63 // Supplicant HAL interface objects 64 private ISupplicant mISupplicant; 65 private ISupplicantStaIface mISupplicantStaIface; 66 // Currently configured network in wpa_supplicant 67 private SupplicantStaNetworkHal mCurrentNetwork; 68 // Currently configured network's framework network Id. 69 private int mFrameworkNetworkId; 70 private final Object mLock = new Object(); 71 private final Context mContext; 72 private final WifiMonitor mWifiMonitor; 73 74 public SupplicantStaIfaceHal(Context context, WifiMonitor monitor) { 75 mContext = context; 76 mWifiMonitor = monitor; 77 } 78 79 /** 80 * Registers a service notification for the ISupplicant service, which triggers intialization of 81 * the ISupplicantStaIface 82 * @return true if the service notification was successfully registered 83 */ 84 public boolean initialize() { 85 if (DBG) Log.i(TAG, "Registering ISupplicant service ready callback."); 86 synchronized (mLock) { 87 mISupplicant = null; 88 mISupplicantStaIface = null; 89 if (mIServiceManager != null) { 90 // Already have an IServiceManager and serviceNotification registered, don't 91 // don't register another. 92 return true; 93 } 94 try { 95 mIServiceManager = getServiceManagerMockable(); 96 if (mIServiceManager == null) { 97 Log.e(TAG, "Failed to get HIDL Service Manager"); 98 return false; 99 } 100 if (!mIServiceManager.linkToDeath(cookie -> { 101 Log.wtf(TAG, "IServiceManager died: cookie=" + cookie); 102 synchronized (mLock) { 103 supplicantServiceDiedHandler(); 104 mIServiceManager = null; // Will need to register a new ServiceNotification 105 } 106 }, 0)) { 107 Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); 108 supplicantServiceDiedHandler(); 109 mIServiceManager = null; // Will need to register a new ServiceNotification 110 return false; 111 } 112 IServiceNotification serviceNotificationCb = new IServiceNotification.Stub() { 113 public void onRegistration(String fqName, String name, boolean preexisting) { 114 synchronized (mLock) { 115 if (DBG) { 116 Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName 117 + ", " + name + " preexisting=" + preexisting); 118 } 119 if (!initSupplicantService() || !initSupplicantStaIface()) { 120 Log.e(TAG, "initalizing ISupplicantIfaces failed."); 121 supplicantServiceDiedHandler(); 122 } else { 123 Log.i(TAG, "Completed initialization of ISupplicant interfaces."); 124 } 125 } 126 } 127 }; 128 /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it 129 exists */ 130 if (!mIServiceManager.registerForNotifications(ISupplicant.kInterfaceName, 131 "", serviceNotificationCb)) { 132 Log.e(TAG, "Failed to register for notifications to " 133 + ISupplicant.kInterfaceName); 134 mIServiceManager = null; // Will need to register a new ServiceNotification 135 return false; 136 } 137 } catch (RemoteException e) { 138 Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: " 139 + e); 140 supplicantServiceDiedHandler(); 141 } 142 return true; 143 } 144 } 145 146 private boolean initSupplicantService() { 147 synchronized (mLock) { 148 try { 149 mISupplicant = getSupplicantMockable(); 150 } catch (RemoteException e) { 151 Log.e(TAG, "ISupplicant.getService exception: " + e); 152 return false; 153 } 154 if (mISupplicant == null) { 155 Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup"); 156 return false; 157 } 158 } 159 return true; 160 } 161 162 private boolean initSupplicantStaIface() { 163 synchronized (mLock) { 164 /** List all supplicant Ifaces */ 165 final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>(); 166 try { 167 mISupplicant.listInterfaces((SupplicantStatus status, 168 ArrayList<ISupplicant.IfaceInfo> ifaces) -> { 169 if (status.code != SupplicantStatusCode.SUCCESS) { 170 Log.e(TAG, "Getting Supplicant Interfaces failed: " + status.code); 171 return; 172 } 173 supplicantIfaces.addAll(ifaces); 174 }); 175 } catch (RemoteException e) { 176 Log.e(TAG, "ISupplicant.listInterfaces exception: " + e); 177 return false; 178 } 179 if (supplicantIfaces.size() == 0) { 180 Log.e(TAG, "Got zero HIDL supplicant ifaces. Stopping supplicant HIDL startup."); 181 return false; 182 } 183 Mutable<ISupplicantIface> supplicantIface = new Mutable<>(); 184 for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) { 185 if (ifaceInfo.type == IfaceType.STA) { 186 try { 187 mISupplicant.getInterface(ifaceInfo, 188 (SupplicantStatus status, ISupplicantIface iface) -> { 189 if (status.code != SupplicantStatusCode.SUCCESS) { 190 Log.e(TAG, "Failed to get ISupplicantIface " + status.code); 191 return; 192 } 193 supplicantIface.value = iface; 194 }); 195 } catch (RemoteException e) { 196 Log.e(TAG, "ISupplicant.getInterface exception: " + e); 197 return false; 198 } 199 break; 200 } 201 } 202 if (supplicantIface.value == null) { 203 Log.e(TAG, "initSupplicantStaIface got null iface"); 204 return false; 205 } 206 mISupplicantStaIface = getStaIfaceMockable(supplicantIface.value); 207 return true; 208 } 209 } 210 211 private void supplicantServiceDiedHandler() { 212 synchronized (mLock) { 213 mISupplicant = null; 214 mISupplicantStaIface = null; 215 } 216 } 217 218 /** 219 * Signals whether Initialization completed successfully. Only necessary for testing, is not 220 * needed to guard calls etc. 221 */ 222 public boolean isInitializationComplete() { 223 return mISupplicantStaIface != null; 224 } 225 226 /** 227 * Wrapper functions to access static HAL methods, created to be mockable in unit tests 228 */ 229 protected IServiceManager getServiceManagerMockable() throws RemoteException { 230 return IServiceManager.getService(SERVICE_MANAGER_NAME); 231 } 232 233 protected ISupplicant getSupplicantMockable() throws RemoteException { 234 return ISupplicant.getService(); 235 } 236 237 protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) { 238 return ISupplicantStaIface.asInterface(iface.asBinder()); 239 } 240 241 /** 242 * Add a network configuration to wpa_supplicant. 243 * 244 * @param config Config corresponding to the network. 245 * @return SupplicantStaNetwork of the added network in wpa_supplicant. 246 */ 247 private SupplicantStaNetworkHal addNetwork(WifiConfiguration config) { 248 logi("addSupplicantStaNetwork via HIDL"); 249 if (config == null) { 250 loge("Cannot add NULL network!"); 251 return null; 252 } 253 SupplicantStaNetworkHal network = addNetwork(); 254 if (network == null) { 255 loge("Failed to add a network!"); 256 return null; 257 } 258 if (network.saveWifiConfiguration(config)) { 259 return network; 260 } else { 261 loge("Failed to save variables for: " + config.configKey()); 262 return null; 263 } 264 } 265 266 /** 267 * Add the provided network configuration to wpa_supplicant and initiate connection to it. 268 * This method does the following: 269 * 1. Triggers disconnect command to wpa_supplicant (if |shouldDisconnect| is true). 270 * 2. Remove any existing network in wpa_supplicant. 271 * 3. Add a new network to wpa_supplicant. 272 * 4. Save the provided configuration to wpa_supplicant. 273 * 5. Select the new network in wpa_supplicant. 274 * 275 * @param config WifiConfiguration parameters for the provided network. 276 * @param shouldDisconnect whether to trigger a disconnection or not. 277 * @return {@code true} if it succeeds, {@code false} otherwise 278 */ 279 public boolean connectToNetwork(WifiConfiguration config, boolean shouldDisconnect) { 280 mFrameworkNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 281 mCurrentNetwork = null; 282 logd("connectToNetwork " + config.configKey() 283 + " (shouldDisconnect " + shouldDisconnect + ")"); 284 if (shouldDisconnect && !disconnect()) { 285 loge("Failed to trigger disconnect"); 286 return false; 287 } 288 if (!removeAllNetworks()) { 289 loge("Failed to remove existing networks"); 290 return false; 291 } 292 mCurrentNetwork = addNetwork(config); 293 if (mCurrentNetwork == null) { 294 loge("Failed to add/save network configuration: " + config.configKey()); 295 return false; 296 } 297 if (!mCurrentNetwork.select()) { 298 loge("Failed to select network configuration: " + config.configKey()); 299 return false; 300 } 301 mFrameworkNetworkId = config.networkId; 302 return true; 303 } 304 305 /** 306 * Initiates roaming to the already configured network in wpa_supplicant. If the network 307 * configuration provided does not match the already configured network, then this triggers 308 * a new connection attempt (instead of roam). 309 * 1. First check if we're attempting to connect to the same network as we currently have 310 * configured. 311 * 2. Set the new bssid for the network in wpa_supplicant. 312 * 3. Trigger reassociate command to wpa_supplicant. 313 * 314 * @param config WifiConfiguration parameters for the provided network. 315 * @return {@code true} if it succeeds, {@code false} otherwise 316 */ 317 public boolean roamToNetwork(WifiConfiguration config) { 318 if (mFrameworkNetworkId != config.networkId || mCurrentNetwork == null) { 319 Log.w(TAG, "Cannot roam to a different network, initiate new connection. " 320 + "Current network ID: " + mFrameworkNetworkId); 321 return connectToNetwork(config, false); 322 } 323 String bssid = config.getNetworkSelectionStatus().getNetworkSelectionBSSID(); 324 logd("roamToNetwork" + config.configKey() + " (bssid " + bssid + ")"); 325 if (!mCurrentNetwork.setBssid(bssid)) { 326 loge("Failed to set new bssid on network: " + config.configKey()); 327 return false; 328 } 329 if (!reassociate()) { 330 loge("Failed to trigger reassociate"); 331 return false; 332 } 333 return true; 334 } 335 336 /** 337 * Load all the configured networks from wpa_supplicant. 338 * 339 * @param configs Map of configuration key to configuration objects corresponding to all 340 * the networks. 341 * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf 342 * @return true if succeeds, false otherwise. 343 */ 344 public boolean loadNetworks(Map<String, WifiConfiguration> configs, 345 SparseArray<Map<String, String>> networkExtras) { 346 List<Integer> networkIds = listNetworks(); 347 if (networkIds == null) { 348 Log.e(TAG, "Failed to list networks"); 349 return false; 350 } 351 for (Integer networkId : networkIds) { 352 SupplicantStaNetworkHal network = getNetwork(networkId); 353 if (network == null) { 354 Log.e(TAG, "Failed to get network with ID: " + networkId); 355 return false; 356 } 357 WifiConfiguration config = new WifiConfiguration(); 358 Map<String, String> networkExtra = new HashMap<>(); 359 if (!network.loadWifiConfiguration(config, networkExtra)) { 360 Log.e(TAG, "Failed to load wifi configuration for network with ID: " + networkId); 361 return false; 362 } 363 // Set the default IP assignments. 364 config.setIpAssignment(IpConfiguration.IpAssignment.DHCP); 365 config.setProxySettings(IpConfiguration.ProxySettings.NONE); 366 367 networkExtras.put(networkId, networkExtra); 368 String configKey = networkExtra.get(SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY); 369 final WifiConfiguration duplicateConfig = configs.put(configKey, config); 370 if (duplicateConfig != null) { 371 // The network is already known. Overwrite the duplicate entry. 372 Log.i(TAG, "Replacing duplicate network: " + duplicateConfig.networkId); 373 removeNetwork(duplicateConfig.networkId); 374 networkExtras.remove(duplicateConfig.networkId); 375 } 376 } 377 return true; 378 } 379 380 /** 381 * Remove all networks from supplicant 382 */ 383 public boolean removeAllNetworks() { 384 synchronized (mLock) { 385 ArrayList<Integer> networks = listNetworks(); 386 if (networks == null) { 387 Log.e(TAG, "removeAllNetworks failed, got null networks"); 388 return false; 389 } 390 for (int id : networks) { 391 if (!removeNetwork(id)) { 392 Log.e(TAG, "removeAllNetworks failed to remove network: " + id); 393 return false; 394 } 395 } 396 } 397 return true; 398 } 399 400 /** 401 * Set the currently configured network's bssid. 402 * 403 * @param bssidStr Bssid to set in the form of "XX:XX:XX:XX:XX:XX" 404 * @return true if succeeds, false otherwise. 405 */ 406 public boolean setCurrentNetworkBssid(String bssidStr) { 407 if (mCurrentNetwork == null) return false; 408 return mCurrentNetwork.setBssid(bssidStr); 409 } 410 411 /** 412 * Get the currently configured network's WPS NFC token. 413 * 414 * @return Hex string corresponding to the WPS NFC token. 415 */ 416 public String getCurrentNetworkWpsNfcConfigurationToken() { 417 if (mCurrentNetwork == null) return null; 418 return mCurrentNetwork.getWpsNfcConfigurationToken(); 419 } 420 421 /** 422 * Gets the interface name. 423 * 424 * @return returns the name of Iface or null if the call fails 425 */ 426 private String getName() { 427 synchronized (mLock) { 428 final String methodStr = "getName"; 429 if (DBG) Log.i(TAG, methodStr); 430 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 431 final Mutable<String> gotName = new Mutable<>(); 432 try { 433 mISupplicantStaIface.getName((SupplicantStatus status, String name) -> { 434 if (checkStatusAndLogFailure(status, methodStr)) { 435 gotName.value = name; 436 437 } 438 }); 439 } catch (RemoteException e) { 440 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e); 441 supplicantServiceDiedHandler(); 442 } 443 return gotName.value; 444 } 445 } 446 447 /** 448 * Adds a new network. 449 * 450 * @return The ISupplicantNetwork object for the new network, or null if the call fails 451 */ 452 private SupplicantStaNetworkHal addNetwork() { 453 synchronized (mLock) { 454 final String methodStr = "addNetwork"; 455 if (DBG) Log.i(TAG, methodStr); 456 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 457 Mutable<ISupplicantNetwork> newNetwork = new Mutable<>(); 458 try { 459 mISupplicantStaIface.addNetwork((SupplicantStatus status, 460 ISupplicantNetwork network) -> { 461 if (checkStatusAndLogFailure(status, methodStr)) { 462 newNetwork.value = network; 463 } 464 }); 465 } catch (RemoteException e) { 466 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e); 467 supplicantServiceDiedHandler(); 468 } 469 if (newNetwork.value != null) { 470 return getStaNetworkMockable( 471 ISupplicantStaNetwork.asInterface(newNetwork.value.asBinder())); 472 } else { 473 return null; 474 } 475 } 476 } 477 478 /** 479 * Remove network from supplicant with network Id 480 * 481 * @return true if request is sent successfully, false otherwise. 482 */ 483 private boolean removeNetwork(int id) { 484 synchronized (mLock) { 485 final String methodStr = "removeNetwork"; 486 if (DBG) Log.i(TAG, methodStr); 487 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 488 try { 489 SupplicantStatus status = mISupplicantStaIface.removeNetwork(id); 490 return checkStatusAndLogFailure(status, methodStr); 491 } catch (RemoteException e) { 492 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 493 supplicantServiceDiedHandler(); 494 return false; 495 } 496 } 497 } 498 499 /** 500 * Use this to mock the creation of SupplicantStaNetworkHal instance. 501 * 502 * @param iSupplicantStaNetwork ISupplicantStaNetwork instance retrieved from HIDL. 503 * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if 504 * the call fails 505 */ 506 protected SupplicantStaNetworkHal getStaNetworkMockable( 507 ISupplicantStaNetwork iSupplicantStaNetwork) { 508 return new SupplicantStaNetworkHal(iSupplicantStaNetwork, mContext, mWifiMonitor); 509 } 510 511 /** 512 * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if 513 * the call fails 514 */ 515 private SupplicantStaNetworkHal getNetwork(int id) { 516 synchronized (mLock) { 517 final String methodStr = "getNetwork"; 518 if (DBG) Log.i(TAG, methodStr); 519 Mutable<ISupplicantNetwork> gotNetwork = new Mutable<>(); 520 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 521 try { 522 mISupplicantStaIface.getNetwork(id, (SupplicantStatus status, 523 ISupplicantNetwork network) -> { 524 if (checkStatusAndLogFailure(status, methodStr)) { 525 gotNetwork.value = network; 526 } 527 }); 528 } catch (RemoteException e) { 529 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e); 530 supplicantServiceDiedHandler(); 531 } 532 if (gotNetwork.value != null) { 533 return getStaNetworkMockable( 534 ISupplicantStaNetwork.asInterface(gotNetwork.value.asBinder())); 535 } else { 536 return null; 537 } 538 } 539 } 540 541 /** 542 * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns 543 * null if the call fails 544 */ 545 private java.util.ArrayList<Integer> listNetworks() { 546 synchronized (mLock) { 547 final String methodStr = "listNetworks"; 548 if (DBG) Log.i(TAG, methodStr); 549 Mutable<ArrayList<Integer>> networkIdList = new Mutable<>(); 550 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 551 try { 552 mISupplicantStaIface.listNetworks((SupplicantStatus status, 553 java.util.ArrayList<Integer> networkIds) -> { 554 if (checkStatusAndLogFailure(status, methodStr)) { 555 networkIdList.value = networkIds; 556 } 557 }); 558 } catch (RemoteException e) { 559 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e); 560 supplicantServiceDiedHandler(); 561 } 562 return networkIdList.value; 563 } 564 } 565 566 /** 567 * Set WPS device name. 568 * 569 * @param name String to be set. 570 * @return true if request is sent successfully, false otherwise. 571 */ 572 public boolean setWpsDeviceName(String name) { 573 synchronized (mLock) { 574 final String methodStr = "setWpsDeviceName"; 575 if (DBG) Log.i(TAG, methodStr); 576 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 577 try { 578 SupplicantStatus status = mISupplicantStaIface.setWpsDeviceName(name); 579 return checkStatusAndLogFailure(status, methodStr); 580 } catch (RemoteException e) { 581 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 582 supplicantServiceDiedHandler(); 583 return false; 584 } 585 } 586 } 587 588 /** 589 * Set WPS device type. 590 * 591 * @param typeStr Type specified as a string. Used format: <categ>-<OUI>-<subcateg> 592 * @return true if request is sent successfully, false otherwise. 593 */ 594 public boolean setWpsDeviceType(String typeStr) { 595 Matcher match = WPS_DEVICE_TYPE_PATTERN.matcher(typeStr); 596 if (!match.find() || match.groupCount() != 3) { 597 Log.e(TAG, "Malformed WPS device type " + typeStr); 598 return false; 599 } 600 short categ = Short.parseShort(match.group(1)); 601 byte[] oui = NativeUtil.hexStringToByteArray(match.group(2)); 602 short subCateg = Short.parseShort(match.group(3)); 603 604 byte[] bytes = new byte[8]; 605 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); 606 byteBuffer.putShort(categ); 607 byteBuffer.put(oui); 608 byteBuffer.putShort(subCateg); 609 return setWpsDeviceType(bytes); 610 } 611 612 private boolean setWpsDeviceType(byte[/* 8 */] type) { 613 synchronized (mLock) { 614 final String methodStr = "setWpsDeviceType"; 615 if (DBG) Log.i(TAG, methodStr); 616 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 617 try { 618 SupplicantStatus status = mISupplicantStaIface.setWpsDeviceType(type); 619 return checkStatusAndLogFailure(status, methodStr); 620 } catch (RemoteException e) { 621 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 622 supplicantServiceDiedHandler(); 623 return false; 624 } 625 } 626 } 627 628 /** 629 * Set WPS manufacturer. 630 * 631 * @param manufacturer String to be set. 632 * @return true if request is sent successfully, false otherwise. 633 */ 634 public boolean setWpsManufacturer(String manufacturer) { 635 synchronized (mLock) { 636 final String methodStr = "setWpsManufacturer"; 637 if (DBG) Log.i(TAG, methodStr); 638 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 639 try { 640 SupplicantStatus status = mISupplicantStaIface.setWpsManufacturer(manufacturer); 641 return checkStatusAndLogFailure(status, methodStr); 642 } catch (RemoteException e) { 643 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 644 supplicantServiceDiedHandler(); 645 return false; 646 } 647 } 648 } 649 650 /** 651 * Set WPS model name. 652 * 653 * @param modelName String to be set. 654 * @return true if request is sent successfully, false otherwise. 655 */ 656 public boolean setWpsModelName(String modelName) { 657 synchronized (mLock) { 658 final String methodStr = "setWpsModelName"; 659 if (DBG) Log.i(TAG, methodStr); 660 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 661 try { 662 SupplicantStatus status = mISupplicantStaIface.setWpsModelName(modelName); 663 return checkStatusAndLogFailure(status, methodStr); 664 } catch (RemoteException e) { 665 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 666 supplicantServiceDiedHandler(); 667 return false; 668 } 669 } 670 } 671 672 /** 673 * Set WPS model number. 674 * 675 * @param modelNumber String to be set. 676 * @return true if request is sent successfully, false otherwise. 677 */ 678 public boolean setWpsModelNumber(String modelNumber) { 679 synchronized (mLock) { 680 final String methodStr = "setWpsModelNumber"; 681 if (DBG) Log.i(TAG, methodStr); 682 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 683 try { 684 SupplicantStatus status = mISupplicantStaIface.setWpsModelNumber(modelNumber); 685 return checkStatusAndLogFailure(status, methodStr); 686 } catch (RemoteException e) { 687 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 688 supplicantServiceDiedHandler(); 689 return false; 690 } 691 } 692 } 693 694 /** 695 * Set WPS serial number. 696 * 697 * @param serialNumber String to be set. 698 * @return true if request is sent successfully, false otherwise. 699 */ 700 public boolean setWpsSerialNumber(String serialNumber) { 701 synchronized (mLock) { 702 final String methodStr = "setWpsSerialNumber"; 703 if (DBG) Log.i(TAG, methodStr); 704 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 705 try { 706 SupplicantStatus status = mISupplicantStaIface.setWpsSerialNumber(serialNumber); 707 return checkStatusAndLogFailure(status, methodStr); 708 } catch (RemoteException e) { 709 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 710 supplicantServiceDiedHandler(); 711 return false; 712 } 713 } 714 } 715 716 /** 717 * Set WPS config methods 718 * 719 * @param configMethodsStr List of config methods. 720 * @return true if request is sent successfully, false otherwise. 721 */ 722 public boolean setWpsConfigMethods(String configMethodsStr) { 723 short configMethodsMask = 0; 724 String[] configMethodsStrArr = configMethodsStr.split("\\s+"); 725 for (int i = 0; i < configMethodsStrArr.length; i++) { 726 configMethodsMask |= stringToWpsConfigMethod(configMethodsStrArr[i]); 727 } 728 return setWpsConfigMethods(configMethodsMask); 729 } 730 731 private boolean setWpsConfigMethods(short configMethods) { 732 synchronized (mLock) { 733 final String methodStr = "setWpsConfigMethods"; 734 if (DBG) Log.i(TAG, methodStr); 735 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 736 try { 737 SupplicantStatus status = mISupplicantStaIface.setWpsConfigMethods(configMethods); 738 return checkStatusAndLogFailure(status, methodStr); 739 } catch (RemoteException e) { 740 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 741 supplicantServiceDiedHandler(); 742 return false; 743 } 744 } 745 } 746 747 /** 748 * Trigger a reassociation even if the iface is currently connected. 749 * 750 * @return true if request is sent successfully, false otherwise. 751 */ 752 public boolean reassociate() { 753 synchronized (mLock) { 754 final String methodStr = "reassociate"; 755 if (DBG) Log.i(TAG, methodStr); 756 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 757 try { 758 SupplicantStatus status = mISupplicantStaIface.reassociate(); 759 return checkStatusAndLogFailure(status, methodStr); 760 } catch (RemoteException e) { 761 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 762 supplicantServiceDiedHandler(); 763 return false; 764 } 765 } 766 } 767 768 /** 769 * Trigger a reconnection if the iface is disconnected. 770 * 771 * @return true if request is sent successfully, false otherwise. 772 */ 773 public boolean reconnect() { 774 synchronized (mLock) { 775 final String methodStr = "reconnect"; 776 if (DBG) Log.i(TAG, methodStr); 777 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 778 try { 779 SupplicantStatus status = mISupplicantStaIface.reconnect(); 780 return checkStatusAndLogFailure(status, methodStr); 781 } catch (RemoteException e) { 782 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 783 supplicantServiceDiedHandler(); 784 return false; 785 } 786 } 787 } 788 789 /** 790 * Trigger a disconnection from the currently connected network. 791 * 792 * @return true if request is sent successfully, false otherwise. 793 */ 794 public boolean disconnect() { 795 synchronized (mLock) { 796 final String methodStr = "disconnect"; 797 if (DBG) Log.i(TAG, methodStr); 798 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 799 try { 800 SupplicantStatus status = mISupplicantStaIface.disconnect(); 801 return checkStatusAndLogFailure(status, methodStr); 802 } catch (RemoteException e) { 803 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 804 supplicantServiceDiedHandler(); 805 return false; 806 } 807 } 808 } 809 810 /** 811 * Enable or disable power save mode. 812 * 813 * @param enable true to enable, false to disable. 814 * @return true if request is sent successfully, false otherwise. 815 */ 816 public boolean setPowerSave(boolean enable) { 817 synchronized (mLock) { 818 final String methodStr = "setPowerSave"; 819 if (DBG) Log.i(TAG, methodStr); 820 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 821 try { 822 SupplicantStatus status = mISupplicantStaIface.setPowerSave(enable); 823 return checkStatusAndLogFailure(status, methodStr); 824 } catch (RemoteException e) { 825 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 826 supplicantServiceDiedHandler(); 827 return false; 828 } 829 } 830 } 831 832 /** 833 * Initiate TDLS discover with the specified AP. 834 * 835 * @param macAddress MAC Address of the AP. 836 * @return true if request is sent successfully, false otherwise. 837 */ 838 public boolean initiateTdlsDiscover(String macAddress) { 839 return initiateTdlsDiscover(NativeUtil.macAddressToByteArray(macAddress)); 840 } 841 /** See ISupplicantStaIface.hal for documentation */ 842 private boolean initiateTdlsDiscover(byte[/* 6 */] macAddress) { 843 synchronized (mLock) { 844 final String methodStr = "initiateTdlsDiscover"; 845 if (DBG) Log.i(TAG, methodStr); 846 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 847 try { 848 SupplicantStatus status = mISupplicantStaIface.initiateTdlsDiscover(macAddress); 849 return checkStatusAndLogFailure(status, methodStr); 850 } catch (RemoteException e) { 851 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 852 supplicantServiceDiedHandler(); 853 return false; 854 } 855 } 856 } 857 858 /** 859 * Initiate TDLS setup with the specified AP. 860 * 861 * @param macAddress MAC Address of the AP. 862 * @return true if request is sent successfully, false otherwise. 863 */ 864 public boolean initiateTdlsSetup(String macAddress) { 865 return initiateTdlsSetup(NativeUtil.macAddressToByteArray(macAddress)); 866 } 867 /** See ISupplicantStaIface.hal for documentation */ 868 private boolean initiateTdlsSetup(byte[/* 6 */] macAddress) { 869 synchronized (mLock) { 870 final String methodStr = "initiateTdlsSetup"; 871 if (DBG) Log.i(TAG, methodStr); 872 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 873 try { 874 SupplicantStatus status = mISupplicantStaIface.initiateTdlsSetup(macAddress); 875 return checkStatusAndLogFailure(status, methodStr); 876 } catch (RemoteException e) { 877 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 878 supplicantServiceDiedHandler(); 879 return false; 880 } 881 } 882 } 883 884 /** 885 * Initiate TDLS teardown with the specified AP. 886 * @param macAddress MAC Address of the AP. 887 * @return true if request is sent successfully, false otherwise. 888 */ 889 public boolean initiateTdlsTeardown(String macAddress) { 890 return initiateTdlsTeardown(NativeUtil.macAddressToByteArray(macAddress)); 891 } 892 893 /** See ISupplicantStaIface.hal for documentation */ 894 private boolean initiateTdlsTeardown(byte[/* 6 */] macAddress) { 895 synchronized (mLock) { 896 final String methodStr = "initiateTdlsTeardown"; 897 if (DBG) Log.i(TAG, methodStr); 898 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 899 try { 900 SupplicantStatus status = mISupplicantStaIface.initiateTdlsTeardown(macAddress); 901 return checkStatusAndLogFailure(status, methodStr); 902 } catch (RemoteException e) { 903 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 904 supplicantServiceDiedHandler(); 905 return false; 906 } 907 } 908 } 909 910 /** 911 * Request the specified ANQP elements |elements| from the specified AP |bssid|. 912 * 913 * @param bssid BSSID of the AP 914 * @param infoElements ANQP elements to be queried. Refer to ISupplicantStaIface.AnqpInfoId. 915 * @param hs20SubTypes HS subtypes to be queried. Refer to ISupplicantStaIface.Hs20AnqpSubTypes. 916 * @return true if request is sent successfully, false otherwise. 917 */ 918 public boolean initiateAnqpQuery(String bssid, ArrayList<Short> infoElements, 919 ArrayList<Integer> hs20SubTypes) { 920 return initiateAnqpQuery( 921 NativeUtil.macAddressToByteArray(bssid), infoElements, hs20SubTypes); 922 } 923 924 /** See ISupplicantStaIface.hal for documentation */ 925 private boolean initiateAnqpQuery(byte[/* 6 */] macAddress, 926 java.util.ArrayList<Short> infoElements, java.util.ArrayList<Integer> subTypes) { 927 synchronized (mLock) { 928 final String methodStr = "initiateAnqpQuery"; 929 if (DBG) Log.i(TAG, methodStr); 930 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 931 try { 932 SupplicantStatus status = mISupplicantStaIface.initiateAnqpQuery(macAddress, 933 infoElements, subTypes); 934 return checkStatusAndLogFailure(status, methodStr); 935 } catch (RemoteException e) { 936 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 937 supplicantServiceDiedHandler(); 938 return false; 939 } 940 } 941 } 942 943 /** 944 * Request the specified ANQP ICON from the specified AP |bssid|. 945 * 946 * @param bssid BSSID of the AP 947 * @param fileName Name of the file to request. 948 * @return true if request is sent successfully, false otherwise. 949 */ 950 public boolean initiateHs20IconQuery(String bssid, String fileName) { 951 return initiateHs20IconQuery(NativeUtil.macAddressToByteArray(bssid), fileName); 952 } 953 954 /** See ISupplicantStaIface.hal for documentation */ 955 private boolean initiateHs20IconQuery(byte[/* 6 */] macAddress, String fileName) { 956 synchronized (mLock) { 957 final String methodStr = "initiateHs20IconQuery"; 958 if (DBG) Log.i(TAG, methodStr); 959 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 960 try { 961 SupplicantStatus status = mISupplicantStaIface.initiateHs20IconQuery(macAddress, 962 fileName); 963 return checkStatusAndLogFailure(status, methodStr); 964 } catch (RemoteException e) { 965 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 966 supplicantServiceDiedHandler(); 967 return false; 968 } 969 } 970 } 971 972 /** 973 * Makes a callback to HIDL to getMacAddress from supplicant 974 * 975 * @return string containing the MAC address, or null on a failed call 976 */ 977 public String getMacAddress() { 978 synchronized (mLock) { 979 final String methodStr = "getMacAddress"; 980 if (DBG) Log.i(TAG, methodStr); 981 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 982 Mutable<String> gotMac = new Mutable<>(); 983 try { 984 mISupplicantStaIface.getMacAddress((SupplicantStatus status, 985 byte[/* 6 */] macAddr) -> { 986 if (checkStatusAndLogFailure(status, methodStr)) { 987 gotMac.value = NativeUtil.macAddressFromByteArray(macAddr); 988 } 989 }); 990 } catch (RemoteException e) { 991 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e); 992 supplicantServiceDiedHandler(); 993 } 994 return gotMac.value; 995 } 996 } 997 998 /** 999 * Start using the added RX filters. 1000 * 1001 * @return true if request is sent successfully, false otherwise. 1002 */ 1003 public boolean startRxFilter() { 1004 synchronized (mLock) { 1005 final String methodStr = "startRxFilter"; 1006 if (DBG) Log.i(TAG, methodStr); 1007 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1008 try { 1009 SupplicantStatus status = mISupplicantStaIface.startRxFilter(); 1010 return checkStatusAndLogFailure(status, methodStr); 1011 } catch (RemoteException e) { 1012 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1013 supplicantServiceDiedHandler(); 1014 return false; 1015 } 1016 } 1017 } 1018 1019 /** 1020 * Stop using the added RX filters. 1021 * 1022 * @return true if request is sent successfully, false otherwise. 1023 */ 1024 public boolean stopRxFilter() { 1025 synchronized (mLock) { 1026 final String methodStr = "stopRxFilter"; 1027 if (DBG) Log.i(TAG, methodStr); 1028 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1029 try { 1030 SupplicantStatus status = mISupplicantStaIface.stopRxFilter(); 1031 return checkStatusAndLogFailure(status, methodStr); 1032 } catch (RemoteException e) { 1033 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1034 supplicantServiceDiedHandler(); 1035 return false; 1036 } 1037 } 1038 } 1039 1040 public static final byte RX_FILTER_TYPE_V4_MULTICAST = 1041 ISupplicantStaIface.RxFilterType.V6_MULTICAST; 1042 public static final byte RX_FILTER_TYPE_V6_MULTICAST = 1043 ISupplicantStaIface.RxFilterType.V6_MULTICAST; 1044 /** 1045 * Add an RX filter. 1046 * 1047 * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or 1048 * {@link #RX_FILTER_TYPE_V6_MULTICAST} values. 1049 * @return true if request is sent successfully, false otherwise. 1050 */ 1051 private boolean addRxFilter(byte type) { 1052 synchronized (mLock) { 1053 final String methodStr = "addRxFilter"; 1054 if (DBG) Log.i(TAG, methodStr); 1055 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1056 try { 1057 SupplicantStatus status = mISupplicantStaIface.addRxFilter(type); 1058 return checkStatusAndLogFailure(status, methodStr); 1059 } catch (RemoteException e) { 1060 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1061 supplicantServiceDiedHandler(); 1062 return false; 1063 } 1064 } 1065 } 1066 1067 /** 1068 * Remove an RX filter. 1069 * 1070 * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or 1071 * {@link #RX_FILTER_TYPE_V6_MULTICAST} values. 1072 * @return true if request is sent successfully, false otherwise. 1073 */ 1074 private boolean removeRxFilter(byte type) { 1075 synchronized (mLock) { 1076 final String methodStr = "removeRxFilter"; 1077 if (DBG) Log.i(TAG, methodStr); 1078 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1079 try { 1080 SupplicantStatus status = mISupplicantStaIface.removeRxFilter(type); 1081 return checkStatusAndLogFailure(status, methodStr); 1082 } catch (RemoteException e) { 1083 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1084 supplicantServiceDiedHandler(); 1085 return false; 1086 } 1087 } 1088 } 1089 1090 public static final byte BT_COEX_MODE_ENABLED = ISupplicantStaIface.BtCoexistenceMode.ENABLED; 1091 public static final byte BT_COEX_MODE_DISABLED = ISupplicantStaIface.BtCoexistenceMode.DISABLED; 1092 public static final byte BT_COEX_MODE_SENSE = ISupplicantStaIface.BtCoexistenceMode.SENSE; 1093 /** 1094 * Set Bt co existense mode. 1095 * 1096 * @param mode one of the above {@link #BT_COEX_MODE_ENABLED}, {@link #BT_COEX_MODE_DISABLED} 1097 * or {@link #BT_COEX_MODE_SENSE} values. 1098 * @return true if request is sent successfully, false otherwise. 1099 */ 1100 public boolean setBtCoexistenceMode(byte mode) { 1101 synchronized (mLock) { 1102 final String methodStr = "setBtCoexistenceMode"; 1103 if (DBG) Log.i(TAG, methodStr); 1104 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1105 try { 1106 SupplicantStatus status = mISupplicantStaIface.setBtCoexistenceMode(mode); 1107 return checkStatusAndLogFailure(status, methodStr); 1108 } catch (RemoteException e) { 1109 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1110 supplicantServiceDiedHandler(); 1111 return false; 1112 } 1113 } 1114 } 1115 1116 /** Enable or disable BT coexistence mode. 1117 * 1118 * @param enable true to enable, false to disable. 1119 * @return true if request is sent successfully, false otherwise. 1120 */ 1121 public boolean setBtCoexistenceScanModeEnabled(boolean enable) { 1122 synchronized (mLock) { 1123 final String methodStr = "setBtCoexistenceScanModeEnabled"; 1124 if (DBG) Log.i(TAG, methodStr); 1125 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1126 try { 1127 SupplicantStatus status = 1128 mISupplicantStaIface.setBtCoexistenceScanModeEnabled(enable); 1129 return checkStatusAndLogFailure(status, methodStr); 1130 } catch (RemoteException e) { 1131 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1132 supplicantServiceDiedHandler(); 1133 return false; 1134 } 1135 } 1136 } 1137 1138 /** 1139 * Enable or disable suspend mode optimizations. 1140 * 1141 * @param enable true to enable, false otherwise. 1142 * @return true if request is sent successfully, false otherwise. 1143 */ 1144 public boolean setSuspendModeEnabled(boolean enable) { 1145 synchronized (mLock) { 1146 final String methodStr = "setSuspendModeEnabled"; 1147 if (DBG) Log.i(TAG, methodStr); 1148 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1149 try { 1150 SupplicantStatus status = mISupplicantStaIface.setSuspendModeEnabled(enable); 1151 return checkStatusAndLogFailure(status, methodStr); 1152 } catch (RemoteException e) { 1153 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1154 supplicantServiceDiedHandler(); 1155 return false; 1156 } 1157 } 1158 } 1159 1160 /** 1161 * Set country code. 1162 * 1163 * @param codeStr 2 byte ASCII string. For ex: US, CA. 1164 * @return true if request is sent successfully, false otherwise. 1165 */ 1166 public boolean setCountryCode(String codeStr) { 1167 return setCountryCode(NativeUtil.stringToByteArray(codeStr)); 1168 } 1169 1170 /** See ISupplicantStaIface.hal for documentation */ 1171 private boolean setCountryCode(byte[/* 2 */] code) { 1172 synchronized (mLock) { 1173 final String methodStr = "setCountryCode"; 1174 if (DBG) Log.i(TAG, methodStr); 1175 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1176 try { 1177 SupplicantStatus status = mISupplicantStaIface.setCountryCode(code); 1178 return checkStatusAndLogFailure(status, methodStr); 1179 } catch (RemoteException e) { 1180 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1181 supplicantServiceDiedHandler(); 1182 return false; 1183 } 1184 } 1185 } 1186 1187 /** 1188 * Start WPS pin registrar operation with the specified peer and pin. 1189 * 1190 * @param bssidStr BSSID of the peer. 1191 * @param pin Pin to be used. 1192 * @return true if request is sent successfully, false otherwise. 1193 */ 1194 public boolean startWpsRegistrar(String bssidStr, String pin) { 1195 return startWpsRegistrar(NativeUtil.macAddressToByteArray(bssidStr), pin); 1196 } 1197 1198 /** See ISupplicantStaIface.hal for documentation */ 1199 private boolean startWpsRegistrar(byte[/* 6 */] bssid, String pin) { 1200 synchronized (mLock) { 1201 final String methodStr = "startWpsRegistrar"; 1202 if (DBG) Log.i(TAG, methodStr); 1203 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1204 try { 1205 SupplicantStatus status = mISupplicantStaIface.startWpsRegistrar(bssid, pin); 1206 return checkStatusAndLogFailure(status, methodStr); 1207 } catch (RemoteException e) { 1208 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1209 supplicantServiceDiedHandler(); 1210 return false; 1211 } 1212 } 1213 } 1214 1215 /** 1216 * Start WPS pin display operation with the specified peer. 1217 * 1218 * @param bssidStr BSSID of the peer. 1219 * @return true if request is sent successfully, false otherwise. 1220 */ 1221 public boolean startWpsPbc(String bssidStr) { 1222 return startWpsPbc(NativeUtil.macAddressToByteArray(bssidStr)); 1223 } 1224 1225 /** See ISupplicantStaIface.hal for documentation */ 1226 private boolean startWpsPbc(byte[/* 6 */] bssid) { 1227 synchronized (mLock) { 1228 final String methodStr = "startWpsPbc"; 1229 if (DBG) Log.i(TAG, methodStr); 1230 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1231 try { 1232 SupplicantStatus status = mISupplicantStaIface.startWpsPbc(bssid); 1233 return checkStatusAndLogFailure(status, methodStr); 1234 } catch (RemoteException e) { 1235 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1236 supplicantServiceDiedHandler(); 1237 return false; 1238 } 1239 } 1240 } 1241 1242 /** 1243 * Start WPS pin keypad operation with the specified pin. 1244 * 1245 * @param pin Pin to be used. 1246 * @return true if request is sent successfully, false otherwise. 1247 */ 1248 public boolean startWpsPinKeypad(String pin) { 1249 synchronized (mLock) { 1250 final String methodStr = "startWpsPinKeypad"; 1251 if (DBG) Log.i(TAG, methodStr); 1252 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1253 try { 1254 SupplicantStatus status = mISupplicantStaIface.startWpsPinKeypad(pin); 1255 return checkStatusAndLogFailure(status, methodStr); 1256 } catch (RemoteException e) { 1257 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1258 supplicantServiceDiedHandler(); 1259 return false; 1260 } 1261 } 1262 } 1263 1264 /** 1265 * Start WPS pin display operation with the specified peer. 1266 * 1267 * @param bssidStr BSSID of the peer. 1268 * @return new pin generated on success, null otherwise. 1269 */ 1270 public String startWpsPinDisplay(String bssidStr) { 1271 return startWpsPinDisplay(NativeUtil.macAddressToByteArray(bssidStr)); 1272 } 1273 1274 /** See ISupplicantStaIface.hal for documentation */ 1275 private String startWpsPinDisplay(byte[/* 6 */] bssid) { 1276 synchronized (mLock) { 1277 final String methodStr = "startWpsPinDisplay"; 1278 if (DBG) Log.i(TAG, methodStr); 1279 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 1280 final Mutable<String> gotPin = new Mutable<>(); 1281 try { 1282 mISupplicantStaIface.startWpsPinDisplay(bssid, 1283 (SupplicantStatus status, String pin) -> { 1284 if (checkStatusAndLogFailure(status, methodStr)) { 1285 gotPin.value = pin; 1286 } 1287 }); 1288 } catch (RemoteException e) { 1289 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1290 supplicantServiceDiedHandler(); 1291 } 1292 return gotPin.value; 1293 } 1294 } 1295 1296 /** 1297 * Cancels any ongoing WPS requests. 1298 * 1299 * @return true if request is sent successfully, false otherwise. 1300 */ 1301 public boolean cancelWps() { 1302 synchronized (mLock) { 1303 final String methodStr = "cancelWps"; 1304 if (DBG) Log.i(TAG, methodStr); 1305 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1306 try { 1307 SupplicantStatus status = mISupplicantStaIface.cancelWps(); 1308 return checkStatusAndLogFailure(status, methodStr); 1309 } catch (RemoteException e) { 1310 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1311 supplicantServiceDiedHandler(); 1312 return false; 1313 } 1314 } 1315 } 1316 1317 /** 1318 * Sets whether to use external sim for SIM/USIM processing. 1319 * 1320 * @param useExternalSim true to enable, false otherwise. 1321 * @return true if request is sent successfully, false otherwise. 1322 */ 1323 public boolean setExternalSim(boolean useExternalSim) { 1324 synchronized (mLock) { 1325 final String methodStr = "setExternalSim"; 1326 if (DBG) Log.i(TAG, methodStr); 1327 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1328 try { 1329 SupplicantStatus status = mISupplicantStaIface.setExternalSim(useExternalSim); 1330 return checkStatusAndLogFailure(status, methodStr); 1331 } catch (RemoteException e) { 1332 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1333 supplicantServiceDiedHandler(); 1334 return false; 1335 } 1336 } 1337 } 1338 1339 /** 1340 * Returns false if SupplicantStaIface is null, and logs failure to call methodStr 1341 */ 1342 private boolean checkSupplicantStaIfaceAndLogFailure(final String methodStr) { 1343 if (DBG) Log.i(TAG, methodStr); 1344 if (mISupplicantStaIface == null) { 1345 Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaIface is null"); 1346 return false; 1347 } 1348 return true; 1349 } 1350 1351 /** 1352 * Returns true if provided status code is SUCCESS, logs debug message and returns false 1353 * otherwise 1354 */ 1355 private static boolean checkStatusAndLogFailure(SupplicantStatus status, 1356 final String methodStr) { 1357 if (DBG) Log.i(TAG, methodStr); 1358 if (status.code != SupplicantStatusCode.SUCCESS) { 1359 Log.e(TAG, methodStr + " failed: " + supplicantStatusCodeToString(status.code) + ", " 1360 + status.debugMessage); 1361 return false; 1362 } 1363 return true; 1364 } 1365 1366 /** 1367 * Converts SupplicantStatus code values to strings for debug logging 1368 * TODO(b/34811152) Remove this, or make it more break resistance 1369 */ 1370 public static String supplicantStatusCodeToString(int code) { 1371 switch (code) { 1372 case 0: 1373 return "SUCCESS"; 1374 case 1: 1375 return "FAILURE_UNKNOWN"; 1376 case 2: 1377 return "FAILURE_ARGS_INVALID"; 1378 case 3: 1379 return "FAILURE_IFACE_INVALID"; 1380 case 4: 1381 return "FAILURE_IFACE_UNKNOWN"; 1382 case 5: 1383 return "FAILURE_IFACE_EXISTS"; 1384 case 6: 1385 return "FAILURE_IFACE_DISABLED"; 1386 case 7: 1387 return "FAILURE_IFACE_NOT_DISCONNECTED"; 1388 case 8: 1389 return "FAILURE_NETWORK_INVALID"; 1390 case 9: 1391 return "FAILURE_NETWORK_UNKNOWN"; 1392 default: 1393 return "??? UNKNOWN_CODE"; 1394 } 1395 } 1396 1397 1398 /** 1399 * Converts the Wps config method string to the equivalent enum value. 1400 */ 1401 private static short stringToWpsConfigMethod(String configMethod) { 1402 switch (configMethod) { 1403 case "usba": 1404 return WpsConfigMethods.USBA; 1405 case "ethernet": 1406 return WpsConfigMethods.ETHERNET; 1407 case "label": 1408 return WpsConfigMethods.LABEL; 1409 case "display": 1410 return WpsConfigMethods.DISPLAY; 1411 case "int_nfc_token": 1412 return WpsConfigMethods.INT_NFC_TOKEN; 1413 case "ext_nfc_token": 1414 return WpsConfigMethods.EXT_NFC_TOKEN; 1415 case "nfc_interface": 1416 return WpsConfigMethods.NFC_INTERFACE; 1417 case "push_button": 1418 return WpsConfigMethods.PUSHBUTTON; 1419 case "keypad": 1420 return WpsConfigMethods.KEYPAD; 1421 case "virtual_push_button": 1422 return WpsConfigMethods.VIRT_PUSHBUTTON; 1423 case "physical_push_button": 1424 return WpsConfigMethods.PHY_PUSHBUTTON; 1425 case "p2ps": 1426 return WpsConfigMethods.P2PS; 1427 case "virtual_display": 1428 return WpsConfigMethods.VIRT_DISPLAY; 1429 case "physical_display": 1430 return WpsConfigMethods.PHY_DISPLAY; 1431 default: 1432 throw new IllegalArgumentException( 1433 "Invalid WPS config method: " + configMethod); 1434 } 1435 } 1436 1437 private static class Mutable<E> { 1438 public E value; 1439 1440 Mutable() { 1441 value = null; 1442 } 1443 1444 Mutable(E value) { 1445 this.value = value; 1446 } 1447 } 1448 1449 private void logd(String s) { 1450 Log.d(TAG, s); 1451 } 1452 1453 private void logi(String s) { 1454 Log.i(TAG, s); 1455 } 1456 1457 private void loge(String s) { 1458 Log.e(TAG, s); 1459 } 1460} 1461