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 = 0; 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 = 1; 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 = 2; 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 = 3; 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 = 4; 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 /** 279 * An access point scan has completed, and results are available from the supplicant. 280 * Call {@link #getScanResults()} to obtain the results. 281 */ 282 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 283 public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; 284 /** 285 * The RSSI (signal strength) has changed. 286 * @see #EXTRA_NEW_RSSI 287 */ 288 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 289 public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; 290 /** 291 * The lookup key for an {@code int} giving the new RSSI in dBm. 292 */ 293 public static final String EXTRA_NEW_RSSI = "newRssi"; 294 295 /** 296 * The network IDs of the configured networks could have changed. 297 */ 298 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 299 public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; 300 301 /** 302 * Activity Action: Pick a Wi-Fi network to connect to. 303 * <p>Input: Nothing. 304 * <p>Output: Nothing. 305 */ 306 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 307 public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; 308 309 /** 310 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 311 * and will behave normally, i.e., it will attempt to automatically 312 * establish a connection to a remembered access point that is 313 * within range, and will do periodic scans if there are remembered 314 * access points but none are in range. 315 */ 316 public static final int WIFI_MODE_FULL = 1; 317 /** 318 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 319 * but the only operation that will be supported is initiation of 320 * scans, and the subsequent reporting of scan results. No attempts 321 * will be made to automatically connect to remembered access points, 322 * nor will periodic scans be automatically performed looking for 323 * remembered access points. Scans must be explicitly requested by 324 * an application in this mode. 325 */ 326 public static final int WIFI_MODE_SCAN_ONLY = 2; 327 328 /** Anything worse than or equal to this will show 0 bars. */ 329 private static final int MIN_RSSI = -100; 330 331 /** Anything better than or equal to this will show the max bars. */ 332 private static final int MAX_RSSI = -55; 333 334 IWifiManager mService; 335 Handler mHandler; 336 337 /* Maximum number of active locks we allow. 338 * This limit was added to prevent apps from creating a ridiculous number 339 * of locks and crashing the system by overflowing the global ref table. 340 */ 341 private static final int MAX_ACTIVE_LOCKS = 50; 342 343 /* Number of currently active WifiLocks and MulticastLocks */ 344 private int mActiveLockCount; 345 346 /** 347 * Create a new WifiManager instance. 348 * Applications will almost always want to use 349 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve 350 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. 351 * @param service the Binder interface 352 * @param handler target for messages 353 * @hide - hide this because it takes in a parameter of type IWifiManager, which 354 * is a system private class. 355 */ 356 public WifiManager(IWifiManager service, Handler handler) { 357 mService = service; 358 mHandler = handler; 359 } 360 361 /** 362 * Return a list of all the networks configured in the supplicant. 363 * Not all fields of WifiConfiguration are returned. Only the following 364 * fields are filled in: 365 * <ul> 366 * <li>networkId</li> 367 * <li>SSID</li> 368 * <li>BSSID</li> 369 * <li>priority</li> 370 * <li>allowedProtocols</li> 371 * <li>allowedKeyManagement</li> 372 * <li>allowedAuthAlgorithms</li> 373 * <li>allowedPairwiseCiphers</li> 374 * <li>allowedGroupCiphers</li> 375 * </ul> 376 * @return a list of network configurations in the form of a list 377 * of {@link WifiConfiguration} objects. 378 */ 379 public List<WifiConfiguration> getConfiguredNetworks() { 380 try { 381 return mService.getConfiguredNetworks(); 382 } catch (RemoteException e) { 383 return null; 384 } 385 } 386 387 /** 388 * Add a new network description to the set of configured networks. 389 * The {@code networkId} field of the supplied configuration object 390 * is ignored. 391 * <p/> 392 * The new network will be marked DISABLED by default. To enable it, 393 * called {@link #enableNetwork}. 394 * 395 * @param config the set of variables that describe the configuration, 396 * contained in a {@link WifiConfiguration} object. 397 * @return the ID of the newly created network description. This is used in 398 * other operations to specified the network to be acted upon. 399 * Returns {@code -1} on failure. 400 */ 401 public int addNetwork(WifiConfiguration config) { 402 if (config == null) { 403 return -1; 404 } 405 config.networkId = -1; 406 return addOrUpdateNetwork(config); 407 } 408 409 /** 410 * Update the network description of an existing configured network. 411 * 412 * @param config the set of variables that describe the configuration, 413 * contained in a {@link WifiConfiguration} object. It may 414 * be sparse, so that only the items that are being changed 415 * are non-<code>null</code>. The {@code networkId} field 416 * must be set to the ID of the existing network being updated. 417 * @return Returns the {@code networkId} of the supplied 418 * {@code WifiConfiguration} on success. 419 * <br/> 420 * Returns {@code -1} on failure, including when the {@code networkId} 421 * field of the {@code WifiConfiguration} does not refer to an 422 * existing network. 423 */ 424 public int updateNetwork(WifiConfiguration config) { 425 if (config == null || config.networkId < 0) { 426 return -1; 427 } 428 return addOrUpdateNetwork(config); 429 } 430 431 /** 432 * Internal method for doing the RPC that creates a new network description 433 * or updates an existing one. 434 * 435 * @param config The possibly sparse object containing the variables that 436 * are to set or updated in the network description. 437 * @return the ID of the network on success, {@code -1} on failure. 438 */ 439 private int addOrUpdateNetwork(WifiConfiguration config) { 440 try { 441 return mService.addOrUpdateNetwork(config); 442 } catch (RemoteException e) { 443 return -1; 444 } 445 } 446 447 /** 448 * Remove the specified network from the list of configured networks. 449 * This may result in the asynchronous delivery of state change 450 * events. 451 * @param netId the integer that identifies the network configuration 452 * to the supplicant 453 * @return {@code true} if the operation succeeded 454 */ 455 public boolean removeNetwork(int netId) { 456 try { 457 return mService.removeNetwork(netId); 458 } catch (RemoteException e) { 459 return false; 460 } 461 } 462 463 /** 464 * Allow a previously configured network to be associated with. If 465 * <code>disableOthers</code> is true, then all other configured 466 * networks are disabled, and an attempt to connect to the selected 467 * network is initiated. This may result in the asynchronous delivery 468 * of state change events. 469 * @param netId the ID of the network in the list of configured networks 470 * @param disableOthers if true, disable all other networks. The way to 471 * select a particular network to connect to is specify {@code true} 472 * for this parameter. 473 * @return {@code true} if the operation succeeded 474 */ 475 public boolean enableNetwork(int netId, boolean disableOthers) { 476 try { 477 return mService.enableNetwork(netId, disableOthers); 478 } catch (RemoteException e) { 479 return false; 480 } 481 } 482 483 /** 484 * Disable a configured network. The specified network will not be 485 * a candidate for associating. This may result in the asynchronous 486 * delivery of state change events. 487 * @param netId the ID of the network as returned by {@link #addNetwork}. 488 * @return {@code true} if the operation succeeded 489 */ 490 public boolean disableNetwork(int netId) { 491 try { 492 return mService.disableNetwork(netId); 493 } catch (RemoteException e) { 494 return false; 495 } 496 } 497 498 /** 499 * Disassociate from the currently active access point. This may result 500 * in the asynchronous delivery of state change events. 501 * @return {@code true} if the operation succeeded 502 */ 503 public boolean disconnect() { 504 try { 505 return mService.disconnect(); 506 } catch (RemoteException e) { 507 return false; 508 } 509 } 510 511 /** 512 * Reconnect to the currently active access point, if we are currently 513 * disconnected. This may result in the asynchronous delivery of state 514 * change events. 515 * @return {@code true} if the operation succeeded 516 */ 517 public boolean reconnect() { 518 try { 519 return mService.reconnect(); 520 } catch (RemoteException e) { 521 return false; 522 } 523 } 524 525 /** 526 * Reconnect to the currently active access point, even if we are already 527 * connected. This may result in the asynchronous delivery of state 528 * change events. 529 * @return {@code true} if the operation succeeded 530 */ 531 public boolean reassociate() { 532 try { 533 return mService.reassociate(); 534 } catch (RemoteException e) { 535 return false; 536 } 537 } 538 539 /** 540 * Check that the supplicant daemon is responding to requests. 541 * @return {@code true} if we were able to communicate with the supplicant and 542 * it returned the expected response to the PING message. 543 */ 544 public boolean pingSupplicant() { 545 if (mService == null) 546 return false; 547 try { 548 return mService.pingSupplicant(); 549 } catch (RemoteException e) { 550 return false; 551 } 552 } 553 554 /** 555 * Request a scan for access points. Returns immediately. The availability 556 * of the results is made known later by means of an asynchronous event sent 557 * on completion of the scan. 558 * @return {@code true} if the operation succeeded, i.e., the scan was initiated 559 */ 560 public boolean startScan() { 561 try { 562 return mService.startScan(false); 563 } catch (RemoteException e) { 564 return false; 565 } 566 } 567 568 /** 569 * Request a scan for access points. Returns immediately. The availability 570 * of the results is made known later by means of an asynchronous event sent 571 * on completion of the scan. 572 * This is a variant of startScan that forces an active scan, even if passive 573 * scans are the current default 574 * @return {@code true} if the operation succeeded, i.e., the scan was initiated 575 * 576 * @hide 577 */ 578 public boolean startScanActive() { 579 try { 580 return mService.startScan(true); 581 } catch (RemoteException e) { 582 return false; 583 } 584 } 585 586 /** 587 * Return dynamic information about the current Wi-Fi connection, if any is active. 588 * @return the Wi-Fi information, contained in {@link WifiInfo}. 589 */ 590 public WifiInfo getConnectionInfo() { 591 try { 592 return mService.getConnectionInfo(); 593 } catch (RemoteException e) { 594 return null; 595 } 596 } 597 598 /** 599 * Return the results of the latest access point scan. 600 * @return the list of access points found in the most recent scan. 601 */ 602 public List<ScanResult> getScanResults() { 603 try { 604 return mService.getScanResults(); 605 } catch (RemoteException e) { 606 return null; 607 } 608 } 609 610 /** 611 * Tell the supplicant to persist the current list of configured networks. 612 * <p> 613 * Note: It is possible for this method to change the network IDs of 614 * existing networks. You should assume the network IDs can be different 615 * after calling this method. 616 * 617 * @return {@code true} if the operation succeeded 618 */ 619 public boolean saveConfiguration() { 620 try { 621 return mService.saveConfiguration(); 622 } catch (RemoteException e) { 623 return false; 624 } 625 } 626 627 /** 628 * Return the number of frequency channels that are allowed 629 * to be used in the current regulatory domain. 630 * @return the number of allowed channels, or {@code -1} if an error occurs 631 * 632 * @hide pending API council 633 */ 634 public int getNumAllowedChannels() { 635 try { 636 return mService.getNumAllowedChannels(); 637 } catch (RemoteException e) { 638 return -1; 639 } 640 } 641 642 /** 643 * Set the number of frequency channels that are allowed to be used 644 * in the current regulatory domain. This method should be used only 645 * if the correct number of channels cannot be determined automatically 646 * for some reason. 647 * @param numChannels the number of allowed channels. Must be greater than 0 648 * and less than or equal to 16. 649 * @param persist {@code true} if you want this remembered 650 * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g., 651 * {@code numChannels} is out of range. 652 * 653 * @hide pending API council 654 */ 655 public boolean setNumAllowedChannels(int numChannels, boolean persist) { 656 try { 657 return mService.setNumAllowedChannels(numChannels, persist); 658 } catch (RemoteException e) { 659 return false; 660 } 661 } 662 663 /** 664 * Return the list of valid values for the number of allowed radio channels 665 * for various regulatory domains. 666 * @return the list of channel counts, or {@code null} if the operation fails 667 * 668 * @hide pending API council review 669 */ 670 public int[] getValidChannelCounts() { 671 try { 672 return mService.getValidChannelCounts(); 673 } catch (RemoteException e) { 674 return null; 675 } 676 } 677 678 /** 679 * Return the DHCP-assigned addresses from the last successful DHCP request, 680 * if any. 681 * @return the DHCP information 682 */ 683 public DhcpInfo getDhcpInfo() { 684 try { 685 return mService.getDhcpInfo(); 686 } catch (RemoteException e) { 687 return null; 688 } 689 } 690 691 692 /** 693 * Enable or disable Wi-Fi. 694 * @param enabled {@code true} to enable, {@code false} to disable. 695 * @return {@code true} if the operation succeeds (or if the existing state 696 * is the same as the requested state). 697 */ 698 public boolean setWifiEnabled(boolean enabled) { 699 try { 700 return mService.setWifiEnabled(enabled); 701 } catch (RemoteException e) { 702 return false; 703 } 704 } 705 706 /** 707 * Gets the Wi-Fi enabled state. 708 * @return One of {@link #WIFI_STATE_DISABLED}, 709 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 710 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 711 * @see #isWifiEnabled() 712 */ 713 public int getWifiState() { 714 try { 715 return mService.getWifiEnabledState(); 716 } catch (RemoteException e) { 717 return WIFI_STATE_UNKNOWN; 718 } 719 } 720 721 /** 722 * Return whether Wi-Fi is enabled or disabled. 723 * @return {@code true} if Wi-Fi is enabled 724 * @see #getWifiState() 725 */ 726 public boolean isWifiEnabled() { 727 return getWifiState() == WIFI_STATE_ENABLED; 728 } 729 730 /** 731 * Calculates the level of the signal. This should be used any time a signal 732 * is being shown. 733 * 734 * @param rssi The power of the signal measured in RSSI. 735 * @param numLevels The number of levels to consider in the calculated 736 * level. 737 * @return A level of the signal, given in the range of 0 to numLevels-1 738 * (both inclusive). 739 */ 740 public static int calculateSignalLevel(int rssi, int numLevels) { 741 if (rssi <= MIN_RSSI) { 742 return 0; 743 } else if (rssi >= MAX_RSSI) { 744 return numLevels - 1; 745 } else { 746 int partitionSize = (MAX_RSSI - MIN_RSSI) / (numLevels - 1); 747 return (rssi - MIN_RSSI) / partitionSize; 748 } 749 } 750 751 /** 752 * Compares two signal strengths. 753 * 754 * @param rssiA The power of the first signal measured in RSSI. 755 * @param rssiB The power of the second signal measured in RSSI. 756 * @return Returns <0 if the first signal is weaker than the second signal, 757 * 0 if the two signals have the same strength, and >0 if the first 758 * signal is stronger than the second signal. 759 */ 760 public static int compareSignalLevel(int rssiA, int rssiB) { 761 return rssiA - rssiB; 762 } 763 764 /** 765 * Start AccessPoint mode with the specified 766 * configuration. If the radio is already running in 767 * AP mode, update the new configuration 768 * Note that starting in access point mode disables station 769 * mode operation 770 * @param wifiConfig SSID, security and channel details as 771 * part of WifiConfiguration 772 * @return {@code true} if the operation succeeds, {@code false} otherwise 773 * 774 * @hide Dont open up yet 775 */ 776 public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { 777 try { 778 return mService.setWifiApEnabled(wifiConfig, enabled); 779 } catch (RemoteException e) { 780 return false; 781 } 782 } 783 784 /** 785 * Gets the Wi-Fi enabled state. 786 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 787 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 788 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 789 * @see #isWifiApEnabled() 790 * 791 * @hide Dont open yet 792 */ 793 public int getWifiApState() { 794 try { 795 return mService.getWifiApEnabledState(); 796 } catch (RemoteException e) { 797 return WIFI_AP_STATE_FAILED; 798 } 799 } 800 801 /** 802 * Return whether Wi-Fi AP is enabled or disabled. 803 * @return {@code true} if Wi-Fi AP is enabled 804 * @see #getWifiApState() 805 * 806 * @hide Dont open yet 807 */ 808 public boolean isWifiApEnabled() { 809 return getWifiApState() == WIFI_AP_STATE_ENABLED; 810 } 811 812 /** 813 * Gets the Wi-Fi AP Configuration. 814 * @return AP details in WifiConfiguration 815 * 816 * @hide Dont open yet 817 */ 818 public WifiConfiguration getWifiApConfiguration() { 819 try { 820 return mService.getWifiApConfiguration(); 821 } catch (RemoteException e) { 822 return null; 823 } 824 } 825 826 /** 827 * Allows an application to keep the Wi-Fi radio awake. 828 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 829 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 830 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 831 * WifiLocks are held in any application. 832 * 833 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 834 * could function over a mobile network, if available. A program that needs to download large 835 * files should hold a WifiLock to ensure that the download will complete, but a program whose 836 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 837 * affecting battery life. 838 * 839 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 840 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 841 * is idle. 842 */ 843 public class WifiLock { 844 private String mTag; 845 private final IBinder mBinder; 846 private int mRefCount; 847 int mLockType; 848 private boolean mRefCounted; 849 private boolean mHeld; 850 851 private WifiLock(int lockType, String tag) { 852 mTag = tag; 853 mLockType = lockType; 854 mBinder = new Binder(); 855 mRefCount = 0; 856 mRefCounted = true; 857 mHeld = false; 858 } 859 860 /** 861 * Locks the Wi-Fi radio on until {@link #release} is called. 862 * 863 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 864 * reference count, and the radio will remain locked as long as the reference count is 865 * above zero. 866 * 867 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 868 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 869 * will be required, regardless of the number of times that {@code acquire} is called. 870 */ 871 public void acquire() { 872 synchronized (mBinder) { 873 if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) { 874 try { 875 mService.acquireWifiLock(mBinder, mLockType, mTag); 876 synchronized (WifiManager.this) { 877 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 878 mService.releaseWifiLock(mBinder); 879 throw new UnsupportedOperationException( 880 "Exceeded maximum number of wifi locks"); 881 } 882 mActiveLockCount++; 883 } 884 } catch (RemoteException ignore) { 885 } 886 mHeld = true; 887 } 888 } 889 } 890 891 /** 892 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 893 * 894 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 895 * reference count, and the radio will be unlocked only when the reference count reaches 896 * zero. If the reference count goes below zero (that is, if {@code release} is called 897 * a greater number of times than {@link #acquire}), an exception is thrown. 898 * 899 * If this WifiLock is not reference-counted, the first call to {@code release} (after 900 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 901 * calls will be ignored. 902 */ 903 public void release() { 904 synchronized (mBinder) { 905 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 906 try { 907 mService.releaseWifiLock(mBinder); 908 synchronized (WifiManager.this) { 909 mActiveLockCount--; 910 } 911 } catch (RemoteException ignore) { 912 } 913 mHeld = false; 914 } 915 if (mRefCount < 0) { 916 throw new RuntimeException("WifiLock under-locked " + mTag); 917 } 918 } 919 } 920 921 /** 922 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 923 * 924 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 925 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 926 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 927 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 928 * radio whenever {@link #release} is called and it is locked. 929 * 930 * @param refCounted true if this WifiLock should keep a reference count 931 */ 932 public void setReferenceCounted(boolean refCounted) { 933 mRefCounted = refCounted; 934 } 935 936 /** 937 * Checks whether this WifiLock is currently held. 938 * 939 * @return true if this WifiLock is held, false otherwise 940 */ 941 public boolean isHeld() { 942 synchronized (mBinder) { 943 return mHeld; 944 } 945 } 946 947 public String toString() { 948 String s1, s2, s3; 949 synchronized (mBinder) { 950 s1 = Integer.toHexString(System.identityHashCode(this)); 951 s2 = mHeld ? "held; " : ""; 952 if (mRefCounted) { 953 s3 = "refcounted: refcount = " + mRefCount; 954 } else { 955 s3 = "not refcounted"; 956 } 957 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 958 } 959 } 960 961 @Override 962 protected void finalize() throws Throwable { 963 super.finalize(); 964 synchronized (mBinder) { 965 if (mHeld) { 966 try { 967 mService.releaseWifiLock(mBinder); 968 synchronized (WifiManager.this) { 969 mActiveLockCount--; 970 } 971 } catch (RemoteException ignore) { 972 } 973 } 974 } 975 } 976 } 977 978 /** 979 * Creates a new WifiLock. 980 * 981 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL} and 982 * {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks. 983 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 984 * never shown to the user under normal conditions, but should be descriptive 985 * enough to identify your application and the specific WifiLock within it, if it 986 * holds multiple WifiLocks. 987 * 988 * @return a new, unacquired WifiLock with the given tag. 989 * 990 * @see WifiLock 991 */ 992 public WifiLock createWifiLock(int lockType, String tag) { 993 return new WifiLock(lockType, tag); 994 } 995 996 /** 997 * Creates a new WifiLock. 998 * 999 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 1000 * never shown to the user under normal conditions, but should be descriptive 1001 * enough to identify your application and the specific WifiLock within it, if it 1002 * holds multiple WifiLocks. 1003 * 1004 * @return a new, unacquired WifiLock with the given tag. 1005 * 1006 * @see WifiLock 1007 */ 1008 public WifiLock createWifiLock(String tag) { 1009 return new WifiLock(WIFI_MODE_FULL, tag); 1010 } 1011 1012 1013 /** 1014 * Create a new MulticastLock 1015 * 1016 * @param tag a tag for the MulticastLock to identify it in debugging 1017 * messages. This string is never shown to the user under 1018 * normal conditions, but should be descriptive enough to 1019 * identify your application and the specific MulticastLock 1020 * within it, if it holds multiple MulticastLocks. 1021 * 1022 * @return a new, unacquired MulticastLock with the given tag. 1023 * 1024 * @see MulticastLock 1025 */ 1026 public MulticastLock createMulticastLock(String tag) { 1027 return new MulticastLock(tag); 1028 } 1029 1030 /** 1031 * Allows an application to receive Wifi Multicast packets. 1032 * Normally the Wifi stack filters out packets not explicitly 1033 * addressed to this device. Acquring a MulticastLock will 1034 * cause the stack to receive packets addressed to multicast 1035 * addresses. Processing these extra packets can cause a noticable 1036 * battery drain and should be disabled when not needed. 1037 */ 1038 public class MulticastLock { 1039 private String mTag; 1040 private final IBinder mBinder; 1041 private int mRefCount; 1042 private boolean mRefCounted; 1043 private boolean mHeld; 1044 1045 private MulticastLock(String tag) { 1046 mTag = tag; 1047 mBinder = new Binder(); 1048 mRefCount = 0; 1049 mRefCounted = true; 1050 mHeld = false; 1051 } 1052 1053 /** 1054 * Locks Wifi Multicast on until {@link #release} is called. 1055 * 1056 * If this MulticastLock is reference-counted each call to 1057 * {@code acquire} will increment the reference count, and the 1058 * wifi interface will receive multicast packets as long as the 1059 * reference count is above zero. 1060 * 1061 * If this MulticastLock is not reference-counted, the first call to 1062 * {@code acquire} will turn on the multicast packets, but subsequent 1063 * calls will be ignored. Only one call to {@link #release} will 1064 * be required, regardless of the number of times that {@code acquire} 1065 * is called. 1066 * 1067 * Note that other applications may also lock Wifi Multicast on. 1068 * Only they can relinquish their lock. 1069 * 1070 * Also note that applications cannot leave Multicast locked on. 1071 * When an app exits or crashes, any Multicast locks will be released. 1072 */ 1073 public void acquire() { 1074 synchronized (mBinder) { 1075 if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) { 1076 try { 1077 mService.acquireMulticastLock(mBinder, mTag); 1078 synchronized (WifiManager.this) { 1079 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 1080 mService.releaseMulticastLock(); 1081 throw new UnsupportedOperationException( 1082 "Exceeded maximum number of wifi locks"); 1083 } 1084 mActiveLockCount++; 1085 } 1086 } catch (RemoteException ignore) { 1087 } 1088 mHeld = true; 1089 } 1090 } 1091 } 1092 1093 /** 1094 * Unlocks Wifi Multicast, restoring the filter of packets 1095 * not addressed specifically to this device and saving power. 1096 * 1097 * If this MulticastLock is reference-counted, each call to 1098 * {@code release} will decrement the reference count, and the 1099 * multicast packets will only stop being received when the reference 1100 * count reaches zero. If the reference count goes below zero (that 1101 * is, if {@code release} is called a greater number of times than 1102 * {@link #acquire}), an exception is thrown. 1103 * 1104 * If this MulticastLock is not reference-counted, the first call to 1105 * {@code release} (after the radio was multicast locked using 1106 * {@link #acquire}) will unlock the multicast, and subsequent calls 1107 * will be ignored. 1108 * 1109 * Note that if any other Wifi Multicast Locks are still outstanding 1110 * this {@code release} call will not have an immediate effect. Only 1111 * when all applications have released all their Multicast Locks will 1112 * the Multicast filter be turned back on. 1113 * 1114 * Also note that when an app exits or crashes all of its Multicast 1115 * Locks will be automatically released. 1116 */ 1117 public void release() { 1118 synchronized (mBinder) { 1119 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 1120 try { 1121 mService.releaseMulticastLock(); 1122 synchronized (WifiManager.this) { 1123 mActiveLockCount--; 1124 } 1125 } catch (RemoteException ignore) { 1126 } 1127 mHeld = false; 1128 } 1129 if (mRefCount < 0) { 1130 throw new RuntimeException("MulticastLock under-locked " 1131 + mTag); 1132 } 1133 } 1134 } 1135 1136 /** 1137 * Controls whether this is a reference-counted or non-reference- 1138 * counted MulticastLock. 1139 * 1140 * Reference-counted MulticastLocks keep track of the number of calls 1141 * to {@link #acquire} and {@link #release}, and only stop the 1142 * reception of multicast packets when every call to {@link #acquire} 1143 * has been balanced with a call to {@link #release}. Non-reference- 1144 * counted MulticastLocks allow the reception of multicast packets 1145 * whenever {@link #acquire} is called and stop accepting multicast 1146 * packets whenever {@link #release} is called. 1147 * 1148 * @param refCounted true if this MulticastLock should keep a reference 1149 * count 1150 */ 1151 public void setReferenceCounted(boolean refCounted) { 1152 mRefCounted = refCounted; 1153 } 1154 1155 /** 1156 * Checks whether this MulticastLock is currently held. 1157 * 1158 * @return true if this MulticastLock is held, false otherwise 1159 */ 1160 public boolean isHeld() { 1161 synchronized (mBinder) { 1162 return mHeld; 1163 } 1164 } 1165 1166 public String toString() { 1167 String s1, s2, s3; 1168 synchronized (mBinder) { 1169 s1 = Integer.toHexString(System.identityHashCode(this)); 1170 s2 = mHeld ? "held; " : ""; 1171 if (mRefCounted) { 1172 s3 = "refcounted: refcount = " + mRefCount; 1173 } else { 1174 s3 = "not refcounted"; 1175 } 1176 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 1177 } 1178 } 1179 1180 @Override 1181 protected void finalize() throws Throwable { 1182 super.finalize(); 1183 setReferenceCounted(false); 1184 release(); 1185 } 1186 } 1187 1188 /** 1189 * Check multicast filter status. 1190 * 1191 * @return true if multicast packets are allowed. 1192 * 1193 * @hide pending API council approval 1194 */ 1195 public boolean isMulticastEnabled() { 1196 try { 1197 return mService.isMulticastEnabled(); 1198 } catch (RemoteException e) { 1199 return false; 1200 } 1201 } 1202 1203 /** 1204 * Initialize the multicast filtering to 'on' 1205 * @hide no intent to publish 1206 */ 1207 public boolean initializeMulticastFiltering() { 1208 try { 1209 mService.initializeMulticastFiltering(); 1210 return true; 1211 } catch (RemoteException e) { 1212 return false; 1213 } 1214 } 1215} 1216