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