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