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