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