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 17 package android.net.wifi; 18 19 import android.annotation.SdkConstant; 20 import android.annotation.SdkConstant.SdkConstantType; 21 import android.net.DhcpInfo; 22 import android.os.Binder; 23 import android.os.IBinder; 24 import android.os.Handler; 25 import android.os.RemoteException; 26 import android.os.WorkSource; 27 28 import 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 */ 51 public 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 mService.startScan(false); 574 return true; 575 } catch (RemoteException e) { 576 return false; 577 } 578 } 579 580 /** 581 * Request a scan for access points. Returns immediately. The availability 582 * of the results is made known later by means of an asynchronous event sent 583 * on completion of the scan. 584 * This is a variant of startScan that forces an active scan, even if passive 585 * scans are the current default 586 * @return {@code true} if the operation succeeded, i.e., the scan was initiated 587 * 588 * @hide 589 */ 590 public boolean startScanActive() { 591 try { 592 mService.startScan(true); 593 return true; 594 } catch (RemoteException e) { 595 return false; 596 } 597 } 598 599 /** 600 * Return dynamic information about the current Wi-Fi connection, if any is active. 601 * @return the Wi-Fi information, contained in {@link WifiInfo}. 602 */ 603 public WifiInfo getConnectionInfo() { 604 try { 605 return mService.getConnectionInfo(); 606 } catch (RemoteException e) { 607 return null; 608 } 609 } 610 611 /** 612 * Return the results of the latest access point scan. 613 * @return the list of access points found in the most recent scan. 614 */ 615 public List<ScanResult> getScanResults() { 616 try { 617 return mService.getScanResults(); 618 } catch (RemoteException e) { 619 return null; 620 } 621 } 622 623 /** 624 * Tell the supplicant to persist the current list of configured networks. 625 * <p> 626 * Note: It is possible for this method to change the network IDs of 627 * existing networks. You should assume the network IDs can be different 628 * after calling this method. 629 * 630 * @return {@code true} if the operation succeeded 631 */ 632 public boolean saveConfiguration() { 633 try { 634 return mService.saveConfiguration(); 635 } catch (RemoteException e) { 636 return false; 637 } 638 } 639 640 /** 641 * Return the number of frequency channels that are allowed 642 * to be used in the current regulatory domain. 643 * @return the number of allowed channels, or {@code -1} if an error occurs 644 * 645 * @hide pending API council 646 */ 647 public int getNumAllowedChannels() { 648 try { 649 return mService.getNumAllowedChannels(); 650 } catch (RemoteException e) { 651 return -1; 652 } 653 } 654 655 /** 656 * Set the number of frequency channels that are allowed to be used 657 * in the current regulatory domain. This method should be used only 658 * if the correct number of channels cannot be determined automatically 659 * for some reason. 660 * @param numChannels the number of allowed channels. Must be greater than 0 661 * and less than or equal to 16. 662 * @param persist {@code true} if you want this remembered 663 * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g., 664 * {@code numChannels} is out of range. 665 * 666 * @hide pending API council 667 */ 668 public boolean setNumAllowedChannels(int numChannels, boolean persist) { 669 try { 670 return mService.setNumAllowedChannels(numChannels, persist); 671 } catch (RemoteException e) { 672 return false; 673 } 674 } 675 676 /** 677 * Return the list of valid values for the number of allowed radio channels 678 * for various regulatory domains. 679 * @return the list of channel counts, or {@code null} if the operation fails 680 * 681 * @hide pending API council review 682 */ 683 public int[] getValidChannelCounts() { 684 try { 685 return mService.getValidChannelCounts(); 686 } catch (RemoteException e) { 687 return null; 688 } 689 } 690 691 /** 692 * Return the DHCP-assigned addresses from the last successful DHCP request, 693 * if any. 694 * @return the DHCP information 695 */ 696 public DhcpInfo getDhcpInfo() { 697 try { 698 return mService.getDhcpInfo(); 699 } catch (RemoteException e) { 700 return null; 701 } 702 } 703 704 705 /** 706 * Enable or disable Wi-Fi. 707 * @param enabled {@code true} to enable, {@code false} to disable. 708 * @return {@code true} if the operation succeeds (or if the existing state 709 * is the same as the requested state). 710 */ 711 public boolean setWifiEnabled(boolean enabled) { 712 try { 713 return mService.setWifiEnabled(enabled); 714 } catch (RemoteException e) { 715 return false; 716 } 717 } 718 719 /** 720 * Gets the Wi-Fi enabled state. 721 * @return One of {@link #WIFI_STATE_DISABLED}, 722 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 723 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 724 * @see #isWifiEnabled() 725 */ 726 public int getWifiState() { 727 try { 728 return mService.getWifiEnabledState(); 729 } catch (RemoteException e) { 730 return WIFI_STATE_UNKNOWN; 731 } 732 } 733 734 /** 735 * Return whether Wi-Fi is enabled or disabled. 736 * @return {@code true} if Wi-Fi is enabled 737 * @see #getWifiState() 738 */ 739 public boolean isWifiEnabled() { 740 return getWifiState() == WIFI_STATE_ENABLED; 741 } 742 743 /** 744 * Calculates the level of the signal. This should be used any time a signal 745 * is being shown. 746 * 747 * @param rssi The power of the signal measured in RSSI. 748 * @param numLevels The number of levels to consider in the calculated 749 * level. 750 * @return A level of the signal, given in the range of 0 to numLevels-1 751 * (both inclusive). 752 */ 753 public static int calculateSignalLevel(int rssi, int numLevels) { 754 if (rssi <= MIN_RSSI) { 755 return 0; 756 } else if (rssi >= MAX_RSSI) { 757 return numLevels - 1; 758 } else { 759 int partitionSize = (MAX_RSSI - MIN_RSSI) / (numLevels - 1); 760 return (rssi - MIN_RSSI) / partitionSize; 761 } 762 } 763 764 /** 765 * Compares two signal strengths. 766 * 767 * @param rssiA The power of the first signal measured in RSSI. 768 * @param rssiB The power of the second signal measured in RSSI. 769 * @return Returns <0 if the first signal is weaker than the second signal, 770 * 0 if the two signals have the same strength, and >0 if the first 771 * signal is stronger than the second signal. 772 */ 773 public static int compareSignalLevel(int rssiA, int rssiB) { 774 return rssiA - rssiB; 775 } 776 777 /** 778 * Start AccessPoint mode with the specified 779 * configuration. If the radio is already running in 780 * AP mode, update the new configuration 781 * Note that starting in access point mode disables station 782 * mode operation 783 * @param wifiConfig SSID, security and channel details as 784 * part of WifiConfiguration 785 * @return {@code true} if the operation succeeds, {@code false} otherwise 786 * 787 * @hide Dont open up yet 788 */ 789 public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { 790 try { 791 return mService.setWifiApEnabled(wifiConfig, enabled); 792 } catch (RemoteException e) { 793 return false; 794 } 795 } 796 797 /** 798 * Gets the Wi-Fi enabled state. 799 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 800 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 801 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 802 * @see #isWifiApEnabled() 803 * 804 * @hide Dont open yet 805 */ 806 public int getWifiApState() { 807 try { 808 return mService.getWifiApEnabledState(); 809 } catch (RemoteException e) { 810 return WIFI_AP_STATE_FAILED; 811 } 812 } 813 814 /** 815 * Return whether Wi-Fi AP is enabled or disabled. 816 * @return {@code true} if Wi-Fi AP is enabled 817 * @see #getWifiApState() 818 * 819 * @hide Dont open yet 820 */ 821 public boolean isWifiApEnabled() { 822 return getWifiApState() == WIFI_AP_STATE_ENABLED; 823 } 824 825 /** 826 * Gets the Wi-Fi AP Configuration. 827 * @return AP details in WifiConfiguration 828 * 829 * @hide Dont open yet 830 */ 831 public WifiConfiguration getWifiApConfiguration() { 832 try { 833 return mService.getWifiApConfiguration(); 834 } catch (RemoteException e) { 835 return null; 836 } 837 } 838 839 /** 840 * Sets the Wi-Fi AP Configuration. 841 * @return {@code true} if the operation succeeded, {@code false} otherwise 842 * 843 * @hide Dont open yet 844 */ 845 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { 846 try { 847 mService.setWifiApConfiguration(wifiConfig); 848 return true; 849 } catch (RemoteException e) { 850 return false; 851 } 852 } 853 854 /** 855 * Allows an application to keep the Wi-Fi radio awake. 856 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 857 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 858 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 859 * WifiLocks are held in any application. 860 * 861 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 862 * could function over a mobile network, if available. A program that needs to download large 863 * files should hold a WifiLock to ensure that the download will complete, but a program whose 864 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 865 * affecting battery life. 866 * 867 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 868 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 869 * is idle. 870 */ 871 public class WifiLock { 872 private String mTag; 873 private final IBinder mBinder; 874 private int mRefCount; 875 int mLockType; 876 private boolean mRefCounted; 877 private boolean mHeld; 878 private WorkSource mWorkSource; 879 880 private WifiLock(int lockType, String tag) { 881 mTag = tag; 882 mLockType = lockType; 883 mBinder = new Binder(); 884 mRefCount = 0; 885 mRefCounted = true; 886 mHeld = false; 887 } 888 889 /** 890 * Locks the Wi-Fi radio on until {@link #release} is called. 891 * 892 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 893 * reference count, and the radio will remain locked as long as the reference count is 894 * above zero. 895 * 896 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 897 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 898 * will be required, regardless of the number of times that {@code acquire} is called. 899 */ 900 public void acquire() { 901 synchronized (mBinder) { 902 if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) { 903 try { 904 mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); 905 synchronized (WifiManager.this) { 906 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 907 mService.releaseWifiLock(mBinder); 908 throw new UnsupportedOperationException( 909 "Exceeded maximum number of wifi locks"); 910 } 911 mActiveLockCount++; 912 } 913 } catch (RemoteException ignore) { 914 } 915 mHeld = true; 916 } 917 } 918 } 919 920 /** 921 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 922 * 923 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 924 * reference count, and the radio will be unlocked only when the reference count reaches 925 * zero. If the reference count goes below zero (that is, if {@code release} is called 926 * a greater number of times than {@link #acquire}), an exception is thrown. 927 * 928 * If this WifiLock is not reference-counted, the first call to {@code release} (after 929 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 930 * calls will be ignored. 931 */ 932 public void release() { 933 synchronized (mBinder) { 934 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 935 try { 936 mService.releaseWifiLock(mBinder); 937 synchronized (WifiManager.this) { 938 mActiveLockCount--; 939 } 940 } catch (RemoteException ignore) { 941 } 942 mHeld = false; 943 } 944 if (mRefCount < 0) { 945 throw new RuntimeException("WifiLock under-locked " + mTag); 946 } 947 } 948 } 949 950 /** 951 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 952 * 953 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 954 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 955 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 956 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 957 * radio whenever {@link #release} is called and it is locked. 958 * 959 * @param refCounted true if this WifiLock should keep a reference count 960 */ 961 public void setReferenceCounted(boolean refCounted) { 962 mRefCounted = refCounted; 963 } 964 965 /** 966 * Checks whether this WifiLock is currently held. 967 * 968 * @return true if this WifiLock is held, false otherwise 969 */ 970 public boolean isHeld() { 971 synchronized (mBinder) { 972 return mHeld; 973 } 974 } 975 976 public void setWorkSource(WorkSource ws) { 977 synchronized (mBinder) { 978 if (ws != null && ws.size() == 0) { 979 ws = null; 980 } 981 boolean changed = true; 982 if (ws == null) { 983 mWorkSource = null; 984 } else if (mWorkSource == null) { 985 changed = mWorkSource != null; 986 mWorkSource = new WorkSource(ws); 987 } else { 988 changed = mWorkSource.diff(ws); 989 if (changed) { 990 mWorkSource.set(ws); 991 } 992 } 993 if (changed && mHeld) { 994 try { 995 mService.updateWifiLockWorkSource(mBinder, mWorkSource); 996 } catch (RemoteException e) { 997 } 998 } 999 } 1000 } 1001 1002 public String toString() { 1003 String s1, s2, s3; 1004 synchronized (mBinder) { 1005 s1 = Integer.toHexString(System.identityHashCode(this)); 1006 s2 = mHeld ? "held; " : ""; 1007 if (mRefCounted) { 1008 s3 = "refcounted: refcount = " + mRefCount; 1009 } else { 1010 s3 = "not refcounted"; 1011 } 1012 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 1013 } 1014 } 1015 1016 @Override 1017 protected void finalize() throws Throwable { 1018 super.finalize(); 1019 synchronized (mBinder) { 1020 if (mHeld) { 1021 try { 1022 mService.releaseWifiLock(mBinder); 1023 synchronized (WifiManager.this) { 1024 mActiveLockCount--; 1025 } 1026 } catch (RemoteException ignore) { 1027 } 1028 } 1029 } 1030 } 1031 } 1032 1033 /** 1034 * Creates a new WifiLock. 1035 * 1036 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL}, 1037 * and {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks. 1038 * 1039 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 1040 * never shown to the user under normal conditions, but should be descriptive 1041 * enough to identify your application and the specific WifiLock within it, if it 1042 * holds multiple WifiLocks. 1043 * 1044 * @return a new, unacquired WifiLock with the given tag. 1045 * 1046 * @see WifiLock 1047 */ 1048 public WifiLock createWifiLock(int lockType, String tag) { 1049 return new WifiLock(lockType, tag); 1050 } 1051 1052 /** 1053 * Creates a new WifiLock. 1054 * 1055 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 1056 * never shown to the user under normal conditions, but should be descriptive 1057 * enough to identify your application and the specific WifiLock within it, if it 1058 * holds multiple WifiLocks. 1059 * 1060 * @return a new, unacquired WifiLock with the given tag. 1061 * 1062 * @see WifiLock 1063 */ 1064 public WifiLock createWifiLock(String tag) { 1065 return new WifiLock(WIFI_MODE_FULL, tag); 1066 } 1067 1068 1069 /** 1070 * Create a new MulticastLock 1071 * 1072 * @param tag a tag for the MulticastLock to identify it in debugging 1073 * messages. This string is never shown to the user under 1074 * normal conditions, but should be descriptive enough to 1075 * identify your application and the specific MulticastLock 1076 * within it, if it holds multiple MulticastLocks. 1077 * 1078 * @return a new, unacquired MulticastLock with the given tag. 1079 * 1080 * @see MulticastLock 1081 */ 1082 public MulticastLock createMulticastLock(String tag) { 1083 return new MulticastLock(tag); 1084 } 1085 1086 /** 1087 * Allows an application to receive Wifi Multicast packets. 1088 * Normally the Wifi stack filters out packets not explicitly 1089 * addressed to this device. Acquring a MulticastLock will 1090 * cause the stack to receive packets addressed to multicast 1091 * addresses. Processing these extra packets can cause a noticable 1092 * battery drain and should be disabled when not needed. 1093 */ 1094 public class MulticastLock { 1095 private String mTag; 1096 private final IBinder mBinder; 1097 private int mRefCount; 1098 private boolean mRefCounted; 1099 private boolean mHeld; 1100 1101 private MulticastLock(String tag) { 1102 mTag = tag; 1103 mBinder = new Binder(); 1104 mRefCount = 0; 1105 mRefCounted = true; 1106 mHeld = false; 1107 } 1108 1109 /** 1110 * Locks Wifi Multicast on until {@link #release} is called. 1111 * 1112 * If this MulticastLock is reference-counted each call to 1113 * {@code acquire} will increment the reference count, and the 1114 * wifi interface will receive multicast packets as long as the 1115 * reference count is above zero. 1116 * 1117 * If this MulticastLock is not reference-counted, the first call to 1118 * {@code acquire} will turn on the multicast packets, but subsequent 1119 * calls will be ignored. Only one call to {@link #release} will 1120 * be required, regardless of the number of times that {@code acquire} 1121 * is called. 1122 * 1123 * Note that other applications may also lock Wifi Multicast on. 1124 * Only they can relinquish their lock. 1125 * 1126 * Also note that applications cannot leave Multicast locked on. 1127 * When an app exits or crashes, any Multicast locks will be released. 1128 */ 1129 public void acquire() { 1130 synchronized (mBinder) { 1131 if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) { 1132 try { 1133 mService.acquireMulticastLock(mBinder, mTag); 1134 synchronized (WifiManager.this) { 1135 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 1136 mService.releaseMulticastLock(); 1137 throw new UnsupportedOperationException( 1138 "Exceeded maximum number of wifi locks"); 1139 } 1140 mActiveLockCount++; 1141 } 1142 } catch (RemoteException ignore) { 1143 } 1144 mHeld = true; 1145 } 1146 } 1147 } 1148 1149 /** 1150 * Unlocks Wifi Multicast, restoring the filter of packets 1151 * not addressed specifically to this device and saving power. 1152 * 1153 * If this MulticastLock is reference-counted, each call to 1154 * {@code release} will decrement the reference count, and the 1155 * multicast packets will only stop being received when the reference 1156 * count reaches zero. If the reference count goes below zero (that 1157 * is, if {@code release} is called a greater number of times than 1158 * {@link #acquire}), an exception is thrown. 1159 * 1160 * If this MulticastLock is not reference-counted, the first call to 1161 * {@code release} (after the radio was multicast locked using 1162 * {@link #acquire}) will unlock the multicast, and subsequent calls 1163 * will be ignored. 1164 * 1165 * Note that if any other Wifi Multicast Locks are still outstanding 1166 * this {@code release} call will not have an immediate effect. Only 1167 * when all applications have released all their Multicast Locks will 1168 * the Multicast filter be turned back on. 1169 * 1170 * Also note that when an app exits or crashes all of its Multicast 1171 * Locks will be automatically released. 1172 */ 1173 public void release() { 1174 synchronized (mBinder) { 1175 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 1176 try { 1177 mService.releaseMulticastLock(); 1178 synchronized (WifiManager.this) { 1179 mActiveLockCount--; 1180 } 1181 } catch (RemoteException ignore) { 1182 } 1183 mHeld = false; 1184 } 1185 if (mRefCount < 0) { 1186 throw new RuntimeException("MulticastLock under-locked " 1187 + mTag); 1188 } 1189 } 1190 } 1191 1192 /** 1193 * Controls whether this is a reference-counted or non-reference- 1194 * counted MulticastLock. 1195 * 1196 * Reference-counted MulticastLocks keep track of the number of calls 1197 * to {@link #acquire} and {@link #release}, and only stop the 1198 * reception of multicast packets when every call to {@link #acquire} 1199 * has been balanced with a call to {@link #release}. Non-reference- 1200 * counted MulticastLocks allow the reception of multicast packets 1201 * whenever {@link #acquire} is called and stop accepting multicast 1202 * packets whenever {@link #release} is called. 1203 * 1204 * @param refCounted true if this MulticastLock should keep a reference 1205 * count 1206 */ 1207 public void setReferenceCounted(boolean refCounted) { 1208 mRefCounted = refCounted; 1209 } 1210 1211 /** 1212 * Checks whether this MulticastLock is currently held. 1213 * 1214 * @return true if this MulticastLock is held, false otherwise 1215 */ 1216 public boolean isHeld() { 1217 synchronized (mBinder) { 1218 return mHeld; 1219 } 1220 } 1221 1222 public String toString() { 1223 String s1, s2, s3; 1224 synchronized (mBinder) { 1225 s1 = Integer.toHexString(System.identityHashCode(this)); 1226 s2 = mHeld ? "held; " : ""; 1227 if (mRefCounted) { 1228 s3 = "refcounted: refcount = " + mRefCount; 1229 } else { 1230 s3 = "not refcounted"; 1231 } 1232 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 1233 } 1234 } 1235 1236 @Override 1237 protected void finalize() throws Throwable { 1238 super.finalize(); 1239 setReferenceCounted(false); 1240 release(); 1241 } 1242 } 1243 1244 /** 1245 * Check multicast filter status. 1246 * 1247 * @return true if multicast packets are allowed. 1248 * 1249 * @hide pending API council approval 1250 */ 1251 public boolean isMulticastEnabled() { 1252 try { 1253 return mService.isMulticastEnabled(); 1254 } catch (RemoteException e) { 1255 return false; 1256 } 1257 } 1258 1259 /** 1260 * Initialize the multicast filtering to 'on' 1261 * @hide no intent to publish 1262 */ 1263 public boolean initializeMulticastFiltering() { 1264 try { 1265 mService.initializeMulticastFiltering(); 1266 return true; 1267 } catch (RemoteException e) { 1268 return false; 1269 } 1270 } 1271 } 1272