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