WifiManager.java revision d24b8183b93e781080b2c16c487e60d51c12da31
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 a connection to the supplicant has 129 * been established (and it is now possible 130 * to perform Wi-Fi operations) or the connection to the supplicant has been 131 * lost. One extra provides the connection state as a boolean, where {@code true} 132 * means CONNECTED. 133 * @see #EXTRA_SUPPLICANT_CONNECTED 134 */ 135 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 136 public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = 137 "android.net.wifi.supplicant.CONNECTION_CHANGE"; 138 /** 139 * The lookup key for a boolean that indicates whether a connection to 140 * the supplicant daemon has been gained or lost. {@code true} means 141 * a connection now exists. 142 * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. 143 */ 144 public static final String EXTRA_SUPPLICANT_CONNECTED = "connected"; 145 /** 146 * Broadcast intent action indicating that the state of Wi-Fi connectivity 147 * has changed. One extra provides the new state 148 * in the form of a {@link android.net.NetworkInfo} object. If the new state is 149 * CONNECTED, a second extra may provide the BSSID of the access point, 150 * as a {@code String}. 151 * @see #EXTRA_NETWORK_INFO 152 * @see #EXTRA_BSSID 153 */ 154 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 155 public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"; 156 /** 157 * The lookup key for a {@link android.net.NetworkInfo} object associated with the 158 * Wi-Fi network. Retrieve with 159 * {@link android.content.Intent#getParcelableExtra(String)}. 160 */ 161 public static final String EXTRA_NETWORK_INFO = "networkInfo"; 162 /** 163 * The lookup key for a String giving the BSSID of the access point to which 164 * we are connected. Only present when the new state is CONNECTED. 165 * Retrieve with 166 * {@link android.content.Intent#getStringExtra(String)}. 167 */ 168 public static final String EXTRA_BSSID = "bssid"; 169 /** 170 * Broadcast intent action indicating that the state of establishing a connection to 171 * an access point has changed.One extra provides the new 172 * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and 173 * is not generally the most useful thing to look at if you are just interested in 174 * the overall state of connectivity. 175 * @see #EXTRA_NEW_STATE 176 * @see #EXTRA_SUPPLICANT_ERROR 177 */ 178 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 179 public static final String SUPPLICANT_STATE_CHANGED_ACTION = 180 "android.net.wifi.supplicant.STATE_CHANGE"; 181 /** 182 * The lookup key for a {@link SupplicantState} describing the new state 183 * Retrieve with 184 * {@link android.content.Intent#getParcelableExtra(String)}. 185 */ 186 public static final String EXTRA_NEW_STATE = "newState"; 187 188 /** 189 * The lookup key for a {@link SupplicantState} describing the supplicant 190 * error code if any 191 * Retrieve with 192 * {@link android.content.Intent#getIntExtra(String, int)}. 193 * @see #ERROR_AUTHENTICATING 194 */ 195 public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; 196 197 /** 198 * An access point scan has completed, and results are available from the supplicant. 199 * Call {@link #getScanResults()} to obtain the results. 200 */ 201 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 202 public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; 203 /** 204 * The RSSI (signal strength) has changed. 205 * @see #EXTRA_NEW_RSSI 206 */ 207 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 208 public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; 209 /** 210 * The lookup key for an {@code int} giving the new RSSI in dBm. 211 */ 212 public static final String EXTRA_NEW_RSSI = "newRssi"; 213 214 /** 215 * The network IDs of the configured networks could have changed. 216 */ 217 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 218 public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; 219 220 /** 221 * Activity Action: Pick a Wi-Fi network to connect to. 222 * <p>Input: Nothing. 223 * <p>Output: Nothing. 224 */ 225 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 226 public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; 227 228 /** 229 * In this mode, Wi-Fi will be kept active, 230 * and will behave normally, i.e., it will attempt to automatically 231 * establish a connection to a remembered access point that is 232 * within range, and will do periodic scans if there are remembered 233 * access points but none are in range. 234 * @hide pending API council review 235 */ 236 public static final int WIFI_MODE_FULL = 1; 237 /** 238 * In this mode, Wi-Fi will be kept active, 239 * but the only operation that will be supported is initiation of 240 * scans, and the subsequent reporting of scan results. No attempts 241 * will be made to automatically connect to remembered access points, 242 * nor will periodic scans be automatically performed looking for 243 * remembered access points. Scans must be explicitly requested by 244 * an application in this mode. 245 * @hide pending API council review 246 */ 247 public static final int WIFI_MODE_SCAN_ONLY = 2; 248 249 /** Anything worse than or equal to this will show 0 bars. */ 250 private static final int MIN_RSSI = -100; 251 252 /** Anything better than or equal to this will show the max bars. */ 253 private static final int MAX_RSSI = -55; 254 255 IWifiManager mService; 256 Handler mHandler; 257 258 /** 259 * Create a new WifiManager instance. 260 * Applications will almost always want to use 261 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve 262 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. 263 * @param service the Binder interface 264 * @param handler target for messages 265 * @hide - hide this because it takes in a parameter of type IWifiManager, which 266 * is a system private class. 267 */ 268 public WifiManager(IWifiManager service, Handler handler) { 269 mService = service; 270 mHandler = handler; 271 } 272 273 /** 274 * Return a list of all the networks configured in the supplicant. 275 * Not all fields of WifiConfiguration are returned. Only the following 276 * fields are filled in: 277 * <ul> 278 * <li>networkId</li> 279 * <li>SSID</li> 280 * <li>BSSID</li> 281 * <li>priority</li> 282 * <li>allowedProtocols</li> 283 * <li>allowedKeyManagement</li> 284 * <li>allowedAuthAlgorithms</li> 285 * <li>allowedPairwiseCiphers</li> 286 * <li>allowedGroupCiphers</li> 287 * </ul> 288 * @return a list of network configurations in the form of a list 289 * of {@link WifiConfiguration} objects. 290 */ 291 public List<WifiConfiguration> getConfiguredNetworks() { 292 try { 293 return mService.getConfiguredNetworks(); 294 } catch (RemoteException e) { 295 return null; 296 } 297 } 298 299 /** 300 * Add a new network description to the set of configured networks. 301 * The {@code networkId} field of the supplied configuration object 302 * is ignored. 303 * <p/> 304 * The new network will be marked DISABLED by default. To enable it, 305 * called {@link #enableNetwork}. 306 * 307 * @param config the set of variables that describe the configuration, 308 * contained in a {@link WifiConfiguration} object. 309 * @return the ID of the newly created network description. This is used in 310 * other operations to specified the network to be acted upon. 311 * Returns {@code -1} on failure. 312 */ 313 public int addNetwork(WifiConfiguration config) { 314 if (config == null) { 315 return -1; 316 } 317 config.networkId = -1; 318 return addOrUpdateNetwork(config); 319 } 320 321 /** 322 * Update the network description of an existing configured network. 323 * 324 * @param config the set of variables that describe the configuration, 325 * contained in a {@link WifiConfiguration} object. It may 326 * be sparse, so that only the items that are being changed 327 * are non-<code>null</code>. The {@code networkId} field 328 * must be set to the ID of the existing network being updated. 329 * @return Returns the {@code networkId} of the supplied 330 * {@code WifiConfiguration} on success. 331 * <br/> 332 * Returns {@code -1} on failure, including when the {@code networkId} 333 * field of the {@code WifiConfiguration} does not refer to an 334 * existing network. 335 */ 336 public int updateNetwork(WifiConfiguration config) { 337 if (config == null || config.networkId < 0) { 338 return -1; 339 } 340 return addOrUpdateNetwork(config); 341 } 342 343 /** 344 * Internal method for doing the RPC that creates a new network description 345 * or updates an existing one. 346 * 347 * @param config The possibly sparse object containing the variables that 348 * are to set or updated in the network description. 349 * @return the ID of the network on success, {@code -1} on failure. 350 */ 351 private int addOrUpdateNetwork(WifiConfiguration config) { 352 try { 353 return mService.addOrUpdateNetwork(config); 354 } catch (RemoteException e) { 355 return -1; 356 } 357 } 358 359 /** 360 * Remove the specified network from the list of configured networks. 361 * This may result in the asynchronous delivery of state change 362 * events. 363 * @param netId the integer that identifies the network configuration 364 * to the supplicant 365 * @return {@code true} if the operation succeeded 366 */ 367 public boolean removeNetwork(int netId) { 368 try { 369 return mService.removeNetwork(netId); 370 } catch (RemoteException e) { 371 return false; 372 } 373 } 374 375 /** 376 * Allow a previously configured network to be associated with. If 377 * <code>disableOthers</code> is true, then all other configured 378 * networks are disabled, and an attempt to connect to the selected 379 * network is initiated. This may result in the asynchronous delivery 380 * of state change events. 381 * @param netId the ID of the network in the list of configured networks 382 * @param disableOthers if true, disable all other networks. The way to 383 * select a particular network to connect to is specify {@code true} 384 * for this parameter. 385 * @return {@code true} if the operation succeeded 386 */ 387 public boolean enableNetwork(int netId, boolean disableOthers) { 388 try { 389 return mService.enableNetwork(netId, disableOthers); 390 } catch (RemoteException e) { 391 return false; 392 } 393 } 394 395 /** 396 * Disable a configured network. The specified network will not be 397 * a candidate for associating. This may result in the asynchronous 398 * delivery of state change events. 399 * @param netId the ID of the network as returned by {@link #addNetwork}. 400 * @return {@code true} if the operation succeeded 401 */ 402 public boolean disableNetwork(int netId) { 403 try { 404 return mService.disableNetwork(netId); 405 } catch (RemoteException e) { 406 return false; 407 } 408 } 409 410 /** 411 * Disassociate from the currently active access point. This may result 412 * in the asynchronous delivery of state change events. 413 * @return {@code true} if the operation succeeded 414 */ 415 public boolean disconnect() { 416 try { 417 return mService.disconnect(); 418 } catch (RemoteException e) { 419 return false; 420 } 421 } 422 423 /** 424 * Reconnect to the currently active access point, if we are currently 425 * disconnected. This may result in the asynchronous delivery of state 426 * change events. 427 * @return {@code true} if the operation succeeded 428 */ 429 public boolean reconnect() { 430 try { 431 return mService.reconnect(); 432 } catch (RemoteException e) { 433 return false; 434 } 435 } 436 437 /** 438 * Reconnect to the currently active access point, even if we are already 439 * connected. This may result in the asynchronous delivery of state 440 * change events. 441 * @return {@code true} if the operation succeeded 442 */ 443 public boolean reassociate() { 444 try { 445 return mService.reassociate(); 446 } catch (RemoteException e) { 447 return false; 448 } 449 } 450 451 /** 452 * Check that the supplicant daemon is responding to requests. 453 * @return {@code true} if we were able to communicate with the supplicant and 454 * it returned the expected response to the PING message. 455 */ 456 public boolean pingSupplicant() { 457 if (mService == null) 458 return false; 459 try { 460 return mService.pingSupplicant(); 461 } catch (RemoteException e) { 462 return false; 463 } 464 } 465 466 /** 467 * Request a scan for access points. Returns immediately. The availability 468 * of the results is made known later by means of an asynchronous event sent 469 * on completion of the scan. 470 * @return {@code true} if the operation succeeded, i.e., the scan was initiated 471 */ 472 public boolean startScan() { 473 try { 474 return mService.startScan(); 475 } catch (RemoteException e) { 476 return false; 477 } 478 } 479 480 /** 481 * Return dynamic information about the current Wi-Fi connection, if any is active. 482 * @return the Wi-Fi information, contained in {@link WifiInfo}. 483 */ 484 public WifiInfo getConnectionInfo() { 485 try { 486 return mService.getConnectionInfo(); 487 } catch (RemoteException e) { 488 return null; 489 } 490 } 491 492 /** 493 * Return the results of the latest access point scan. 494 * @return the list of access points found in the most recent scan. 495 */ 496 public List<ScanResult> getScanResults() { 497 try { 498 return mService.getScanResults(); 499 } catch (RemoteException e) { 500 return null; 501 } 502 } 503 504 /** 505 * Tell the supplicant to persist the current list of configured networks. 506 * <p> 507 * Note: It is possible for this method to change the network IDs of 508 * existing networks. You should assume the network IDs can be different 509 * after calling this method. 510 * 511 * @return {@code true} if the operation succeeded 512 */ 513 public boolean saveConfiguration() { 514 try { 515 return mService.saveConfiguration(); 516 } catch (RemoteException e) { 517 return false; 518 } 519 } 520 521 /** 522 * Return the number of frequency channels that are allowed 523 * to be used in the current regulatory domain. 524 * @return the number of allowed channels, or {@code -1} if an error occurs 525 * 526 * @hide pending API council 527 */ 528 public int getNumAllowedChannels() { 529 try { 530 return mService.getNumAllowedChannels(); 531 } catch (RemoteException e) { 532 return -1; 533 } 534 } 535 536 /** 537 * Set the number of frequency channels that are allowed to be used 538 * in the current regulatory domain. This method should be used only 539 * if the correct number of channels cannot be determined automatically 540 * for some reason. 541 * @param numChannels the number of allowed channels. Must be greater than 0 542 * and less than or equal to 16. 543 * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g., 544 * {@code numChannels} is out of range. 545 * 546 * @hide pending API council 547 */ 548 public boolean setNumAllowedChannels(int numChannels) { 549 try { 550 return mService.setNumAllowedChannels(numChannels); 551 } catch (RemoteException e) { 552 return false; 553 } 554 } 555 556 /** 557 * Return the list of valid values for the number of allowed radio channels 558 * for various regulatory domains. 559 * @return the list of channel counts, or {@code null} if the operation fails 560 * 561 * @hide pending API council review 562 */ 563 public int[] getValidChannelCounts() { 564 try { 565 return mService.getValidChannelCounts(); 566 } catch (RemoteException e) { 567 return null; 568 } 569 } 570 571 /** 572 * Return the DHCP-assigned addresses from the last successful DHCP request, 573 * if any. 574 * @return the DHCP information 575 */ 576 public DhcpInfo getDhcpInfo() { 577 try { 578 return mService.getDhcpInfo(); 579 } catch (RemoteException e) { 580 return null; 581 } 582 } 583 584 585 /** 586 * Enable or disable Wi-Fi. 587 * @param enabled {@code true} to enable, {@code false} to disable. 588 * @return {@code true} if the operation succeeds (or if the existing state 589 * is the same as the requested state). 590 */ 591 public boolean setWifiEnabled(boolean enabled) { 592 try { 593 return mService.setWifiEnabled(enabled); 594 } catch (RemoteException e) { 595 return false; 596 } 597 } 598 599 /** 600 * Gets the Wi-Fi enabled state. 601 * @return One of {@link #WIFI_STATE_DISABLED}, 602 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 603 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 604 * @see #isWifiEnabled() 605 */ 606 public int getWifiState() { 607 try { 608 return mService.getWifiEnabledState(); 609 } catch (RemoteException e) { 610 return WIFI_STATE_UNKNOWN; 611 } 612 } 613 614 /** 615 * Return whether Wi-Fi is enabled or disabled. 616 * @return {@code true} if Wi-Fi is enabled 617 * @see #getWifiState() 618 */ 619 public boolean isWifiEnabled() { 620 return getWifiState() == WIFI_STATE_ENABLED; 621 } 622 623 /** 624 * Calculates the level of the signal. This should be used any time a signal 625 * is being shown. 626 * 627 * @param rssi The power of the signal measured in RSSI. 628 * @param numLevels The number of levels to consider in the calculated 629 * level. 630 * @return A level of the signal, given in the range of 0 to numLevels-1 631 * (both inclusive). 632 */ 633 public static int calculateSignalLevel(int rssi, int numLevels) { 634 if (rssi <= MIN_RSSI) { 635 return 0; 636 } else if (rssi >= MAX_RSSI) { 637 return numLevels - 1; 638 } else { 639 int partitionSize = (MAX_RSSI - MIN_RSSI) / (numLevels - 1); 640 return (rssi - MIN_RSSI) / partitionSize; 641 } 642 } 643 644 /** 645 * Compares two signal strengths. 646 * 647 * @param rssiA The power of the first signal measured in RSSI. 648 * @param rssiB The power of the second signal measured in RSSI. 649 * @return Returns <0 if the first signal is weaker than the second signal, 650 * 0 if the two signals have the same strength, and >0 if the first 651 * signal is stronger than the second signal. 652 */ 653 public static int compareSignalLevel(int rssiA, int rssiB) { 654 return rssiA - rssiB; 655 } 656 657 /** 658 * Allows an application to keep the Wi-Fi radio awake. 659 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 660 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 661 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 662 * WifiLocks are held in any application. 663 * 664 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 665 * could function over a mobile network, if available. A program that needs to download large 666 * files should hold a WifiLock to ensure that the download will complete, but a program whose 667 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 668 * affecting battery life. 669 * 670 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 671 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 672 * is idle. 673 */ 674 public class WifiLock { 675 private String mTag; 676 private final IBinder mBinder; 677 private int mRefCount; 678 int mLockType; 679 private boolean mRefCounted; 680 private boolean mHeld; 681 682 private WifiLock(int lockType, String tag) { 683 mTag = tag; 684 mLockType = lockType; 685 mBinder = new Binder(); 686 mRefCount = 0; 687 mRefCounted = true; 688 mHeld = false; 689 } 690 691 /** 692 * Locks the Wi-Fi radio on until {@link #release} is called. 693 * 694 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 695 * reference count, and the radio will remain locked as long as the reference count is 696 * above zero. 697 * 698 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 699 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 700 * will be required, regardless of the number of times that {@code acquire} is called. 701 */ 702 public void acquire() { 703 synchronized (mBinder) { 704 if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) { 705 try { 706 mService.acquireWifiLock(mBinder, mLockType, mTag); 707 } catch (RemoteException ignore) { 708 } 709 mHeld = true; 710 } 711 } 712 } 713 714 /** 715 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 716 * 717 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 718 * reference count, and the radio will be unlocked only when the reference count reaches 719 * zero. If the reference count goes below zero (that is, if {@code release} is called 720 * a greater number of times than {@link #acquire}), an exception is thrown. 721 * 722 * If this WifiLock is not reference-counted, the first call to {@code release} (after 723 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 724 * calls will be ignored. 725 */ 726 public void release() { 727 synchronized (mBinder) { 728 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 729 try { 730 mService.releaseWifiLock(mBinder); 731 } catch (RemoteException ignore) { 732 } 733 mHeld = false; 734 } 735 if (mRefCount < 0) { 736 throw new RuntimeException("WifiLock under-locked " + mTag); 737 } 738 } 739 } 740 741 /** 742 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 743 * 744 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 745 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 746 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 747 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 748 * radio whenever {@link #release} is called and it is locked. 749 * 750 * @param refCounted true if this WifiLock should keep a reference count 751 */ 752 public void setReferenceCounted(boolean refCounted) { 753 mRefCounted = refCounted; 754 } 755 756 /** 757 * Checks whether this WifiLock is currently held. 758 * 759 * @return true if this WifiLock is held, false otherwise 760 */ 761 public boolean isHeld() { 762 synchronized (mBinder) { 763 return mHeld; 764 } 765 } 766 767 public String toString() { 768 String s1, s2, s3; 769 synchronized (mBinder) { 770 s1 = Integer.toHexString(System.identityHashCode(this)); 771 s2 = mHeld ? "held; " : ""; 772 if (mRefCounted) { 773 s3 = "refcounted: refcount = " + mRefCount; 774 } else { 775 s3 = "not refcounted"; 776 } 777 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 778 } 779 } 780 781 @Override 782 protected void finalize() throws Throwable { 783 super.finalize(); 784 synchronized (mBinder) { 785 if (mHeld) { 786 try { 787 mService.releaseWifiLock(mBinder); 788 } catch (RemoteException ignore) { 789 } 790 } 791 } 792 } 793 } 794 795 /** 796 * Creates a new WifiLock. 797 * 798 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL} and 799 * {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks. 800 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 801 * never shown to the user under normal conditions, but should be descriptive 802 * enough to identify your application and the specific WifiLock within it, if it 803 * holds multiple WifiLocks. 804 * 805 * @return a new, unacquired WifiLock with the given tag. 806 * 807 * @see WifiLock 808 * 809 * @hide pending API council review 810 */ 811 public WifiLock createWifiLock(int lockType, String tag) { 812 return new WifiLock(lockType, tag); 813 } 814 815 /** 816 * Creates a new WifiLock. 817 * 818 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 819 * never shown to the user under normal conditions, but should be descriptive 820 * enough to identify your application and the specific WifiLock within it, if it 821 * holds multiple WifiLocks. 822 * 823 * @return a new, unacquired WifiLock with the given tag. 824 * 825 * @see WifiLock 826 */ 827 public WifiLock createWifiLock(String tag) { 828 return new WifiLock(WIFI_MODE_FULL, tag); 829 } 830} 831