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