WifiManager.java revision e498475b187277309c81b38240c7e71ec049e369
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.net.wifi; 18 19import android.annotation.SdkConstant; 20import android.annotation.SdkConstant.SdkConstantType; 21import android.net.DhcpInfo; 22import android.os.Binder; 23import android.os.IBinder; 24import android.os.Handler; 25import android.os.RemoteException; 26 27import java.util.List; 28 29/** 30 * This class provides the primary API for managing all aspects of Wi-Fi 31 * connectivity. Get an instance of this class by calling 32 * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}. 33 34 * It deals with several categories of items: 35 * <ul> 36 * <li>The list of configured networks. The list can be viewed and updated, 37 * and attributes of individual entries can be modified.</li> 38 * <li>The currently active Wi-Fi network, if any. Connectivity can be 39 * established or torn down, and dynamic information about the state of 40 * the network can be queried.</li> 41 * <li>Results of access point scans, containing enough information to 42 * make decisions about what access point to connect to.</li> 43 * <li>It defines the names of various Intent actions that are broadcast 44 * upon any sort of change in Wi-Fi state. 45 * </ul> 46 * This is the API to use when performing Wi-Fi specific operations. To 47 * perform operations that pertain to network connectivity at an abstract 48 * level, use {@link android.net.ConnectivityManager}. 49 */ 50public class WifiManager { 51 52 // Supplicant error codes: 53 /** 54 * The error code if there was a problem authenticating. 55 */ 56 public static final int ERROR_AUTHENTICATING = 1; 57 58 /** 59 * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, 60 * enabling, disabling, or unknown. One extra provides this state as an int. 61 * Another extra provides the previous state, if available. 62 * 63 * @see #EXTRA_WIFI_STATE 64 * @see #EXTRA_PREVIOUS_WIFI_STATE 65 */ 66 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 67 public static final String WIFI_STATE_CHANGED_ACTION = 68 "android.net.wifi.WIFI_STATE_CHANGED"; 69 /** 70 * The lookup key for an int that indicates whether Wi-Fi is enabled, 71 * disabled, enabling, disabling, or unknown. Retrieve it with 72 * {@link android.content.Intent#getIntExtra(String,int)}. 73 * 74 * @see #WIFI_STATE_DISABLED 75 * @see #WIFI_STATE_DISABLING 76 * @see #WIFI_STATE_ENABLED 77 * @see #WIFI_STATE_ENABLING 78 * @see #WIFI_STATE_UNKNOWN 79 */ 80 public static final String EXTRA_WIFI_STATE = "wifi_state"; 81 /** 82 * The previous Wi-Fi state. 83 * 84 * @see #EXTRA_WIFI_STATE 85 */ 86 public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; 87 88 /** 89 * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if 90 * it finishes successfully. 91 * 92 * @see #WIFI_STATE_CHANGED_ACTION 93 * @see #getWifiState() 94 */ 95 public static final int WIFI_STATE_DISABLING = 0; 96 /** 97 * Wi-Fi is disabled. 98 * 99 * @see #WIFI_STATE_CHANGED_ACTION 100 * @see #getWifiState() 101 */ 102 public static final int WIFI_STATE_DISABLED = 1; 103 /** 104 * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if 105 * it finishes successfully. 106 * 107 * @see #WIFI_STATE_CHANGED_ACTION 108 * @see #getWifiState() 109 */ 110 public static final int WIFI_STATE_ENABLING = 2; 111 /** 112 * Wi-Fi is enabled. 113 * 114 * @see #WIFI_STATE_CHANGED_ACTION 115 * @see #getWifiState() 116 */ 117 public static final int WIFI_STATE_ENABLED = 3; 118 /** 119 * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling 120 * or disabling. 121 * 122 * @see #WIFI_STATE_CHANGED_ACTION 123 * @see #getWifiState() 124 */ 125 public static final int WIFI_STATE_UNKNOWN = 4; 126 127 /** 128 * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled, 129 * enabling, disabling, or failed. 130 * 131 * @hide 132 */ 133 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 134 public static final String WIFI_AP_STATE_CHANGED_ACTION = 135 "android.net.wifi.WIFI_AP_STATE_CHANGED"; 136 137 /** 138 * The lookup key for an int that indicates whether Wi-Fi AP is enabled, 139 * disabled, enabling, disabling, or failed. Retrieve it with 140 * {@link android.content.Intent#getIntExtra(String,int)}. 141 * 142 * @see #WIFI_AP_STATE_DISABLED 143 * @see #WIFI_AP_STATE_DISABLING 144 * @see #WIFI_AP_STATE_ENABLED 145 * @see #WIFI_AP_STATE_ENABLING 146 * @see #WIFI_AP_STATE_FAILED 147 * 148 * @hide 149 */ 150 public static final String EXTRA_WIFI_AP_STATE = "wifi_state"; 151 /** 152 * The previous Wi-Fi state. 153 * 154 * @see #EXTRA_WIFI_AP_STATE 155 * 156 * @hide 157 */ 158 public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; 159 /** 160 * Wi-Fi AP is currently being disabled. The state will change to 161 * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully. 162 * 163 * @see #WIFI_AP_STATE_CHANGED_ACTION 164 * @see #getWifiApState() 165 * 166 * @hide 167 */ 168 public static final int WIFI_AP_STATE_DISABLING = 10; 169 /** 170 * Wi-Fi AP is disabled. 171 * 172 * @see #WIFI_AP_STATE_CHANGED_ACTION 173 * @see #getWifiState() 174 * 175 * @hide 176 */ 177 public static final int WIFI_AP_STATE_DISABLED = 11; 178 /** 179 * Wi-Fi AP is currently being enabled. The state will change to 180 * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully. 181 * 182 * @see #WIFI_AP_STATE_CHANGED_ACTION 183 * @see #getWifiApState() 184 * 185 * @hide 186 */ 187 public static final int WIFI_AP_STATE_ENABLING = 12; 188 /** 189 * Wi-Fi AP is enabled. 190 * 191 * @see #WIFI_AP_STATE_CHANGED_ACTION 192 * @see #getWifiApState() 193 * 194 * @hide 195 */ 196 public static final int WIFI_AP_STATE_ENABLED = 13; 197 /** 198 * Wi-Fi AP is in a failed state. This state will occur when an error occurs during 199 * enabling or disabling 200 * 201 * @see #WIFI_AP_STATE_CHANGED_ACTION 202 * @see #getWifiApState() 203 * 204 * @hide 205 */ 206 public static final int WIFI_AP_STATE_FAILED = 14; 207 208 /** 209 * Broadcast intent action indicating that a connection to the supplicant has 210 * been established (and it is now possible 211 * to perform Wi-Fi operations) or the connection to the supplicant has been 212 * lost. One extra provides the connection state as a boolean, where {@code true} 213 * means CONNECTED. 214 * @see #EXTRA_SUPPLICANT_CONNECTED 215 */ 216 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 217 public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = 218 "android.net.wifi.supplicant.CONNECTION_CHANGE"; 219 /** 220 * The lookup key for a boolean that indicates whether a connection to 221 * the supplicant daemon has been gained or lost. {@code true} means 222 * a connection now exists. 223 * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. 224 */ 225 public static final String EXTRA_SUPPLICANT_CONNECTED = "connected"; 226 /** 227 * Broadcast intent action indicating that the state of Wi-Fi connectivity 228 * has changed. One extra provides the new state 229 * in the form of a {@link android.net.NetworkInfo} object. If the new state is 230 * CONNECTED, a second extra may provide the BSSID of the access point, 231 * as a {@code String}. 232 * @see #EXTRA_NETWORK_INFO 233 * @see #EXTRA_BSSID 234 */ 235 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 236 public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"; 237 /** 238 * The lookup key for a {@link android.net.NetworkInfo} object associated with the 239 * Wi-Fi network. Retrieve with 240 * {@link android.content.Intent#getParcelableExtra(String)}. 241 */ 242 public static final String EXTRA_NETWORK_INFO = "networkInfo"; 243 /** 244 * The lookup key for a String giving the BSSID of the access point to which 245 * we are connected. Only present when the new state is CONNECTED. 246 * Retrieve with 247 * {@link android.content.Intent#getStringExtra(String)}. 248 */ 249 public static final String EXTRA_BSSID = "bssid"; 250 /** 251 * Broadcast intent action indicating that the state of establishing a connection to 252 * an access point has changed.One extra provides the new 253 * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and 254 * is not generally the most useful thing to look at if you are just interested in 255 * the overall state of connectivity. 256 * @see #EXTRA_NEW_STATE 257 * @see #EXTRA_SUPPLICANT_ERROR 258 */ 259 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 260 public static final String SUPPLICANT_STATE_CHANGED_ACTION = 261 "android.net.wifi.supplicant.STATE_CHANGE"; 262 /** 263 * The lookup key for a {@link SupplicantState} describing the new state 264 * Retrieve with 265 * {@link android.content.Intent#getParcelableExtra(String)}. 266 */ 267 public static final String EXTRA_NEW_STATE = "newState"; 268 269 /** 270 * The lookup key for a {@link SupplicantState} describing the supplicant 271 * error code if any 272 * Retrieve with 273 * {@link android.content.Intent#getIntExtra(String, int)}. 274 * @see #ERROR_AUTHENTICATING 275 */ 276 public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; 277 /** 278 * Broadcast intent action indicating that the supplicant configuration changed. 279 * This can be as a result of adding/updating/deleting a network 280 * @hide 281 */ 282 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 283 public static final String SUPPLICANT_CONFIG_CHANGED_ACTION = 284 "android.net.wifi.supplicant.CONFIG_CHANGE"; 285 /** 286 * An access point scan has completed, and results are available from the supplicant. 287 * Call {@link #getScanResults()} to obtain the results. 288 */ 289 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 290 public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; 291 /** 292 * The RSSI (signal strength) has changed. 293 * @see #EXTRA_NEW_RSSI 294 */ 295 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 296 public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; 297 /** 298 * The lookup key for an {@code int} giving the new RSSI in dBm. 299 */ 300 public static final String EXTRA_NEW_RSSI = "newRssi"; 301 302 /** 303 * Broadcast intent action indicating that the IP configuration 304 * changed on wifi. 305 * @hide 306 */ 307 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 308 public static final String CONFIG_CHANGED_ACTION = "android.net.wifi.CONFIG_CHANGED"; 309 /** 310 * The lookup key for a {@link android.net.NetworkProperties} object associated with the 311 * Wi-Fi network. Retrieve with 312 * {@link android.content.Intent#getParcelableExtra(String)}. 313 * @hide 314 */ 315 public static final String EXTRA_NETWORK_PROPERTIES = "networkProperties"; 316 317 /** 318 * The network IDs of the configured networks could have changed. 319 */ 320 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 321 public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; 322 323 /** 324 * Activity Action: Pick a Wi-Fi network to connect to. 325 * <p>Input: Nothing. 326 * <p>Output: Nothing. 327 */ 328 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 329 public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; 330 331 /** 332 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 333 * and will behave normally, i.e., it will attempt to automatically 334 * establish a connection to a remembered access point that is 335 * within range, and will do periodic scans if there are remembered 336 * access points but none are in range. 337 */ 338 public static final int WIFI_MODE_FULL = 1; 339 /** 340 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 341 * but the only operation that will be supported is initiation of 342 * scans, and the subsequent reporting of scan results. No attempts 343 * will be made to automatically connect to remembered access points, 344 * nor will periodic scans be automatically performed looking for 345 * remembered access points. Scans must be explicitly requested by 346 * an application in this mode. 347 */ 348 public static final int WIFI_MODE_SCAN_ONLY = 2; 349 350 /** Anything worse than or equal to this will show 0 bars. */ 351 private static final int MIN_RSSI = -100; 352 353 /** Anything better than or equal to this will show the max bars. */ 354 private static final int MAX_RSSI = -55; 355 356 IWifiManager mService; 357 Handler mHandler; 358 359 /* Maximum number of active locks we allow. 360 * This limit was added to prevent apps from creating a ridiculous number 361 * of locks and crashing the system by overflowing the global ref table. 362 */ 363 private static final int MAX_ACTIVE_LOCKS = 50; 364 365 /* Number of currently active WifiLocks and MulticastLocks */ 366 private int mActiveLockCount; 367 368 /** 369 * Create a new WifiManager instance. 370 * Applications will almost always want to use 371 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve 372 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. 373 * @param service the Binder interface 374 * @param handler target for messages 375 * @hide - hide this because it takes in a parameter of type IWifiManager, which 376 * is a system private class. 377 */ 378 public WifiManager(IWifiManager service, Handler handler) { 379 mService = service; 380 mHandler = handler; 381 } 382 383 /** 384 * Return a list of all the networks configured in the supplicant. 385 * Not all fields of WifiConfiguration are returned. Only the following 386 * fields are filled in: 387 * <ul> 388 * <li>networkId</li> 389 * <li>SSID</li> 390 * <li>BSSID</li> 391 * <li>priority</li> 392 * <li>allowedProtocols</li> 393 * <li>allowedKeyManagement</li> 394 * <li>allowedAuthAlgorithms</li> 395 * <li>allowedPairwiseCiphers</li> 396 * <li>allowedGroupCiphers</li> 397 * </ul> 398 * @return a list of network configurations in the form of a list 399 * of {@link WifiConfiguration} objects. 400 */ 401 public List<WifiConfiguration> getConfiguredNetworks() { 402 try { 403 return mService.getConfiguredNetworks(); 404 } catch (RemoteException e) { 405 return null; 406 } 407 } 408 409 /** 410 * Add a new network description to the set of configured networks. 411 * The {@code networkId} field of the supplied configuration object 412 * is ignored. 413 * <p/> 414 * The new network will be marked DISABLED by default. To enable it, 415 * called {@link #enableNetwork}. 416 * 417 * @param config the set of variables that describe the configuration, 418 * contained in a {@link WifiConfiguration} object. 419 * @return the ID of the newly created network description. This is used in 420 * other operations to specified the network to be acted upon. 421 * Returns {@code -1} on failure. 422 */ 423 public int addNetwork(WifiConfiguration config) { 424 if (config == null) { 425 return -1; 426 } 427 config.networkId = -1; 428 return addOrUpdateNetwork(config); 429 } 430 431 /** 432 * Update the network description of an existing configured network. 433 * 434 * @param config the set of variables that describe the configuration, 435 * contained in a {@link WifiConfiguration} object. It may 436 * be sparse, so that only the items that are being changed 437 * are non-<code>null</code>. The {@code networkId} field 438 * must be set to the ID of the existing network being updated. 439 * @return Returns the {@code networkId} of the supplied 440 * {@code WifiConfiguration} on success. 441 * <br/> 442 * Returns {@code -1} on failure, including when the {@code networkId} 443 * field of the {@code WifiConfiguration} does not refer to an 444 * existing network. 445 */ 446 public int updateNetwork(WifiConfiguration config) { 447 if (config == null || config.networkId < 0) { 448 return -1; 449 } 450 return addOrUpdateNetwork(config); 451 } 452 453 /** 454 * Internal method for doing the RPC that creates a new network description 455 * or updates an existing one. 456 * 457 * @param config The possibly sparse object containing the variables that 458 * are to set or updated in the network description. 459 * @return the ID of the network on success, {@code -1} on failure. 460 */ 461 private int addOrUpdateNetwork(WifiConfiguration config) { 462 try { 463 return mService.addOrUpdateNetwork(config); 464 } catch (RemoteException e) { 465 return -1; 466 } 467 } 468 469 /** 470 * Remove the specified network from the list of configured networks. 471 * This may result in the asynchronous delivery of state change 472 * events. 473 * @param netId the integer that identifies the network configuration 474 * to the supplicant 475 * @return {@code true} if the operation succeeded 476 */ 477 public boolean removeNetwork(int netId) { 478 try { 479 return mService.removeNetwork(netId); 480 } catch (RemoteException e) { 481 return false; 482 } 483 } 484 485 /** 486 * Allow a previously configured network to be associated with. If 487 * <code>disableOthers</code> is true, then all other configured 488 * networks are disabled, and an attempt to connect to the selected 489 * network is initiated. This may result in the asynchronous delivery 490 * of state change events. 491 * @param netId the ID of the network in the list of configured networks 492 * @param disableOthers if true, disable all other networks. The way to 493 * select a particular network to connect to is specify {@code true} 494 * for this parameter. 495 * @return {@code true} if the operation succeeded 496 */ 497 public boolean enableNetwork(int netId, boolean disableOthers) { 498 try { 499 return mService.enableNetwork(netId, disableOthers); 500 } catch (RemoteException e) { 501 return false; 502 } 503 } 504 505 /** 506 * Disable a configured network. The specified network will not be 507 * a candidate for associating. This may result in the asynchronous 508 * delivery of state change events. 509 * @param netId the ID of the network as returned by {@link #addNetwork}. 510 * @return {@code true} if the operation succeeded 511 */ 512 public boolean disableNetwork(int netId) { 513 try { 514 return mService.disableNetwork(netId); 515 } catch (RemoteException e) { 516 return false; 517 } 518 } 519 520 /** 521 * Disassociate from the currently active access point. This may result 522 * in the asynchronous delivery of state change events. 523 * @return {@code true} if the operation succeeded 524 */ 525 public boolean disconnect() { 526 try { 527 mService.disconnect(); 528 return true; 529 } catch (RemoteException e) { 530 return false; 531 } 532 } 533 534 /** 535 * Reconnect to the currently active access point, if we are currently 536 * disconnected. This may result in the asynchronous delivery of state 537 * change events. 538 * @return {@code true} if the operation succeeded 539 */ 540 public boolean reconnect() { 541 try { 542 mService.reconnect(); 543 return true; 544 } catch (RemoteException e) { 545 return false; 546 } 547 } 548 549 /** 550 * Reconnect to the currently active access point, even if we are already 551 * connected. This may result in the asynchronous delivery of state 552 * change events. 553 * @return {@code true} if the operation succeeded 554 */ 555 public boolean reassociate() { 556 try { 557 mService.reassociate(); 558 return true; 559 } catch (RemoteException e) { 560 return false; 561 } 562 } 563 564 /** 565 * Check that the supplicant daemon is responding to requests. 566 * @return {@code true} if we were able to communicate with the supplicant and 567 * it returned the expected response to the PING message. 568 */ 569 public boolean pingSupplicant() { 570 if (mService == null) 571 return false; 572 try { 573 return mService.pingSupplicant(); 574 } catch (RemoteException e) { 575 return false; 576 } 577 } 578 579 /** 580 * Request a scan for access points. Returns immediately. The availability 581 * of the results is made known later by means of an asynchronous event sent 582 * on completion of the scan. 583 * @return {@code true} if the operation succeeded, i.e., the scan was initiated 584 */ 585 public boolean startScan() { 586 try { 587 mService.startScan(false); 588 return true; 589 } catch (RemoteException e) { 590 return false; 591 } 592 } 593 594 /** 595 * Request a scan for access points. Returns immediately. The availability 596 * of the results is made known later by means of an asynchronous event sent 597 * on completion of the scan. 598 * This is a variant of startScan that forces an active scan, even if passive 599 * scans are the current default 600 * @return {@code true} if the operation succeeded, i.e., the scan was initiated 601 * 602 * @hide 603 */ 604 public boolean startScanActive() { 605 try { 606 mService.startScan(true); 607 return true; 608 } catch (RemoteException e) { 609 return false; 610 } 611 } 612 613 /** 614 * Return dynamic information about the current Wi-Fi connection, if any is active. 615 * @return the Wi-Fi information, contained in {@link WifiInfo}. 616 */ 617 public WifiInfo getConnectionInfo() { 618 try { 619 return mService.getConnectionInfo(); 620 } catch (RemoteException e) { 621 return null; 622 } 623 } 624 625 /** 626 * Return the results of the latest access point scan. 627 * @return the list of access points found in the most recent scan. 628 */ 629 public List<ScanResult> getScanResults() { 630 try { 631 return mService.getScanResults(); 632 } catch (RemoteException e) { 633 return null; 634 } 635 } 636 637 /** 638 * Tell the supplicant to persist the current list of configured networks. 639 * <p> 640 * Note: It is possible for this method to change the network IDs of 641 * existing networks. You should assume the network IDs can be different 642 * after calling this method. 643 * 644 * @return {@code true} if the operation succeeded 645 */ 646 public boolean saveConfiguration() { 647 try { 648 return mService.saveConfiguration(); 649 } catch (RemoteException e) { 650 return false; 651 } 652 } 653 654 /** 655 * Return the number of frequency channels that are allowed 656 * to be used in the current regulatory domain. 657 * @return the number of allowed channels, or {@code -1} if an error occurs 658 * 659 * @hide pending API council 660 */ 661 public int getNumAllowedChannels() { 662 try { 663 return mService.getNumAllowedChannels(); 664 } catch (RemoteException e) { 665 return -1; 666 } 667 } 668 669 /** 670 * Set the number of frequency channels that are allowed to be used 671 * in the current regulatory domain. This method should be used only 672 * if the correct number of channels cannot be determined automatically 673 * for some reason. 674 * @param numChannels the number of allowed channels. Must be greater than 0 675 * and less than or equal to 16. 676 * @param persist {@code true} if you want this remembered 677 * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g., 678 * {@code numChannels} is out of range. 679 * 680 * @hide pending API council 681 */ 682 public boolean setNumAllowedChannels(int numChannels, boolean persist) { 683 try { 684 return mService.setNumAllowedChannels(numChannels, persist); 685 } catch (RemoteException e) { 686 return false; 687 } 688 } 689 690 /** 691 * Return the list of valid values for the number of allowed radio channels 692 * for various regulatory domains. 693 * @return the list of channel counts, or {@code null} if the operation fails 694 * 695 * @hide pending API council review 696 */ 697 public int[] getValidChannelCounts() { 698 try { 699 return mService.getValidChannelCounts(); 700 } catch (RemoteException e) { 701 return null; 702 } 703 } 704 705 /** 706 * Return the DHCP-assigned addresses from the last successful DHCP request, 707 * if any. 708 * @return the DHCP information 709 */ 710 public DhcpInfo getDhcpInfo() { 711 try { 712 return mService.getDhcpInfo(); 713 } catch (RemoteException e) { 714 return null; 715 } 716 } 717 718 719 /** 720 * Enable or disable Wi-Fi. 721 * @param enabled {@code true} to enable, {@code false} to disable. 722 * @return {@code true} if the operation succeeds (or if the existing state 723 * is the same as the requested state). 724 */ 725 public boolean setWifiEnabled(boolean enabled) { 726 try { 727 return mService.setWifiEnabled(enabled); 728 } catch (RemoteException e) { 729 return false; 730 } 731 } 732 733 /** 734 * Gets the Wi-Fi enabled state. 735 * @return One of {@link #WIFI_STATE_DISABLED}, 736 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 737 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 738 * @see #isWifiEnabled() 739 */ 740 public int getWifiState() { 741 try { 742 return mService.getWifiEnabledState(); 743 } catch (RemoteException e) { 744 return WIFI_STATE_UNKNOWN; 745 } 746 } 747 748 /** 749 * Return whether Wi-Fi is enabled or disabled. 750 * @return {@code true} if Wi-Fi is enabled 751 * @see #getWifiState() 752 */ 753 public boolean isWifiEnabled() { 754 return getWifiState() == WIFI_STATE_ENABLED; 755 } 756 757 /** 758 * Calculates the level of the signal. This should be used any time a signal 759 * is being shown. 760 * 761 * @param rssi The power of the signal measured in RSSI. 762 * @param numLevels The number of levels to consider in the calculated 763 * level. 764 * @return A level of the signal, given in the range of 0 to numLevels-1 765 * (both inclusive). 766 */ 767 public static int calculateSignalLevel(int rssi, int numLevels) { 768 if (rssi <= MIN_RSSI) { 769 return 0; 770 } else if (rssi >= MAX_RSSI) { 771 return numLevels - 1; 772 } else { 773 float inputRange = (MAX_RSSI - MIN_RSSI); 774 float outputRange = (numLevels - 1); 775 return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange); 776 } 777 } 778 779 /** 780 * Compares two signal strengths. 781 * 782 * @param rssiA The power of the first signal measured in RSSI. 783 * @param rssiB The power of the second signal measured in RSSI. 784 * @return Returns <0 if the first signal is weaker than the second signal, 785 * 0 if the two signals have the same strength, and >0 if the first 786 * signal is stronger than the second signal. 787 */ 788 public static int compareSignalLevel(int rssiA, int rssiB) { 789 return rssiA - rssiB; 790 } 791 792 /** 793 * Start AccessPoint mode with the specified 794 * configuration. If the radio is already running in 795 * AP mode, update the new configuration 796 * Note that starting in access point mode disables station 797 * mode operation 798 * @param wifiConfig SSID, security and channel details as 799 * part of WifiConfiguration 800 * @return {@code true} if the operation succeeds, {@code false} otherwise 801 * 802 * @hide Dont open up yet 803 */ 804 public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { 805 try { 806 return mService.setWifiApEnabled(wifiConfig, enabled); 807 } catch (RemoteException e) { 808 return false; 809 } 810 } 811 812 /** 813 * Gets the Wi-Fi enabled state. 814 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 815 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 816 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 817 * @see #isWifiApEnabled() 818 * 819 * @hide Dont open yet 820 */ 821 public int getWifiApState() { 822 try { 823 return mService.getWifiApEnabledState(); 824 } catch (RemoteException e) { 825 return WIFI_AP_STATE_FAILED; 826 } 827 } 828 829 /** 830 * Return whether Wi-Fi AP is enabled or disabled. 831 * @return {@code true} if Wi-Fi AP is enabled 832 * @see #getWifiApState() 833 * 834 * @hide Dont open yet 835 */ 836 public boolean isWifiApEnabled() { 837 return getWifiApState() == WIFI_AP_STATE_ENABLED; 838 } 839 840 /** 841 * Gets the Wi-Fi AP Configuration. 842 * @return AP details in WifiConfiguration 843 * 844 * @hide Dont open yet 845 */ 846 public WifiConfiguration getWifiApConfiguration() { 847 try { 848 return mService.getWifiApConfiguration(); 849 } catch (RemoteException e) { 850 return null; 851 } 852 } 853 854 /** 855 * Sets the Wi-Fi AP Configuration. 856 * @return {@code true} if the operation succeeded, {@code false} otherwise 857 * 858 * @hide Dont open yet 859 */ 860 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { 861 try { 862 mService.setWifiApConfiguration(wifiConfig); 863 return true; 864 } catch (RemoteException e) { 865 return false; 866 } 867 } 868 869 /** 870 * Start the driver and connect to network. 871 * 872 * This function will over-ride WifiLock and device idle status. For example, 873 * even if the device is idle or there is only a scan-only lock held, 874 * a start wifi would mean that wifi connection is kept active until 875 * a stopWifi() is sent. 876 * 877 * This API is used by WifiStateTracker 878 * 879 * @return {@code true} if the operation succeeds else {@code false} 880 * @hide 881 */ 882 public boolean startWifi() { 883 try { 884 mService.startWifi(); 885 return true; 886 } catch (RemoteException e) { 887 return false; 888 } 889 } 890 891 /** 892 * Disconnect from a network (if any) and stop the driver. 893 * 894 * This function will over-ride WifiLock and device idle status. Wi-Fi 895 * stays inactive until a startWifi() is issued. 896 * 897 * This API is used by WifiStateTracker 898 * 899 * @return {@code true} if the operation succeeds else {@code false} 900 * @hide 901 */ 902 public boolean stopWifi() { 903 try { 904 mService.stopWifi(); 905 return true; 906 } catch (RemoteException e) { 907 return false; 908 } 909 } 910 911 /** 912 * Add a bssid to the supplicant blacklist 913 * 914 * This API is used by WifiWatchdogService 915 * 916 * @return {@code true} if the operation succeeds else {@code false} 917 * @hide 918 */ 919 public boolean addToBlacklist(String bssid) { 920 try { 921 mService.addToBlacklist(bssid); 922 return true; 923 } catch (RemoteException e) { 924 return false; 925 } 926 } 927 928 /** 929 * Clear the supplicant blacklist 930 * 931 * This API is used by WifiWatchdogService 932 * 933 * @return {@code true} if the operation succeeds else {@code false} 934 * @hide 935 */ 936 public boolean clearBlacklist() { 937 try { 938 mService.clearBlacklist(); 939 return true; 940 } catch (RemoteException e) { 941 return false; 942 } 943 } 944 945 /* TODO: deprecate synchronous API and open up the following API */ 946 /** 947 * Connect to a network with the given configuration. The network also 948 * gets added to the supplicant configuration. 949 * 950 * For a new network, this function is used instead of a 951 * sequence of addNetwork(), enableNetwork(), saveConfiguration() and 952 * reconnect() 953 * 954 * @param config the set of variables that describe the configuration, 955 * contained in a {@link WifiConfiguration} object. 956 * @hide 957 */ 958 public void connectNetwork(WifiConfiguration config) { 959 if (config == null) { 960 return; 961 } 962 try { 963 mService.connectNetworkWithConfig(config); 964 } catch (RemoteException e) { } 965 } 966 967 /** 968 * Connect to a network with the given networkId. 969 * 970 * This function is used instead of a enableNetwork(), saveConfiguration() and 971 * reconnect() 972 * 973 * @param networkId the network id identifiying the network in the 974 * supplicant configuration list 975 * @hide 976 */ 977 public void connectNetwork(int networkId) { 978 if (networkId < 0) { 979 return; 980 } 981 try { 982 mService.connectNetworkWithId(networkId); 983 } catch (RemoteException e) { } 984 } 985 986 /** 987 * Save the given network in the supplicant config. If the network already 988 * exists, the configuration is updated. A new network is enabled 989 * by default. 990 * 991 * For a new network, this function is used instead of a 992 * sequence of addNetwork(), enableNetwork() and saveConfiguration(). 993 * 994 * For an existing network, it accomplishes the task of updateNetwork() 995 * and saveConfiguration() 996 * 997 * @param config the set of variables that describe the configuration, 998 * contained in a {@link WifiConfiguration} object. 999 * @hide 1000 */ 1001 public void saveNetwork(WifiConfiguration config) { 1002 if (config == null) { 1003 return; 1004 } 1005 try { 1006 mService.saveNetwork(config); 1007 } catch (RemoteException e) { } 1008 } 1009 1010 /** 1011 * Delete the network in the supplicant config. 1012 * 1013 * This function is used instead of a sequence of removeNetwork() 1014 * and saveConfiguration(). 1015 * 1016 * @param config the set of variables that describe the configuration, 1017 * contained in a {@link WifiConfiguration} object. 1018 * @hide 1019 */ 1020 public void forgetNetwork(int netId) { 1021 if (netId < 0) { 1022 return; 1023 } 1024 try { 1025 mService.forgetNetwork(netId); 1026 } catch (RemoteException e) { } 1027 } 1028 1029 /** 1030 * Allows an application to keep the Wi-Fi radio awake. 1031 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 1032 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 1033 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 1034 * WifiLocks are held in any application. 1035 * 1036 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 1037 * could function over a mobile network, if available. A program that needs to download large 1038 * files should hold a WifiLock to ensure that the download will complete, but a program whose 1039 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 1040 * affecting battery life. 1041 * 1042 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 1043 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 1044 * is idle. 1045 */ 1046 public class WifiLock { 1047 private String mTag; 1048 private final IBinder mBinder; 1049 private int mRefCount; 1050 int mLockType; 1051 private boolean mRefCounted; 1052 private boolean mHeld; 1053 1054 private WifiLock(int lockType, String tag) { 1055 mTag = tag; 1056 mLockType = lockType; 1057 mBinder = new Binder(); 1058 mRefCount = 0; 1059 mRefCounted = true; 1060 mHeld = false; 1061 } 1062 1063 /** 1064 * Locks the Wi-Fi radio on until {@link #release} is called. 1065 * 1066 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 1067 * reference count, and the radio will remain locked as long as the reference count is 1068 * above zero. 1069 * 1070 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 1071 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 1072 * will be required, regardless of the number of times that {@code acquire} is called. 1073 */ 1074 public void acquire() { 1075 synchronized (mBinder) { 1076 if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) { 1077 try { 1078 mService.acquireWifiLock(mBinder, mLockType, mTag); 1079 synchronized (WifiManager.this) { 1080 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 1081 mService.releaseWifiLock(mBinder); 1082 throw new UnsupportedOperationException( 1083 "Exceeded maximum number of wifi locks"); 1084 } 1085 mActiveLockCount++; 1086 } 1087 } catch (RemoteException ignore) { 1088 } 1089 mHeld = true; 1090 } 1091 } 1092 } 1093 1094 /** 1095 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 1096 * 1097 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 1098 * reference count, and the radio will be unlocked only when the reference count reaches 1099 * zero. If the reference count goes below zero (that is, if {@code release} is called 1100 * a greater number of times than {@link #acquire}), an exception is thrown. 1101 * 1102 * If this WifiLock is not reference-counted, the first call to {@code release} (after 1103 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 1104 * calls will be ignored. 1105 */ 1106 public void release() { 1107 synchronized (mBinder) { 1108 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 1109 try { 1110 mService.releaseWifiLock(mBinder); 1111 synchronized (WifiManager.this) { 1112 mActiveLockCount--; 1113 } 1114 } catch (RemoteException ignore) { 1115 } 1116 mHeld = false; 1117 } 1118 if (mRefCount < 0) { 1119 throw new RuntimeException("WifiLock under-locked " + mTag); 1120 } 1121 } 1122 } 1123 1124 /** 1125 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 1126 * 1127 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 1128 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 1129 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 1130 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 1131 * radio whenever {@link #release} is called and it is locked. 1132 * 1133 * @param refCounted true if this WifiLock should keep a reference count 1134 */ 1135 public void setReferenceCounted(boolean refCounted) { 1136 mRefCounted = refCounted; 1137 } 1138 1139 /** 1140 * Checks whether this WifiLock is currently held. 1141 * 1142 * @return true if this WifiLock is held, false otherwise 1143 */ 1144 public boolean isHeld() { 1145 synchronized (mBinder) { 1146 return mHeld; 1147 } 1148 } 1149 1150 public String toString() { 1151 String s1, s2, s3; 1152 synchronized (mBinder) { 1153 s1 = Integer.toHexString(System.identityHashCode(this)); 1154 s2 = mHeld ? "held; " : ""; 1155 if (mRefCounted) { 1156 s3 = "refcounted: refcount = " + mRefCount; 1157 } else { 1158 s3 = "not refcounted"; 1159 } 1160 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 1161 } 1162 } 1163 1164 @Override 1165 protected void finalize() throws Throwable { 1166 super.finalize(); 1167 synchronized (mBinder) { 1168 if (mHeld) { 1169 try { 1170 mService.releaseWifiLock(mBinder); 1171 synchronized (WifiManager.this) { 1172 mActiveLockCount--; 1173 } 1174 } catch (RemoteException ignore) { 1175 } 1176 } 1177 } 1178 } 1179 } 1180 1181 /** 1182 * Creates a new WifiLock. 1183 * 1184 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL} and 1185 * {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks. 1186 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 1187 * never shown to the user under normal conditions, but should be descriptive 1188 * enough to identify your application and the specific WifiLock within it, if it 1189 * holds multiple WifiLocks. 1190 * 1191 * @return a new, unacquired WifiLock with the given tag. 1192 * 1193 * @see WifiLock 1194 */ 1195 public WifiLock createWifiLock(int lockType, String tag) { 1196 return new WifiLock(lockType, tag); 1197 } 1198 1199 /** 1200 * Creates a new WifiLock. 1201 * 1202 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 1203 * never shown to the user under normal conditions, but should be descriptive 1204 * enough to identify your application and the specific WifiLock within it, if it 1205 * holds multiple WifiLocks. 1206 * 1207 * @return a new, unacquired WifiLock with the given tag. 1208 * 1209 * @see WifiLock 1210 */ 1211 public WifiLock createWifiLock(String tag) { 1212 return new WifiLock(WIFI_MODE_FULL, tag); 1213 } 1214 1215 1216 /** 1217 * Create a new MulticastLock 1218 * 1219 * @param tag a tag for the MulticastLock to identify it in debugging 1220 * messages. This string is never shown to the user under 1221 * normal conditions, but should be descriptive enough to 1222 * identify your application and the specific MulticastLock 1223 * within it, if it holds multiple MulticastLocks. 1224 * 1225 * @return a new, unacquired MulticastLock with the given tag. 1226 * 1227 * @see MulticastLock 1228 */ 1229 public MulticastLock createMulticastLock(String tag) { 1230 return new MulticastLock(tag); 1231 } 1232 1233 /** 1234 * Allows an application to receive Wifi Multicast packets. 1235 * Normally the Wifi stack filters out packets not explicitly 1236 * addressed to this device. Acquring a MulticastLock will 1237 * cause the stack to receive packets addressed to multicast 1238 * addresses. Processing these extra packets can cause a noticable 1239 * battery drain and should be disabled when not needed. 1240 */ 1241 public class MulticastLock { 1242 private String mTag; 1243 private final IBinder mBinder; 1244 private int mRefCount; 1245 private boolean mRefCounted; 1246 private boolean mHeld; 1247 1248 private MulticastLock(String tag) { 1249 mTag = tag; 1250 mBinder = new Binder(); 1251 mRefCount = 0; 1252 mRefCounted = true; 1253 mHeld = false; 1254 } 1255 1256 /** 1257 * Locks Wifi Multicast on until {@link #release} is called. 1258 * 1259 * If this MulticastLock is reference-counted each call to 1260 * {@code acquire} will increment the reference count, and the 1261 * wifi interface will receive multicast packets as long as the 1262 * reference count is above zero. 1263 * 1264 * If this MulticastLock is not reference-counted, the first call to 1265 * {@code acquire} will turn on the multicast packets, but subsequent 1266 * calls will be ignored. Only one call to {@link #release} will 1267 * be required, regardless of the number of times that {@code acquire} 1268 * is called. 1269 * 1270 * Note that other applications may also lock Wifi Multicast on. 1271 * Only they can relinquish their lock. 1272 * 1273 * Also note that applications cannot leave Multicast locked on. 1274 * When an app exits or crashes, any Multicast locks will be released. 1275 */ 1276 public void acquire() { 1277 synchronized (mBinder) { 1278 if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) { 1279 try { 1280 mService.acquireMulticastLock(mBinder, mTag); 1281 synchronized (WifiManager.this) { 1282 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 1283 mService.releaseMulticastLock(); 1284 throw new UnsupportedOperationException( 1285 "Exceeded maximum number of wifi locks"); 1286 } 1287 mActiveLockCount++; 1288 } 1289 } catch (RemoteException ignore) { 1290 } 1291 mHeld = true; 1292 } 1293 } 1294 } 1295 1296 /** 1297 * Unlocks Wifi Multicast, restoring the filter of packets 1298 * not addressed specifically to this device and saving power. 1299 * 1300 * If this MulticastLock is reference-counted, each call to 1301 * {@code release} will decrement the reference count, and the 1302 * multicast packets will only stop being received when the reference 1303 * count reaches zero. If the reference count goes below zero (that 1304 * is, if {@code release} is called a greater number of times than 1305 * {@link #acquire}), an exception is thrown. 1306 * 1307 * If this MulticastLock is not reference-counted, the first call to 1308 * {@code release} (after the radio was multicast locked using 1309 * {@link #acquire}) will unlock the multicast, and subsequent calls 1310 * will be ignored. 1311 * 1312 * Note that if any other Wifi Multicast Locks are still outstanding 1313 * this {@code release} call will not have an immediate effect. Only 1314 * when all applications have released all their Multicast Locks will 1315 * the Multicast filter be turned back on. 1316 * 1317 * Also note that when an app exits or crashes all of its Multicast 1318 * Locks will be automatically released. 1319 */ 1320 public void release() { 1321 synchronized (mBinder) { 1322 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 1323 try { 1324 mService.releaseMulticastLock(); 1325 synchronized (WifiManager.this) { 1326 mActiveLockCount--; 1327 } 1328 } catch (RemoteException ignore) { 1329 } 1330 mHeld = false; 1331 } 1332 if (mRefCount < 0) { 1333 throw new RuntimeException("MulticastLock under-locked " 1334 + mTag); 1335 } 1336 } 1337 } 1338 1339 /** 1340 * Controls whether this is a reference-counted or non-reference- 1341 * counted MulticastLock. 1342 * 1343 * Reference-counted MulticastLocks keep track of the number of calls 1344 * to {@link #acquire} and {@link #release}, and only stop the 1345 * reception of multicast packets when every call to {@link #acquire} 1346 * has been balanced with a call to {@link #release}. Non-reference- 1347 * counted MulticastLocks allow the reception of multicast packets 1348 * whenever {@link #acquire} is called and stop accepting multicast 1349 * packets whenever {@link #release} is called. 1350 * 1351 * @param refCounted true if this MulticastLock should keep a reference 1352 * count 1353 */ 1354 public void setReferenceCounted(boolean refCounted) { 1355 mRefCounted = refCounted; 1356 } 1357 1358 /** 1359 * Checks whether this MulticastLock is currently held. 1360 * 1361 * @return true if this MulticastLock is held, false otherwise 1362 */ 1363 public boolean isHeld() { 1364 synchronized (mBinder) { 1365 return mHeld; 1366 } 1367 } 1368 1369 public String toString() { 1370 String s1, s2, s3; 1371 synchronized (mBinder) { 1372 s1 = Integer.toHexString(System.identityHashCode(this)); 1373 s2 = mHeld ? "held; " : ""; 1374 if (mRefCounted) { 1375 s3 = "refcounted: refcount = " + mRefCount; 1376 } else { 1377 s3 = "not refcounted"; 1378 } 1379 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 1380 } 1381 } 1382 1383 @Override 1384 protected void finalize() throws Throwable { 1385 super.finalize(); 1386 setReferenceCounted(false); 1387 release(); 1388 } 1389 } 1390 1391 /** 1392 * Check multicast filter status. 1393 * 1394 * @return true if multicast packets are allowed. 1395 * 1396 * @hide pending API council approval 1397 */ 1398 public boolean isMulticastEnabled() { 1399 try { 1400 return mService.isMulticastEnabled(); 1401 } catch (RemoteException e) { 1402 return false; 1403 } 1404 } 1405 1406 /** 1407 * Initialize the multicast filtering to 'on' 1408 * @hide no intent to publish 1409 */ 1410 public boolean initializeMulticastFiltering() { 1411 try { 1412 mService.initializeMulticastFiltering(); 1413 return true; 1414 } catch (RemoteException e) { 1415 return false; 1416 } 1417 } 1418} 1419