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