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