WifiManager.java revision b5010cc3c33c74cc406a70f34f93d330a3f0db6a
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 * @param persist {@code true} if you want this remembered 542 * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g., 543 * {@code numChannels} is out of range. 544 * 545 * @hide pending API council 546 */ 547 public boolean setNumAllowedChannels(int numChannels, boolean persist) { 548 try { 549 return mService.setNumAllowedChannels(numChannels, persist); 550 } catch (RemoteException e) { 551 return false; 552 } 553 } 554 555 /** 556 * Return the list of valid values for the number of allowed radio channels 557 * for various regulatory domains. 558 * @return the list of channel counts, or {@code null} if the operation fails 559 * 560 * @hide pending API council review 561 */ 562 public int[] getValidChannelCounts() { 563 try { 564 return mService.getValidChannelCounts(); 565 } catch (RemoteException e) { 566 return null; 567 } 568 } 569 570 /** 571 * Return the DHCP-assigned addresses from the last successful DHCP request, 572 * if any. 573 * @return the DHCP information 574 */ 575 public DhcpInfo getDhcpInfo() { 576 try { 577 return mService.getDhcpInfo(); 578 } catch (RemoteException e) { 579 return null; 580 } 581 } 582 583 584 /** 585 * Enable or disable Wi-Fi. 586 * @param enabled {@code true} to enable, {@code false} to disable. 587 * @return {@code true} if the operation succeeds (or if the existing state 588 * is the same as the requested state). 589 */ 590 public boolean setWifiEnabled(boolean enabled) { 591 try { 592 return mService.setWifiEnabled(enabled); 593 } catch (RemoteException e) { 594 return false; 595 } 596 } 597 598 /** 599 * Gets the Wi-Fi enabled state. 600 * @return One of {@link #WIFI_STATE_DISABLED}, 601 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 602 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 603 * @see #isWifiEnabled() 604 */ 605 public int getWifiState() { 606 try { 607 return mService.getWifiEnabledState(); 608 } catch (RemoteException e) { 609 return WIFI_STATE_UNKNOWN; 610 } 611 } 612 613 /** 614 * Return whether Wi-Fi is enabled or disabled. 615 * @return {@code true} if Wi-Fi is enabled 616 * @see #getWifiState() 617 */ 618 public boolean isWifiEnabled() { 619 return getWifiState() == WIFI_STATE_ENABLED; 620 } 621 622 /** 623 * Calculates the level of the signal. This should be used any time a signal 624 * is being shown. 625 * 626 * @param rssi The power of the signal measured in RSSI. 627 * @param numLevels The number of levels to consider in the calculated 628 * level. 629 * @return A level of the signal, given in the range of 0 to numLevels-1 630 * (both inclusive). 631 */ 632 public static int calculateSignalLevel(int rssi, int numLevels) { 633 if (rssi <= MIN_RSSI) { 634 return 0; 635 } else if (rssi >= MAX_RSSI) { 636 return numLevels - 1; 637 } else { 638 int partitionSize = (MAX_RSSI - MIN_RSSI) / (numLevels - 1); 639 return (rssi - MIN_RSSI) / partitionSize; 640 } 641 } 642 643 /** 644 * Compares two signal strengths. 645 * 646 * @param rssiA The power of the first signal measured in RSSI. 647 * @param rssiB The power of the second signal measured in RSSI. 648 * @return Returns <0 if the first signal is weaker than the second signal, 649 * 0 if the two signals have the same strength, and >0 if the first 650 * signal is stronger than the second signal. 651 */ 652 public static int compareSignalLevel(int rssiA, int rssiB) { 653 return rssiA - rssiB; 654 } 655 656 /** 657 * Allows an application to keep the Wi-Fi radio awake. 658 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 659 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 660 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 661 * WifiLocks are held in any application. 662 * 663 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 664 * could function over a mobile network, if available. A program that needs to download large 665 * files should hold a WifiLock to ensure that the download will complete, but a program whose 666 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 667 * affecting battery life. 668 * 669 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 670 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 671 * is idle. 672 */ 673 public class WifiLock { 674 private String mTag; 675 private final IBinder mBinder; 676 private int mRefCount; 677 int mLockType; 678 private boolean mRefCounted; 679 private boolean mHeld; 680 681 private WifiLock(int lockType, String tag) { 682 mTag = tag; 683 mLockType = lockType; 684 mBinder = new Binder(); 685 mRefCount = 0; 686 mRefCounted = true; 687 mHeld = false; 688 } 689 690 /** 691 * Locks the Wi-Fi radio on until {@link #release} is called. 692 * 693 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 694 * reference count, and the radio will remain locked as long as the reference count is 695 * above zero. 696 * 697 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 698 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 699 * will be required, regardless of the number of times that {@code acquire} is called. 700 */ 701 public void acquire() { 702 synchronized (mBinder) { 703 if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) { 704 try { 705 mService.acquireWifiLock(mBinder, mLockType, mTag); 706 } catch (RemoteException ignore) { 707 } 708 mHeld = true; 709 } 710 } 711 } 712 713 /** 714 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 715 * 716 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 717 * reference count, and the radio will be unlocked only when the reference count reaches 718 * zero. If the reference count goes below zero (that is, if {@code release} is called 719 * a greater number of times than {@link #acquire}), an exception is thrown. 720 * 721 * If this WifiLock is not reference-counted, the first call to {@code release} (after 722 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 723 * calls will be ignored. 724 */ 725 public void release() { 726 synchronized (mBinder) { 727 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 728 try { 729 mService.releaseWifiLock(mBinder); 730 } catch (RemoteException ignore) { 731 } 732 mHeld = false; 733 } 734 if (mRefCount < 0) { 735 throw new RuntimeException("WifiLock under-locked " + mTag); 736 } 737 } 738 } 739 740 /** 741 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 742 * 743 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 744 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 745 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 746 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 747 * radio whenever {@link #release} is called and it is locked. 748 * 749 * @param refCounted true if this WifiLock should keep a reference count 750 */ 751 public void setReferenceCounted(boolean refCounted) { 752 mRefCounted = refCounted; 753 } 754 755 /** 756 * Checks whether this WifiLock is currently held. 757 * 758 * @return true if this WifiLock is held, false otherwise 759 */ 760 public boolean isHeld() { 761 synchronized (mBinder) { 762 return mHeld; 763 } 764 } 765 766 public String toString() { 767 String s1, s2, s3; 768 synchronized (mBinder) { 769 s1 = Integer.toHexString(System.identityHashCode(this)); 770 s2 = mHeld ? "held; " : ""; 771 if (mRefCounted) { 772 s3 = "refcounted: refcount = " + mRefCount; 773 } else { 774 s3 = "not refcounted"; 775 } 776 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 777 } 778 } 779 780 @Override 781 protected void finalize() throws Throwable { 782 super.finalize(); 783 synchronized (mBinder) { 784 if (mHeld) { 785 try { 786 mService.releaseWifiLock(mBinder); 787 } catch (RemoteException ignore) { 788 } 789 } 790 } 791 } 792 } 793 794 /** 795 * Creates a new WifiLock. 796 * 797 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL} and 798 * {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks. 799 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 800 * never shown to the user under normal conditions, but should be descriptive 801 * enough to identify your application and the specific WifiLock within it, if it 802 * holds multiple WifiLocks. 803 * 804 * @return a new, unacquired WifiLock with the given tag. 805 * 806 * @see WifiLock 807 */ 808 public WifiLock createWifiLock(int lockType, String tag) { 809 return new WifiLock(lockType, tag); 810 } 811 812 /** 813 * Creates a new WifiLock. 814 * 815 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 816 * never shown to the user under normal conditions, but should be descriptive 817 * enough to identify your application and the specific WifiLock within it, if it 818 * holds multiple WifiLocks. 819 * 820 * @return a new, unacquired WifiLock with the given tag. 821 * 822 * @see WifiLock 823 */ 824 public WifiLock createWifiLock(String tag) { 825 return new WifiLock(WIFI_MODE_FULL, tag); 826 } 827 828 /** 829 * Check multicast filter status. 830 * 831 * @return true if multicast packets are allowed. 832 * 833 * @hide pending API council approval 834 */ 835 public boolean isMulticastEnabled() { 836 try { 837 return mService.isMulticastEnabled(); 838 } catch (RemoteException e) { 839 return false; 840 } 841 } 842 843 /** 844 * Turn on the reception of multicast packets. 845 * The default behavior is to disable multicast packets as they 846 * have a noticable negative effect on battery life. An 847 * application can turn them on, but should not leave it on for longer 848 * than needed. When the app quits (or crashes) its request will 849 * be reverted. 850 * 851 * @param tag a string associated with this request for debugging. 852 * 853 * @return true on success 854 * 855 * @see #disableMulticast 856 * 857 * @hide pending API council approval 858 */ 859 public boolean enableMulticast(String tag) { 860 try { 861 mService.enableMulticast(new Binder(), tag); 862 return true; 863 } catch (RemoteException e) { 864 return false; 865 } 866 } 867 868 /** 869 * Return to the default multicast-off setting. 870 * Note that if others had turned on Multicast reception, your 871 * call will not turn it back off - they must also turn off their 872 * request for multicast reception. 873 * 874 * @return true on success 875 * 876 * @see #enableMulticast 877 * 878 * @hide pending API council approval 879 */ 880 public boolean disableMulticast() { 881 try { 882 mService.disableMulticast(); 883 return true; 884 } catch (RemoteException e) { 885 return false; 886 } 887 } 888} 889