WifiManager.java revision f5af4a972598611c46d4bf169919e23b7375a5a9
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.net.wifi.ScanSettings; 24import android.net.wifi.WifiChannel; 25import android.os.Binder; 26import android.os.IBinder; 27import android.os.Handler; 28import android.os.HandlerThread; 29import android.os.Looper; 30import android.os.Message; 31import android.os.RemoteException; 32import android.os.WorkSource; 33import android.os.Messenger; 34import android.util.Log; 35import android.util.SparseArray; 36 37import java.net.InetAddress; 38import java.util.concurrent.CountDownLatch; 39 40import com.android.internal.util.AsyncChannel; 41import com.android.internal.util.Protocol; 42 43import java.util.List; 44 45/** 46 * This class provides the primary API for managing all aspects of Wi-Fi 47 * connectivity. Get an instance of this class by calling 48 * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}. 49 50 * It deals with several categories of items: 51 * <ul> 52 * <li>The list of configured networks. The list can be viewed and updated, 53 * and attributes of individual entries can be modified.</li> 54 * <li>The currently active Wi-Fi network, if any. Connectivity can be 55 * established or torn down, and dynamic information about the state of 56 * the network can be queried.</li> 57 * <li>Results of access point scans, containing enough information to 58 * make decisions about what access point to connect to.</li> 59 * <li>It defines the names of various Intent actions that are broadcast 60 * upon any sort of change in Wi-Fi state. 61 * </ul> 62 * This is the API to use when performing Wi-Fi specific operations. To 63 * perform operations that pertain to network connectivity at an abstract 64 * level, use {@link android.net.ConnectivityManager}. 65 */ 66public class WifiManager { 67 68 private static final String TAG = "WifiManager"; 69 // Supplicant error codes: 70 /** 71 * The error code if there was a problem authenticating. 72 */ 73 public static final int ERROR_AUTHENTICATING = 1; 74 75 /** 76 * Broadcast intent action indicating whether Wi-Fi scanning is allowed currently 77 * @hide 78 */ 79 public static final String WIFI_SCAN_AVAILABLE = "wifi_scan_available"; 80 81 /** 82 * Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED 83 * @hide 84 */ 85 public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled"; 86 87 /** 88 * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, 89 * enabling, disabling, or unknown. One extra provides this state as an int. 90 * Another extra provides the previous state, if available. 91 * 92 * @see #EXTRA_WIFI_STATE 93 * @see #EXTRA_PREVIOUS_WIFI_STATE 94 */ 95 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 96 public static final String WIFI_STATE_CHANGED_ACTION = 97 "android.net.wifi.WIFI_STATE_CHANGED"; 98 /** 99 * The lookup key for an int that indicates whether Wi-Fi is enabled, 100 * disabled, enabling, disabling, or unknown. Retrieve it with 101 * {@link android.content.Intent#getIntExtra(String,int)}. 102 * 103 * @see #WIFI_STATE_DISABLED 104 * @see #WIFI_STATE_DISABLING 105 * @see #WIFI_STATE_ENABLED 106 * @see #WIFI_STATE_ENABLING 107 * @see #WIFI_STATE_UNKNOWN 108 */ 109 public static final String EXTRA_WIFI_STATE = "wifi_state"; 110 /** 111 * The previous Wi-Fi state. 112 * 113 * @see #EXTRA_WIFI_STATE 114 */ 115 public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; 116 117 /** 118 * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if 119 * it finishes successfully. 120 * 121 * @see #WIFI_STATE_CHANGED_ACTION 122 * @see #getWifiState() 123 */ 124 public static final int WIFI_STATE_DISABLING = 0; 125 /** 126 * Wi-Fi is disabled. 127 * 128 * @see #WIFI_STATE_CHANGED_ACTION 129 * @see #getWifiState() 130 */ 131 public static final int WIFI_STATE_DISABLED = 1; 132 /** 133 * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if 134 * it finishes successfully. 135 * 136 * @see #WIFI_STATE_CHANGED_ACTION 137 * @see #getWifiState() 138 */ 139 public static final int WIFI_STATE_ENABLING = 2; 140 /** 141 * Wi-Fi is enabled. 142 * 143 * @see #WIFI_STATE_CHANGED_ACTION 144 * @see #getWifiState() 145 */ 146 public static final int WIFI_STATE_ENABLED = 3; 147 /** 148 * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling 149 * or disabling. 150 * 151 * @see #WIFI_STATE_CHANGED_ACTION 152 * @see #getWifiState() 153 */ 154 public static final int WIFI_STATE_UNKNOWN = 4; 155 156 /** 157 * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled, 158 * enabling, disabling, or failed. 159 * 160 * @hide 161 */ 162 public static final String WIFI_AP_STATE_CHANGED_ACTION = 163 "android.net.wifi.WIFI_AP_STATE_CHANGED"; 164 165 /** 166 * The lookup key for an int that indicates whether Wi-Fi AP is enabled, 167 * disabled, enabling, disabling, or failed. Retrieve it with 168 * {@link android.content.Intent#getIntExtra(String,int)}. 169 * 170 * @see #WIFI_AP_STATE_DISABLED 171 * @see #WIFI_AP_STATE_DISABLING 172 * @see #WIFI_AP_STATE_ENABLED 173 * @see #WIFI_AP_STATE_ENABLING 174 * @see #WIFI_AP_STATE_FAILED 175 * 176 * @hide 177 */ 178 public static final String EXTRA_WIFI_AP_STATE = "wifi_state"; 179 /** 180 * The previous Wi-Fi state. 181 * 182 * @see #EXTRA_WIFI_AP_STATE 183 * 184 * @hide 185 */ 186 public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; 187 /** 188 * Wi-Fi AP is currently being disabled. The state will change to 189 * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully. 190 * 191 * @see #WIFI_AP_STATE_CHANGED_ACTION 192 * @see #getWifiApState() 193 * 194 * @hide 195 */ 196 public static final int WIFI_AP_STATE_DISABLING = 10; 197 /** 198 * Wi-Fi AP is disabled. 199 * 200 * @see #WIFI_AP_STATE_CHANGED_ACTION 201 * @see #getWifiState() 202 * 203 * @hide 204 */ 205 public static final int WIFI_AP_STATE_DISABLED = 11; 206 /** 207 * Wi-Fi AP is currently being enabled. The state will change to 208 * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully. 209 * 210 * @see #WIFI_AP_STATE_CHANGED_ACTION 211 * @see #getWifiApState() 212 * 213 * @hide 214 */ 215 public static final int WIFI_AP_STATE_ENABLING = 12; 216 /** 217 * Wi-Fi AP is enabled. 218 * 219 * @see #WIFI_AP_STATE_CHANGED_ACTION 220 * @see #getWifiApState() 221 * 222 * @hide 223 */ 224 public static final int WIFI_AP_STATE_ENABLED = 13; 225 /** 226 * Wi-Fi AP is in a failed state. This state will occur when an error occurs during 227 * enabling or disabling 228 * 229 * @see #WIFI_AP_STATE_CHANGED_ACTION 230 * @see #getWifiApState() 231 * 232 * @hide 233 */ 234 public static final int WIFI_AP_STATE_FAILED = 14; 235 236 /** 237 * Broadcast intent action indicating that a connection to the supplicant has 238 * been established (and it is now possible 239 * to perform Wi-Fi operations) or the connection to the supplicant has been 240 * lost. One extra provides the connection state as a boolean, where {@code true} 241 * means CONNECTED. 242 * @see #EXTRA_SUPPLICANT_CONNECTED 243 */ 244 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 245 public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = 246 "android.net.wifi.supplicant.CONNECTION_CHANGE"; 247 /** 248 * The lookup key for a boolean that indicates whether a connection to 249 * the supplicant daemon has been gained or lost. {@code true} means 250 * a connection now exists. 251 * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. 252 */ 253 public static final String EXTRA_SUPPLICANT_CONNECTED = "connected"; 254 /** 255 * Broadcast intent action indicating that the state of Wi-Fi connectivity 256 * has changed. One extra provides the new state 257 * in the form of a {@link android.net.NetworkInfo} object. If the new 258 * state is CONNECTED, additional extras may provide the BSSID and WifiInfo of 259 * the access point. 260 * as a {@code String}. 261 * @see #EXTRA_NETWORK_INFO 262 * @see #EXTRA_BSSID 263 * @see #EXTRA_WIFI_INFO 264 */ 265 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 266 public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"; 267 /** 268 * The lookup key for a {@link android.net.NetworkInfo} object associated with the 269 * Wi-Fi network. Retrieve with 270 * {@link android.content.Intent#getParcelableExtra(String)}. 271 */ 272 public static final String EXTRA_NETWORK_INFO = "networkInfo"; 273 /** 274 * The lookup key for a String giving the BSSID of the access point to which 275 * we are connected. Only present when the new state is CONNECTED. 276 * Retrieve with 277 * {@link android.content.Intent#getStringExtra(String)}. 278 */ 279 public static final String EXTRA_BSSID = "bssid"; 280 /** 281 * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the 282 * information about the access point to which we are connected. Only present 283 * when the new state is CONNECTED. Retrieve with 284 * {@link android.content.Intent#getParcelableExtra(String)}. 285 */ 286 public static final String EXTRA_WIFI_INFO = "wifiInfo"; 287 /** 288 * Broadcast intent action indicating that the state of establishing a connection to 289 * an access point has changed.One extra provides the new 290 * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and 291 * is not generally the most useful thing to look at if you are just interested in 292 * the overall state of connectivity. 293 * @see #EXTRA_NEW_STATE 294 * @see #EXTRA_SUPPLICANT_ERROR 295 */ 296 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 297 public static final String SUPPLICANT_STATE_CHANGED_ACTION = 298 "android.net.wifi.supplicant.STATE_CHANGE"; 299 /** 300 * The lookup key for a {@link SupplicantState} describing the new state 301 * Retrieve with 302 * {@link android.content.Intent#getParcelableExtra(String)}. 303 */ 304 public static final String EXTRA_NEW_STATE = "newState"; 305 306 /** 307 * The lookup key for a {@link SupplicantState} describing the supplicant 308 * error code if any 309 * Retrieve with 310 * {@link android.content.Intent#getIntExtra(String, int)}. 311 * @see #ERROR_AUTHENTICATING 312 */ 313 public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; 314 315 /** 316 * Broadcast intent action indicating that the configured networks changed. 317 * This can be as a result of adding/updating/deleting a network. If 318 * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration 319 * can be retreived with the {@link #EXTRA_WIFI_CONFIGURATION} extra. If multiple 320 * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present. 321 * @hide 322 */ 323 public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = 324 "android.net.wifi.CONFIGURED_NETWORKS_CHANGE"; 325 /** 326 * The lookup key for a (@link android.net.wifi.WifiConfiguration} object representing 327 * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION} 328 * broadcast is sent. 329 * @hide 330 */ 331 public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; 332 /** 333 * Multiple network configurations have changed. 334 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 335 * 336 * @hide 337 */ 338 public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges"; 339 /** 340 * The lookup key for an integer indicating the reason a Wi-Fi network configuration 341 * has changed. Only present if {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is {@code false} 342 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 343 * @hide 344 */ 345 public static final String EXTRA_CHANGE_REASON = "changeReason"; 346 /** 347 * The configuration is new and was added. 348 * @hide 349 */ 350 public static final int CHANGE_REASON_ADDED = 0; 351 /** 352 * The configuration was removed and is no longer present in the system's list of 353 * configured networks. 354 * @hide 355 */ 356 public static final int CHANGE_REASON_REMOVED = 1; 357 /** 358 * The configuration has changed as a result of explicit action or because the system 359 * took an automated action such as disabling a malfunctioning configuration. 360 * @hide 361 */ 362 public static final int CHANGE_REASON_CONFIG_CHANGE = 2; 363 /** 364 * An access point scan has completed, and results are available from the supplicant. 365 * Call {@link #getScanResults()} to obtain the results. 366 */ 367 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 368 public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; 369 /** 370 * A batch of access point scans has been completed and the results areavailable. 371 * Call {@link #getBatchedScanResults()} to obtain the results. 372 * @hide pending review 373 */ 374 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 375 public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION = 376 "android.net.wifi.BATCHED_RESULTS"; 377 /** 378 * The RSSI (signal strength) has changed. 379 * @see #EXTRA_NEW_RSSI 380 */ 381 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 382 public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; 383 /** 384 * The lookup key for an {@code int} giving the new RSSI in dBm. 385 */ 386 public static final String EXTRA_NEW_RSSI = "newRssi"; 387 388 /** 389 * Broadcast intent action indicating that the link configuration 390 * changed on wifi. 391 * @hide 392 */ 393 public static final String LINK_CONFIGURATION_CHANGED_ACTION = 394 "android.net.wifi.LINK_CONFIGURATION_CHANGED"; 395 396 /** 397 * The lookup key for a {@link android.net.LinkProperties} object associated with the 398 * Wi-Fi network. Retrieve with 399 * {@link android.content.Intent#getParcelableExtra(String)}. 400 * @hide 401 */ 402 public static final String EXTRA_LINK_PROPERTIES = "linkProperties"; 403 404 /** 405 * The lookup key for a {@link android.net.NetworkCapabilities} object associated with the 406 * Wi-Fi network. Retrieve with 407 * {@link android.content.Intent#getParcelableExtra(String)}. 408 * @hide 409 */ 410 public static final String EXTRA_NETWORK_CAPABILITIES = "networkCapabilities"; 411 412 /** 413 * The network IDs of the configured networks could have changed. 414 */ 415 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 416 public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; 417 418 /** 419 * Activity Action: Show a system activity that allows the user to enable 420 * scans to be available even with Wi-Fi turned off. 421 * 422 * <p>Notification of the result of this activity is posted using the 423 * {@link android.app.Activity#onActivityResult} callback. The 424 * <code>resultCode</code> 425 * will be {@link android.app.Activity#RESULT_OK} if scan always mode has 426 * been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user 427 * has rejected the request or an error has occurred. 428 */ 429 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 430 public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = 431 "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; 432 433 /** 434 * Activity Action: Pick a Wi-Fi network to connect to. 435 * <p>Input: Nothing. 436 * <p>Output: Nothing. 437 */ 438 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 439 public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; 440 441 /** 442 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 443 * and will behave normally, i.e., it will attempt to automatically 444 * establish a connection to a remembered access point that is 445 * within range, and will do periodic scans if there are remembered 446 * access points but none are in range. 447 */ 448 public static final int WIFI_MODE_FULL = 1; 449 /** 450 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 451 * but the only operation that will be supported is initiation of 452 * scans, and the subsequent reporting of scan results. No attempts 453 * will be made to automatically connect to remembered access points, 454 * nor will periodic scans be automatically performed looking for 455 * remembered access points. Scans must be explicitly requested by 456 * an application in this mode. 457 */ 458 public static final int WIFI_MODE_SCAN_ONLY = 2; 459 /** 460 * In this Wi-Fi lock mode, Wi-Fi will be kept active as in mode 461 * {@link #WIFI_MODE_FULL} but it operates at high performance 462 * with minimum packet loss and low packet latency even when 463 * the device screen is off. This mode will consume more power 464 * and hence should be used only when there is a need for such 465 * an active connection. 466 * <p> 467 * An example use case is when a voice connection needs to be 468 * kept active even after the device screen goes off. Holding the 469 * regular {@link #WIFI_MODE_FULL} lock will keep the wifi 470 * connection active, but the connection can be lossy. 471 * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the 472 * duration of the voice call will improve the call quality. 473 * <p> 474 * When there is no support from the hardware, this lock mode 475 * will have the same behavior as {@link #WIFI_MODE_FULL} 476 */ 477 public static final int WIFI_MODE_FULL_HIGH_PERF = 3; 478 479 /** Anything worse than or equal to this will show 0 bars. */ 480 private static final int MIN_RSSI = -100; 481 482 /** Anything better than or equal to this will show the max bars. */ 483 private static final int MAX_RSSI = -55; 484 485 /** 486 * Number of RSSI levels used in the framework to initiate 487 * {@link #RSSI_CHANGED_ACTION} broadcast 488 * @hide 489 */ 490 public static final int RSSI_LEVELS = 5; 491 492 /** 493 * Auto settings in the driver. The driver could choose to operate on both 494 * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band. 495 * @hide 496 */ 497 public static final int WIFI_FREQUENCY_BAND_AUTO = 0; 498 499 /** 500 * Operation on 5 GHz alone 501 * @hide 502 */ 503 public static final int WIFI_FREQUENCY_BAND_5GHZ = 1; 504 505 /** 506 * Operation on 2.4 GHz alone 507 * @hide 508 */ 509 public static final int WIFI_FREQUENCY_BAND_2GHZ = 2; 510 511 /** List of asyncronous notifications 512 * @hide 513 */ 514 public static final int DATA_ACTIVITY_NOTIFICATION = 1; 515 516 //Lowest bit indicates data reception and the second lowest 517 //bit indicates data transmitted 518 /** @hide */ 519 public static final int DATA_ACTIVITY_NONE = 0x00; 520 /** @hide */ 521 public static final int DATA_ACTIVITY_IN = 0x01; 522 /** @hide */ 523 public static final int DATA_ACTIVITY_OUT = 0x02; 524 /** @hide */ 525 public static final int DATA_ACTIVITY_INOUT = 0x03; 526 527 /** @hide */ 528 public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false; 529 530 /* Maximum number of active locks we allow. 531 * This limit was added to prevent apps from creating a ridiculous number 532 * of locks and crashing the system by overflowing the global ref table. 533 */ 534 private static final int MAX_ACTIVE_LOCKS = 50; 535 536 /* Number of currently active WifiLocks and MulticastLocks */ 537 private int mActiveLockCount; 538 539 private Context mContext; 540 IWifiManager mService; 541 542 private static final int INVALID_KEY = 0; 543 private static int sListenerKey = 1; 544 private static final SparseArray sListenerMap = new SparseArray(); 545 private static final Object sListenerMapLock = new Object(); 546 547 private static AsyncChannel sAsyncChannel; 548 private static CountDownLatch sConnected; 549 550 private static final Object sThreadRefLock = new Object(); 551 private static int sThreadRefCount; 552 private static HandlerThread sHandlerThread; 553 554 /** 555 * Create a new WifiManager instance. 556 * Applications will almost always want to use 557 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve 558 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. 559 * @param context the application context 560 * @param service the Binder interface 561 * @hide - hide this because it takes in a parameter of type IWifiManager, which 562 * is a system private class. 563 */ 564 public WifiManager(Context context, IWifiManager service) { 565 mContext = context; 566 mService = service; 567 init(); 568 } 569 570 /** 571 * Return a list of all the networks configured in the supplicant. 572 * Not all fields of WifiConfiguration are returned. Only the following 573 * fields are filled in: 574 * <ul> 575 * <li>networkId</li> 576 * <li>SSID</li> 577 * <li>BSSID</li> 578 * <li>priority</li> 579 * <li>allowedProtocols</li> 580 * <li>allowedKeyManagement</li> 581 * <li>allowedAuthAlgorithms</li> 582 * <li>allowedPairwiseCiphers</li> 583 * <li>allowedGroupCiphers</li> 584 * </ul> 585 * @return a list of network configurations in the form of a list 586 * of {@link WifiConfiguration} objects. Upon failure to fetch or 587 * when when Wi-Fi is turned off, it can be null. 588 */ 589 public List<WifiConfiguration> getConfiguredNetworks() { 590 try { 591 return mService.getConfiguredNetworks(); 592 } catch (RemoteException e) { 593 return null; 594 } 595 } 596 597 /** 598 * Add a new network description to the set of configured networks. 599 * The {@code networkId} field of the supplied configuration object 600 * is ignored. 601 * <p/> 602 * The new network will be marked DISABLED by default. To enable it, 603 * called {@link #enableNetwork}. 604 * 605 * @param config the set of variables that describe the configuration, 606 * contained in a {@link WifiConfiguration} object. 607 * @return the ID of the newly created network description. This is used in 608 * other operations to specified the network to be acted upon. 609 * Returns {@code -1} on failure. 610 */ 611 public int addNetwork(WifiConfiguration config) { 612 if (config == null) { 613 return -1; 614 } 615 config.networkId = -1; 616 return addOrUpdateNetwork(config); 617 } 618 619 /** 620 * Update the network description of an existing configured network. 621 * 622 * @param config the set of variables that describe the configuration, 623 * contained in a {@link WifiConfiguration} object. It may 624 * be sparse, so that only the items that are being changed 625 * are non-<code>null</code>. The {@code networkId} field 626 * must be set to the ID of the existing network being updated. 627 * @return Returns the {@code networkId} of the supplied 628 * {@code WifiConfiguration} on success. 629 * <br/> 630 * Returns {@code -1} on failure, including when the {@code networkId} 631 * field of the {@code WifiConfiguration} does not refer to an 632 * existing network. 633 */ 634 public int updateNetwork(WifiConfiguration config) { 635 if (config == null || config.networkId < 0) { 636 return -1; 637 } 638 return addOrUpdateNetwork(config); 639 } 640 641 /** 642 * Internal method for doing the RPC that creates a new network description 643 * or updates an existing one. 644 * 645 * @param config The possibly sparse object containing the variables that 646 * are to set or updated in the network description. 647 * @return the ID of the network on success, {@code -1} on failure. 648 */ 649 private int addOrUpdateNetwork(WifiConfiguration config) { 650 try { 651 return mService.addOrUpdateNetwork(config); 652 } catch (RemoteException e) { 653 return -1; 654 } 655 } 656 657 /** 658 * Remove the specified network from the list of configured networks. 659 * This may result in the asynchronous delivery of state change 660 * events. 661 * @param netId the integer that identifies the network configuration 662 * to the supplicant 663 * @return {@code true} if the operation succeeded 664 */ 665 public boolean removeNetwork(int netId) { 666 try { 667 return mService.removeNetwork(netId); 668 } catch (RemoteException e) { 669 return false; 670 } 671 } 672 673 /** 674 * Allow a previously configured network to be associated with. If 675 * <code>disableOthers</code> is true, then all other configured 676 * networks are disabled, and an attempt to connect to the selected 677 * network is initiated. This may result in the asynchronous delivery 678 * of state change events. 679 * @param netId the ID of the network in the list of configured networks 680 * @param disableOthers if true, disable all other networks. The way to 681 * select a particular network to connect to is specify {@code true} 682 * for this parameter. 683 * @return {@code true} if the operation succeeded 684 */ 685 public boolean enableNetwork(int netId, boolean disableOthers) { 686 try { 687 return mService.enableNetwork(netId, disableOthers); 688 } catch (RemoteException e) { 689 return false; 690 } 691 } 692 693 /** 694 * Disable a configured network. The specified network will not be 695 * a candidate for associating. This may result in the asynchronous 696 * delivery of state change events. 697 * @param netId the ID of the network as returned by {@link #addNetwork}. 698 * @return {@code true} if the operation succeeded 699 */ 700 public boolean disableNetwork(int netId) { 701 try { 702 return mService.disableNetwork(netId); 703 } catch (RemoteException e) { 704 return false; 705 } 706 } 707 708 /** 709 * Disassociate from the currently active access point. This may result 710 * in the asynchronous delivery of state change events. 711 * @return {@code true} if the operation succeeded 712 */ 713 public boolean disconnect() { 714 try { 715 mService.disconnect(); 716 return true; 717 } catch (RemoteException e) { 718 return false; 719 } 720 } 721 722 /** 723 * Reconnect to the currently active access point, if we are currently 724 * disconnected. This may result in the asynchronous delivery of state 725 * change events. 726 * @return {@code true} if the operation succeeded 727 */ 728 public boolean reconnect() { 729 try { 730 mService.reconnect(); 731 return true; 732 } catch (RemoteException e) { 733 return false; 734 } 735 } 736 737 /** 738 * Reconnect to the currently active access point, even if we are already 739 * connected. This may result in the asynchronous delivery of state 740 * change events. 741 * @return {@code true} if the operation succeeded 742 */ 743 public boolean reassociate() { 744 try { 745 mService.reassociate(); 746 return true; 747 } catch (RemoteException e) { 748 return false; 749 } 750 } 751 752 /** 753 * Check that the supplicant daemon is responding to requests. 754 * @return {@code true} if we were able to communicate with the supplicant and 755 * it returned the expected response to the PING message. 756 */ 757 public boolean pingSupplicant() { 758 if (mService == null) 759 return false; 760 try { 761 return mService.pingSupplicant(); 762 } catch (RemoteException e) { 763 return false; 764 } 765 } 766 767 /** 768 * Get a list of available channels for customized scan. 769 * 770 * @see {@link WifiChannel} 771 * 772 * @return the channel list, or null if not available 773 * @hide 774 */ 775 public List<WifiChannel> getChannelList() { 776 try { 777 return mService.getChannelList(); 778 } catch (RemoteException e) { 779 return null; 780 } 781 } 782 783 /** 784 * Request a scan for access points. Returns immediately. The availability 785 * of the results is made known later by means of an asynchronous event sent 786 * on completion of the scan. 787 * @return {@code true} if the operation succeeded, i.e., the scan was initiated 788 */ 789 public boolean startScan() { 790 try { 791 mService.startScan(null, null); 792 return true; 793 } catch (RemoteException e) { 794 return false; 795 } 796 } 797 798 /** @hide */ 799 public boolean startScan(WorkSource workSource) { 800 try { 801 mService.startScan(null, workSource); 802 return true; 803 } catch (RemoteException e) { 804 return false; 805 } 806 } 807 808 /** 809 * Request a scan for access points in specified channel list. Each channel is specified by its 810 * frequency in MHz, e.g. "5500" (do NOT include "DFS" even though it is). The availability of 811 * the results is made known later in the same way as {@link #startScan}. 812 * 813 * Note: 814 * 815 * 1. Customized scan is for non-connection purposes, i.e. it won't trigger a wifi connection 816 * even though it finds some known networks. 817 * 818 * 2. Customized scan result may include access points that is not specified in the channel 819 * list. An app will need to do frequency filtering if it wants to get pure results for the 820 * channel list it specified. 821 * 822 * @hide 823 */ 824 public boolean startCustomizedScan(ScanSettings requested) { 825 try { 826 mService.startScan(requested, null); 827 return true; 828 } catch (RemoteException e) { 829 return false; 830 } 831 } 832 833 /** @hide */ 834 public boolean startCustomizedScan(ScanSettings requested, WorkSource workSource) { 835 try { 836 mService.startScan(requested, workSource); 837 return true; 838 } catch (RemoteException e) { 839 return false; 840 } 841 } 842 843 /** 844 * Request a batched scan for access points. To end your requested batched scan, 845 * call stopBatchedScan with the same Settings. 846 * 847 * If there are mulitple requests for batched scans, the more demanding settings will 848 * take precidence. 849 * 850 * @param requested {@link BatchedScanSettings} the scan settings requested. 851 * @return false on known error 852 * @hide 853 */ 854 public boolean requestBatchedScan(BatchedScanSettings requested) { 855 try { 856 return mService.requestBatchedScan(requested, new Binder(), null); 857 } catch (RemoteException e) { return false; } 858 } 859 /** @hide */ 860 public boolean requestBatchedScan(BatchedScanSettings requested, WorkSource workSource) { 861 try { 862 return mService.requestBatchedScan(requested, new Binder(), workSource); 863 } catch (RemoteException e) { return false; } 864 } 865 866 /** 867 * Check if the Batched Scan feature is supported. 868 * 869 * @return false if not supported. 870 * @hide 871 */ 872 public boolean isBatchedScanSupported() { 873 try { 874 return mService.isBatchedScanSupported(); 875 } catch (RemoteException e) { return false; } 876 } 877 878 /** 879 * End a requested batch scan for this applicaiton. Note that batched scan may 880 * still occur if other apps are using them. 881 * 882 * @param requested {@link BatchedScanSettings} the scan settings you previously requested 883 * and now wish to stop. A value of null here will stop all scans requested by the 884 * calling App. 885 * @hide 886 */ 887 public void stopBatchedScan(BatchedScanSettings requested) { 888 try { 889 mService.stopBatchedScan(requested); 890 } catch (RemoteException e) {} 891 } 892 893 /** 894 * Retrieve the latest batched scan result. This should be called immediately after 895 * {@link BATCHED_SCAN_RESULTS_AVAILABLE_ACTION} is received. 896 * @hide 897 */ 898 public List<BatchedScanResult> getBatchedScanResults() { 899 try { 900 return mService.getBatchedScanResults(mContext.getOpPackageName()); 901 } catch (RemoteException e) { 902 return null; 903 } 904 } 905 906 /** 907 * Force a re-reading of batched scan results. This will attempt 908 * to read more information from the chip, but will do so at the expense 909 * of previous data. Rate limited to the current scan frequency. 910 * 911 * pollBatchedScan will always wait 1 period from the start of the batch 912 * before trying to read from the chip, so if your #scans/batch == 1 this will 913 * have no effect. 914 * 915 * If you had already waited 1 period before calling, this should have 916 * immediate (though async) effect. 917 * 918 * If you call before that 1 period is up this will set up a timer and fetch 919 * results when the 1 period is up. 920 * 921 * Servicing a pollBatchedScan request (immediate or after timed delay) starts a 922 * new batch, so if you were doing 10 scans/batch and called in the 4th scan, you 923 * would get data in the 4th and then again 10 scans later. 924 * @hide 925 */ 926 public void pollBatchedScan() { 927 try { 928 mService.pollBatchedScan(); 929 } catch (RemoteException e) { } 930 } 931 932 /** 933 * Creates a configuration token describing the network referenced by {@code netId} 934 * of MIME type application/vnd.wfa.wsc. Can be used to configure WiFi networks via NFC. 935 * 936 * @return hex-string encoded configuration token 937 * @hide 938 */ 939 public String getWpsNfcConfigurationToken(int netId) { 940 try { 941 return mService.getWpsNfcConfigurationToken(netId); 942 } catch (RemoteException e) { 943 return null; 944 } 945 } 946 947 /** 948 * Return dynamic information about the current Wi-Fi connection, if any is active. 949 * @return the Wi-Fi information, contained in {@link WifiInfo}. 950 */ 951 public WifiInfo getConnectionInfo() { 952 try { 953 return mService.getConnectionInfo(); 954 } catch (RemoteException e) { 955 return null; 956 } 957 } 958 959 /** 960 * Return the results of the latest access point scan. 961 * @return the list of access points found in the most recent scan. 962 */ 963 public List<ScanResult> getScanResults() { 964 try { 965 return mService.getScanResults(mContext.getOpPackageName()); 966 } catch (RemoteException e) { 967 return null; 968 } 969 } 970 971 /** 972 * Check if scanning is always available. 973 * 974 * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results 975 * even when Wi-Fi is turned off. 976 * 977 * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}. 978 */ 979 public boolean isScanAlwaysAvailable() { 980 try { 981 return mService.isScanAlwaysAvailable(); 982 } catch (RemoteException e) { 983 return false; 984 } 985 } 986 987 /** 988 * Tell the supplicant to persist the current list of configured networks. 989 * <p> 990 * Note: It is possible for this method to change the network IDs of 991 * existing networks. You should assume the network IDs can be different 992 * after calling this method. 993 * 994 * @return {@code true} if the operation succeeded 995 */ 996 public boolean saveConfiguration() { 997 try { 998 return mService.saveConfiguration(); 999 } catch (RemoteException e) { 1000 return false; 1001 } 1002 } 1003 1004 /** 1005 * Set the country code. 1006 * @param countryCode country code in ISO 3166 format. 1007 * @param persist {@code true} if this needs to be remembered 1008 * 1009 * @hide 1010 */ 1011 public void setCountryCode(String country, boolean persist) { 1012 try { 1013 mService.setCountryCode(country, persist); 1014 } catch (RemoteException e) { } 1015 } 1016 1017 /** 1018 * Set the operational frequency band. 1019 * @param band One of 1020 * {@link #WIFI_FREQUENCY_BAND_AUTO}, 1021 * {@link #WIFI_FREQUENCY_BAND_5GHZ}, 1022 * {@link #WIFI_FREQUENCY_BAND_2GHZ}, 1023 * @param persist {@code true} if this needs to be remembered 1024 * @hide 1025 */ 1026 public void setFrequencyBand(int band, boolean persist) { 1027 try { 1028 mService.setFrequencyBand(band, persist); 1029 } catch (RemoteException e) { } 1030 } 1031 1032 /** 1033 * Get the operational frequency band. 1034 * @return One of 1035 * {@link #WIFI_FREQUENCY_BAND_AUTO}, 1036 * {@link #WIFI_FREQUENCY_BAND_5GHZ}, 1037 * {@link #WIFI_FREQUENCY_BAND_2GHZ} or 1038 * {@code -1} on failure. 1039 * @hide 1040 */ 1041 public int getFrequencyBand() { 1042 try { 1043 return mService.getFrequencyBand(); 1044 } catch (RemoteException e) { 1045 return -1; 1046 } 1047 } 1048 1049 /** 1050 * Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz) 1051 * @return {@code true} if supported, {@code false} otherwise. 1052 * @hide 1053 */ 1054 public boolean isDualBandSupported() { 1055 try { 1056 return mService.isDualBandSupported(); 1057 } catch (RemoteException e) { 1058 return false; 1059 } 1060 } 1061 1062 /** 1063 * Return the DHCP-assigned addresses from the last successful DHCP request, 1064 * if any. 1065 * @return the DHCP information 1066 */ 1067 public DhcpInfo getDhcpInfo() { 1068 try { 1069 return mService.getDhcpInfo(); 1070 } catch (RemoteException e) { 1071 return null; 1072 } 1073 } 1074 1075 /** 1076 * Enable or disable Wi-Fi. 1077 * @param enabled {@code true} to enable, {@code false} to disable. 1078 * @return {@code true} if the operation succeeds (or if the existing state 1079 * is the same as the requested state). 1080 */ 1081 public boolean setWifiEnabled(boolean enabled) { 1082 try { 1083 return mService.setWifiEnabled(enabled); 1084 } catch (RemoteException e) { 1085 return false; 1086 } 1087 } 1088 1089 /** 1090 * Gets the Wi-Fi enabled state. 1091 * @return One of {@link #WIFI_STATE_DISABLED}, 1092 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 1093 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 1094 * @see #isWifiEnabled() 1095 */ 1096 public int getWifiState() { 1097 try { 1098 return mService.getWifiEnabledState(); 1099 } catch (RemoteException e) { 1100 return WIFI_STATE_UNKNOWN; 1101 } 1102 } 1103 1104 /** 1105 * Return whether Wi-Fi is enabled or disabled. 1106 * @return {@code true} if Wi-Fi is enabled 1107 * @see #getWifiState() 1108 */ 1109 public boolean isWifiEnabled() { 1110 return getWifiState() == WIFI_STATE_ENABLED; 1111 } 1112 1113 /** 1114 * Return TX packet counter, for CTS test of WiFi watchdog. 1115 * @param listener is the interface to receive result 1116 * 1117 * @hide for CTS test only 1118 */ 1119 public void getTxPacketCount(TxPacketCountListener listener) { 1120 validateChannel(); 1121 sAsyncChannel.sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener)); 1122 } 1123 1124 /** 1125 * Calculates the level of the signal. This should be used any time a signal 1126 * is being shown. 1127 * 1128 * @param rssi The power of the signal measured in RSSI. 1129 * @param numLevels The number of levels to consider in the calculated 1130 * level. 1131 * @return A level of the signal, given in the range of 0 to numLevels-1 1132 * (both inclusive). 1133 */ 1134 public static int calculateSignalLevel(int rssi, int numLevels) { 1135 if (rssi <= MIN_RSSI) { 1136 return 0; 1137 } else if (rssi >= MAX_RSSI) { 1138 return numLevels - 1; 1139 } else { 1140 float inputRange = (MAX_RSSI - MIN_RSSI); 1141 float outputRange = (numLevels - 1); 1142 return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange); 1143 } 1144 } 1145 1146 /** 1147 * Compares two signal strengths. 1148 * 1149 * @param rssiA The power of the first signal measured in RSSI. 1150 * @param rssiB The power of the second signal measured in RSSI. 1151 * @return Returns <0 if the first signal is weaker than the second signal, 1152 * 0 if the two signals have the same strength, and >0 if the first 1153 * signal is stronger than the second signal. 1154 */ 1155 public static int compareSignalLevel(int rssiA, int rssiB) { 1156 return rssiA - rssiB; 1157 } 1158 1159 /** 1160 * Start AccessPoint mode with the specified 1161 * configuration. If the radio is already running in 1162 * AP mode, update the new configuration 1163 * Note that starting in access point mode disables station 1164 * mode operation 1165 * @param wifiConfig SSID, security and channel details as 1166 * part of WifiConfiguration 1167 * @return {@code true} if the operation succeeds, {@code false} otherwise 1168 * 1169 * @hide Dont open up yet 1170 */ 1171 public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { 1172 try { 1173 mService.setWifiApEnabled(wifiConfig, enabled); 1174 return true; 1175 } catch (RemoteException e) { 1176 return false; 1177 } 1178 } 1179 1180 /** 1181 * Gets the Wi-Fi enabled state. 1182 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 1183 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 1184 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 1185 * @see #isWifiApEnabled() 1186 * 1187 * @hide Dont open yet 1188 */ 1189 public int getWifiApState() { 1190 try { 1191 return mService.getWifiApEnabledState(); 1192 } catch (RemoteException e) { 1193 return WIFI_AP_STATE_FAILED; 1194 } 1195 } 1196 1197 /** 1198 * Return whether Wi-Fi AP is enabled or disabled. 1199 * @return {@code true} if Wi-Fi AP is enabled 1200 * @see #getWifiApState() 1201 * 1202 * @hide Dont open yet 1203 */ 1204 public boolean isWifiApEnabled() { 1205 return getWifiApState() == WIFI_AP_STATE_ENABLED; 1206 } 1207 1208 /** 1209 * Gets the Wi-Fi AP Configuration. 1210 * @return AP details in WifiConfiguration 1211 * 1212 * @hide Dont open yet 1213 */ 1214 public WifiConfiguration getWifiApConfiguration() { 1215 try { 1216 return mService.getWifiApConfiguration(); 1217 } catch (RemoteException e) { 1218 return null; 1219 } 1220 } 1221 1222 /** 1223 * Sets the Wi-Fi AP Configuration. 1224 * @return {@code true} if the operation succeeded, {@code false} otherwise 1225 * 1226 * @hide Dont open yet 1227 */ 1228 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { 1229 try { 1230 mService.setWifiApConfiguration(wifiConfig); 1231 return true; 1232 } catch (RemoteException e) { 1233 return false; 1234 } 1235 } 1236 1237 /** 1238 * Start the driver and connect to network. 1239 * 1240 * This function will over-ride WifiLock and device idle status. For example, 1241 * even if the device is idle or there is only a scan-only lock held, 1242 * a start wifi would mean that wifi connection is kept active until 1243 * a stopWifi() is sent. 1244 * 1245 * This API is used by WifiStateTracker 1246 * 1247 * @return {@code true} if the operation succeeds else {@code false} 1248 * @hide 1249 */ 1250 public boolean startWifi() { 1251 try { 1252 mService.startWifi(); 1253 return true; 1254 } catch (RemoteException e) { 1255 return false; 1256 } 1257 } 1258 1259 /** 1260 * Disconnect from a network (if any) and stop the driver. 1261 * 1262 * This function will over-ride WifiLock and device idle status. Wi-Fi 1263 * stays inactive until a startWifi() is issued. 1264 * 1265 * This API is used by WifiStateTracker 1266 * 1267 * @return {@code true} if the operation succeeds else {@code false} 1268 * @hide 1269 */ 1270 public boolean stopWifi() { 1271 try { 1272 mService.stopWifi(); 1273 return true; 1274 } catch (RemoteException e) { 1275 return false; 1276 } 1277 } 1278 1279 /** 1280 * Add a bssid to the supplicant blacklist 1281 * 1282 * This API is used by WifiWatchdogService 1283 * 1284 * @return {@code true} if the operation succeeds else {@code false} 1285 * @hide 1286 */ 1287 public boolean addToBlacklist(String bssid) { 1288 try { 1289 mService.addToBlacklist(bssid); 1290 return true; 1291 } catch (RemoteException e) { 1292 return false; 1293 } 1294 } 1295 1296 /** 1297 * Clear the supplicant blacklist 1298 * 1299 * This API is used by WifiWatchdogService 1300 * 1301 * @return {@code true} if the operation succeeds else {@code false} 1302 * @hide 1303 */ 1304 public boolean clearBlacklist() { 1305 try { 1306 mService.clearBlacklist(); 1307 return true; 1308 } catch (RemoteException e) { 1309 return false; 1310 } 1311 } 1312 1313 1314 /** 1315 * Enable/Disable TDLS on a specific local route. 1316 * 1317 * <p> 1318 * TDLS enables two wireless endpoints to talk to each other directly 1319 * without going through the access point that is managing the local 1320 * network. It saves bandwidth and improves quality of the link. 1321 * </p> 1322 * <p> 1323 * This API enables/disables the option of using TDLS. If enabled, the 1324 * underlying hardware is free to use TDLS or a hop through the access 1325 * point. If disabled, existing TDLS session is torn down and 1326 * hardware is restricted to use access point for transferring wireless 1327 * packets. Default value for all routes is 'disabled', meaning restricted 1328 * to use access point for transferring packets. 1329 * </p> 1330 * 1331 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 1332 * @param enable true = setup and false = tear down TDLS 1333 */ 1334 public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) { 1335 try { 1336 mService.enableTdls(remoteIPAddress.getHostAddress(), enable); 1337 } catch (RemoteException e) { 1338 // Just ignore the exception 1339 } 1340 } 1341 1342 /** 1343 * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except 1344 * this version allows you to specify remote endpoint with a MAC address. 1345 * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab 1346 * @param enable true = setup and false = tear down TDLS 1347 */ 1348 public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) { 1349 try { 1350 mService.enableTdlsWithMacAddress(remoteMacAddress, enable); 1351 } catch (RemoteException e) { 1352 // Just ignore the exception 1353 } 1354 } 1355 1356 /* TODO: deprecate synchronous API and open up the following API */ 1357 1358 private static final int BASE = Protocol.BASE_WIFI_MANAGER; 1359 1360 /* Commands to WifiService */ 1361 /** @hide */ 1362 public static final int CONNECT_NETWORK = BASE + 1; 1363 /** @hide */ 1364 public static final int CONNECT_NETWORK_FAILED = BASE + 2; 1365 /** @hide */ 1366 public static final int CONNECT_NETWORK_SUCCEEDED = BASE + 3; 1367 1368 /** @hide */ 1369 public static final int FORGET_NETWORK = BASE + 4; 1370 /** @hide */ 1371 public static final int FORGET_NETWORK_FAILED = BASE + 5; 1372 /** @hide */ 1373 public static final int FORGET_NETWORK_SUCCEEDED = BASE + 6; 1374 1375 /** @hide */ 1376 public static final int SAVE_NETWORK = BASE + 7; 1377 /** @hide */ 1378 public static final int SAVE_NETWORK_FAILED = BASE + 8; 1379 /** @hide */ 1380 public static final int SAVE_NETWORK_SUCCEEDED = BASE + 9; 1381 1382 /** @hide */ 1383 public static final int START_WPS = BASE + 10; 1384 /** @hide */ 1385 public static final int START_WPS_SUCCEEDED = BASE + 11; 1386 /** @hide */ 1387 public static final int WPS_FAILED = BASE + 12; 1388 /** @hide */ 1389 public static final int WPS_COMPLETED = BASE + 13; 1390 1391 /** @hide */ 1392 public static final int CANCEL_WPS = BASE + 14; 1393 /** @hide */ 1394 public static final int CANCEL_WPS_FAILED = BASE + 15; 1395 /** @hide */ 1396 public static final int CANCEL_WPS_SUCCEDED = BASE + 16; 1397 1398 /** @hide */ 1399 public static final int DISABLE_NETWORK = BASE + 17; 1400 /** @hide */ 1401 public static final int DISABLE_NETWORK_FAILED = BASE + 18; 1402 /** @hide */ 1403 public static final int DISABLE_NETWORK_SUCCEEDED = BASE + 19; 1404 1405 /** @hide */ 1406 public static final int RSSI_PKTCNT_FETCH = BASE + 20; 1407 /** @hide */ 1408 public static final int RSSI_PKTCNT_FETCH_SUCCEEDED = BASE + 21; 1409 /** @hide */ 1410 public static final int RSSI_PKTCNT_FETCH_FAILED = BASE + 22; 1411 1412 1413 /** 1414 * Passed with {@link ActionListener#onFailure}. 1415 * Indicates that the operation failed due to an internal error. 1416 */ 1417 public static final int ERROR = 0; 1418 1419 /** 1420 * Passed with {@link ActionListener#onFailure}. 1421 * Indicates that the operation is already in progress 1422 */ 1423 public static final int IN_PROGRESS = 1; 1424 1425 /** 1426 * Passed with {@link ActionListener#onFailure}. 1427 * Indicates that the operation failed because the framework is busy and 1428 * unable to service the request 1429 */ 1430 public static final int BUSY = 2; 1431 1432 /* WPS specific errors */ 1433 /** WPS overlap detected */ 1434 public static final int WPS_OVERLAP_ERROR = 3; 1435 /** WEP on WPS is prohibited */ 1436 public static final int WPS_WEP_PROHIBITED = 4; 1437 /** TKIP only prohibited */ 1438 public static final int WPS_TKIP_ONLY_PROHIBITED = 5; 1439 /** Authentication failure on WPS */ 1440 public static final int WPS_AUTH_FAILURE = 6; 1441 /** WPS timed out */ 1442 public static final int WPS_TIMED_OUT = 7; 1443 1444 /** 1445 * Passed with {@link ActionListener#onFailure}. 1446 * Indicates that the operation failed due to invalid inputs 1447 */ 1448 public static final int INVALID_ARGS = 8; 1449 1450 /** 1451 * Passed with {@link ActionListener#onFailure}. 1452 * Indicates that the operation failed due to user permissions. 1453 * 1454 * @hide 1455 */ 1456 public static final int NOT_AUTHORIZED = 9; 1457 1458 /** Interface for callback invocation on an application action */ 1459 public interface ActionListener { 1460 /** The operation succeeded */ 1461 public void onSuccess(); 1462 /** 1463 * The operation failed 1464 * @param reason The reason for failure could be one of 1465 * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY} 1466 */ 1467 public void onFailure(int reason); 1468 } 1469 1470 /** Interface for callback invocation on a start WPS action */ 1471 public interface WpsListener { 1472 /** WPS start succeeded */ 1473 public void onStartSuccess(String pin); 1474 1475 /** WPS operation completed succesfully */ 1476 public void onCompletion(); 1477 1478 /** 1479 * WPS operation failed 1480 * @param reason The reason for failure could be one of 1481 * {@link #IN_PROGRESS}, {@link #WPS_OVERLAP_ERROR},{@link #ERROR} or {@link #BUSY} 1482 */ 1483 public void onFailure(int reason); 1484 } 1485 1486 /** Interface for callback invocation on a TX packet count poll action {@hide} */ 1487 public interface TxPacketCountListener { 1488 /** 1489 * The operation succeeded 1490 * @param count TX packet counter 1491 */ 1492 public void onSuccess(int count); 1493 /** 1494 * The operation failed 1495 * @param reason The reason for failure could be one of 1496 * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY} 1497 */ 1498 public void onFailure(int reason); 1499 } 1500 1501 private static class ServiceHandler extends Handler { 1502 ServiceHandler(Looper looper) { 1503 super(looper); 1504 } 1505 1506 @Override 1507 public void handleMessage(Message message) { 1508 Object listener = removeListener(message.arg2); 1509 switch (message.what) { 1510 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 1511 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 1512 sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 1513 } else { 1514 Log.e(TAG, "Failed to set up channel connection"); 1515 // This will cause all further async API calls on the WifiManager 1516 // to fail and throw an exception 1517 sAsyncChannel = null; 1518 } 1519 sConnected.countDown(); 1520 break; 1521 case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: 1522 // Ignore 1523 break; 1524 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 1525 Log.e(TAG, "Channel connection lost"); 1526 // This will cause all further async API calls on the WifiManager 1527 // to fail and throw an exception 1528 sAsyncChannel = null; 1529 getLooper().quit(); 1530 break; 1531 /* ActionListeners grouped together */ 1532 case WifiManager.CONNECT_NETWORK_FAILED: 1533 case WifiManager.FORGET_NETWORK_FAILED: 1534 case WifiManager.SAVE_NETWORK_FAILED: 1535 case WifiManager.CANCEL_WPS_FAILED: 1536 case WifiManager.DISABLE_NETWORK_FAILED: 1537 if (listener != null) { 1538 ((ActionListener) listener).onFailure(message.arg1); 1539 } 1540 break; 1541 /* ActionListeners grouped together */ 1542 case WifiManager.CONNECT_NETWORK_SUCCEEDED: 1543 case WifiManager.FORGET_NETWORK_SUCCEEDED: 1544 case WifiManager.SAVE_NETWORK_SUCCEEDED: 1545 case WifiManager.CANCEL_WPS_SUCCEDED: 1546 case WifiManager.DISABLE_NETWORK_SUCCEEDED: 1547 if (listener != null) { 1548 ((ActionListener) listener).onSuccess(); 1549 } 1550 break; 1551 case WifiManager.START_WPS_SUCCEEDED: 1552 if (listener != null) { 1553 WpsResult result = (WpsResult) message.obj; 1554 ((WpsListener) listener).onStartSuccess(result.pin); 1555 //Listener needs to stay until completion or failure 1556 synchronized(sListenerMapLock) { 1557 sListenerMap.put(message.arg2, listener); 1558 } 1559 } 1560 break; 1561 case WifiManager.WPS_COMPLETED: 1562 if (listener != null) { 1563 ((WpsListener) listener).onCompletion(); 1564 } 1565 break; 1566 case WifiManager.WPS_FAILED: 1567 if (listener != null) { 1568 ((WpsListener) listener).onFailure(message.arg1); 1569 } 1570 break; 1571 case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED: 1572 if (listener != null) { 1573 RssiPacketCountInfo info = (RssiPacketCountInfo) message.obj; 1574 if (info != null) 1575 ((TxPacketCountListener) listener).onSuccess(info.txgood + info.txbad); 1576 else 1577 ((TxPacketCountListener) listener).onFailure(ERROR); 1578 } 1579 break; 1580 case WifiManager.RSSI_PKTCNT_FETCH_FAILED: 1581 if (listener != null) { 1582 ((TxPacketCountListener) listener).onFailure(message.arg1); 1583 } 1584 break; 1585 default: 1586 //ignore 1587 break; 1588 } 1589 } 1590 } 1591 1592 private static int putListener(Object listener) { 1593 if (listener == null) return INVALID_KEY; 1594 int key; 1595 synchronized (sListenerMapLock) { 1596 do { 1597 key = sListenerKey++; 1598 } while (key == INVALID_KEY); 1599 sListenerMap.put(key, listener); 1600 } 1601 return key; 1602 } 1603 1604 private static Object removeListener(int key) { 1605 if (key == INVALID_KEY) return null; 1606 synchronized (sListenerMapLock) { 1607 Object listener = sListenerMap.get(key); 1608 sListenerMap.remove(key); 1609 return listener; 1610 } 1611 } 1612 1613 private void init() { 1614 synchronized (sThreadRefLock) { 1615 if (++sThreadRefCount == 1) { 1616 Messenger messenger = getWifiServiceMessenger(); 1617 if (messenger == null) { 1618 sAsyncChannel = null; 1619 return; 1620 } 1621 1622 sHandlerThread = new HandlerThread("WifiManager"); 1623 sAsyncChannel = new AsyncChannel(); 1624 sConnected = new CountDownLatch(1); 1625 1626 sHandlerThread.start(); 1627 Handler handler = new ServiceHandler(sHandlerThread.getLooper()); 1628 sAsyncChannel.connect(mContext, handler, messenger); 1629 try { 1630 sConnected.await(); 1631 } catch (InterruptedException e) { 1632 Log.e(TAG, "interrupted wait at init"); 1633 } 1634 } 1635 } 1636 } 1637 1638 private void validateChannel() { 1639 if (sAsyncChannel == null) throw new IllegalStateException( 1640 "No permission to access and change wifi or a bad initialization"); 1641 } 1642 1643 /** 1644 * Connect to a network with the given configuration. The network also 1645 * gets added to the supplicant configuration. 1646 * 1647 * For a new network, this function is used instead of a 1648 * sequence of addNetwork(), enableNetwork(), saveConfiguration() and 1649 * reconnect() 1650 * 1651 * @param config the set of variables that describe the configuration, 1652 * contained in a {@link WifiConfiguration} object. 1653 * @param listener for callbacks on success or failure. Can be null. 1654 * @throws IllegalStateException if the WifiManager instance needs to be 1655 * initialized again 1656 * 1657 * @hide 1658 */ 1659 public void connect(WifiConfiguration config, ActionListener listener) { 1660 if (config == null) throw new IllegalArgumentException("config cannot be null"); 1661 validateChannel(); 1662 // Use INVALID_NETWORK_ID for arg1 when passing a config object 1663 // arg1 is used to pass network id when the network already exists 1664 sAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, 1665 putListener(listener), config); 1666 } 1667 1668 /** 1669 * Connect to a network with the given networkId. 1670 * 1671 * This function is used instead of a enableNetwork(), saveConfiguration() and 1672 * reconnect() 1673 * 1674 * @param networkId the network id identifiying the network in the 1675 * supplicant configuration list 1676 * @param listener for callbacks on success or failure. Can be null. 1677 * @throws IllegalStateException if the WifiManager instance needs to be 1678 * initialized again 1679 * @hide 1680 */ 1681 public void connect(int networkId, ActionListener listener) { 1682 if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 1683 validateChannel(); 1684 sAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener)); 1685 } 1686 1687 /** 1688 * Save the given network in the supplicant config. If the network already 1689 * exists, the configuration is updated. A new network is enabled 1690 * by default. 1691 * 1692 * For a new network, this function is used instead of a 1693 * sequence of addNetwork(), enableNetwork() and saveConfiguration(). 1694 * 1695 * For an existing network, it accomplishes the task of updateNetwork() 1696 * and saveConfiguration() 1697 * 1698 * @param config the set of variables that describe the configuration, 1699 * contained in a {@link WifiConfiguration} object. 1700 * @param listener for callbacks on success or failure. Can be null. 1701 * @throws IllegalStateException if the WifiManager instance needs to be 1702 * initialized again 1703 * @hide 1704 */ 1705 public void save(WifiConfiguration config, ActionListener listener) { 1706 if (config == null) throw new IllegalArgumentException("config cannot be null"); 1707 validateChannel(); 1708 sAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config); 1709 } 1710 1711 /** 1712 * Delete the network in the supplicant config. 1713 * 1714 * This function is used instead of a sequence of removeNetwork() 1715 * and saveConfiguration(). 1716 * 1717 * @param config the set of variables that describe the configuration, 1718 * contained in a {@link WifiConfiguration} object. 1719 * @param listener for callbacks on success or failure. Can be null. 1720 * @throws IllegalStateException if the WifiManager instance needs to be 1721 * initialized again 1722 * @hide 1723 */ 1724 public void forget(int netId, ActionListener listener) { 1725 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 1726 validateChannel(); 1727 sAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener)); 1728 } 1729 1730 /** 1731 * Disable network 1732 * 1733 * @param netId is the network Id 1734 * @param listener for callbacks on success or failure. Can be null. 1735 * @throws IllegalStateException if the WifiManager instance needs to be 1736 * initialized again 1737 * @hide 1738 */ 1739 public void disable(int netId, ActionListener listener) { 1740 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 1741 validateChannel(); 1742 sAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener)); 1743 } 1744 1745 /** 1746 * Start Wi-fi Protected Setup 1747 * 1748 * @param config WPS configuration 1749 * @param listener for callbacks on success or failure. Can be null. 1750 * @throws IllegalStateException if the WifiManager instance needs to be 1751 * initialized again 1752 */ 1753 public void startWps(WpsInfo config, WpsListener listener) { 1754 if (config == null) throw new IllegalArgumentException("config cannot be null"); 1755 validateChannel(); 1756 sAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config); 1757 } 1758 1759 /** 1760 * Cancel any ongoing Wi-fi Protected Setup 1761 * 1762 * @param listener for callbacks on success or failure. Can be null. 1763 * @throws IllegalStateException if the WifiManager instance needs to be 1764 * initialized again 1765 */ 1766 public void cancelWps(ActionListener listener) { 1767 validateChannel(); 1768 sAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener)); 1769 } 1770 1771 /** 1772 * Get a reference to WifiService handler. This is used by a client to establish 1773 * an AsyncChannel communication with WifiService 1774 * 1775 * @return Messenger pointing to the WifiService handler 1776 * @hide 1777 */ 1778 public Messenger getWifiServiceMessenger() { 1779 try { 1780 return mService.getWifiServiceMessenger(); 1781 } catch (RemoteException e) { 1782 return null; 1783 } catch (SecurityException e) { 1784 return null; 1785 } 1786 } 1787 1788 1789 /** 1790 * Returns the file in which IP and proxy configuration data is stored 1791 * @hide 1792 */ 1793 public String getConfigFile() { 1794 try { 1795 return mService.getConfigFile(); 1796 } catch (RemoteException e) { 1797 return null; 1798 } 1799 } 1800 1801 /** 1802 * Allows an application to keep the Wi-Fi radio awake. 1803 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 1804 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 1805 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 1806 * WifiLocks are held in any application. 1807 * <p> 1808 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 1809 * could function over a mobile network, if available. A program that needs to download large 1810 * files should hold a WifiLock to ensure that the download will complete, but a program whose 1811 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 1812 * affecting battery life. 1813 * <p> 1814 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 1815 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 1816 * is idle. 1817 * <p> 1818 * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK} 1819 * permission in an {@code <uses-permission>} element of the application's manifest. 1820 */ 1821 public class WifiLock { 1822 private String mTag; 1823 private final IBinder mBinder; 1824 private int mRefCount; 1825 int mLockType; 1826 private boolean mRefCounted; 1827 private boolean mHeld; 1828 private WorkSource mWorkSource; 1829 1830 private WifiLock(int lockType, String tag) { 1831 mTag = tag; 1832 mLockType = lockType; 1833 mBinder = new Binder(); 1834 mRefCount = 0; 1835 mRefCounted = true; 1836 mHeld = false; 1837 } 1838 1839 /** 1840 * Locks the Wi-Fi radio on until {@link #release} is called. 1841 * 1842 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 1843 * reference count, and the radio will remain locked as long as the reference count is 1844 * above zero. 1845 * 1846 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 1847 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 1848 * will be required, regardless of the number of times that {@code acquire} is called. 1849 */ 1850 public void acquire() { 1851 synchronized (mBinder) { 1852 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 1853 try { 1854 mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); 1855 synchronized (WifiManager.this) { 1856 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 1857 mService.releaseWifiLock(mBinder); 1858 throw new UnsupportedOperationException( 1859 "Exceeded maximum number of wifi locks"); 1860 } 1861 mActiveLockCount++; 1862 } 1863 } catch (RemoteException ignore) { 1864 } 1865 mHeld = true; 1866 } 1867 } 1868 } 1869 1870 /** 1871 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 1872 * 1873 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 1874 * reference count, and the radio will be unlocked only when the reference count reaches 1875 * zero. If the reference count goes below zero (that is, if {@code release} is called 1876 * a greater number of times than {@link #acquire}), an exception is thrown. 1877 * 1878 * If this WifiLock is not reference-counted, the first call to {@code release} (after 1879 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 1880 * calls will be ignored. 1881 */ 1882 public void release() { 1883 synchronized (mBinder) { 1884 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 1885 try { 1886 mService.releaseWifiLock(mBinder); 1887 synchronized (WifiManager.this) { 1888 mActiveLockCount--; 1889 } 1890 } catch (RemoteException ignore) { 1891 } 1892 mHeld = false; 1893 } 1894 if (mRefCount < 0) { 1895 throw new RuntimeException("WifiLock under-locked " + mTag); 1896 } 1897 } 1898 } 1899 1900 /** 1901 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 1902 * 1903 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 1904 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 1905 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 1906 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 1907 * radio whenever {@link #release} is called and it is locked. 1908 * 1909 * @param refCounted true if this WifiLock should keep a reference count 1910 */ 1911 public void setReferenceCounted(boolean refCounted) { 1912 mRefCounted = refCounted; 1913 } 1914 1915 /** 1916 * Checks whether this WifiLock is currently held. 1917 * 1918 * @return true if this WifiLock is held, false otherwise 1919 */ 1920 public boolean isHeld() { 1921 synchronized (mBinder) { 1922 return mHeld; 1923 } 1924 } 1925 1926 public void setWorkSource(WorkSource ws) { 1927 synchronized (mBinder) { 1928 if (ws != null && ws.size() == 0) { 1929 ws = null; 1930 } 1931 boolean changed = true; 1932 if (ws == null) { 1933 mWorkSource = null; 1934 } else { 1935 ws.clearNames(); 1936 if (mWorkSource == null) { 1937 changed = mWorkSource != null; 1938 mWorkSource = new WorkSource(ws); 1939 } else { 1940 changed = mWorkSource.diff(ws); 1941 if (changed) { 1942 mWorkSource.set(ws); 1943 } 1944 } 1945 } 1946 if (changed && mHeld) { 1947 try { 1948 mService.updateWifiLockWorkSource(mBinder, mWorkSource); 1949 } catch (RemoteException e) { 1950 } 1951 } 1952 } 1953 } 1954 1955 public String toString() { 1956 String s1, s2, s3; 1957 synchronized (mBinder) { 1958 s1 = Integer.toHexString(System.identityHashCode(this)); 1959 s2 = mHeld ? "held; " : ""; 1960 if (mRefCounted) { 1961 s3 = "refcounted: refcount = " + mRefCount; 1962 } else { 1963 s3 = "not refcounted"; 1964 } 1965 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 1966 } 1967 } 1968 1969 @Override 1970 protected void finalize() throws Throwable { 1971 super.finalize(); 1972 synchronized (mBinder) { 1973 if (mHeld) { 1974 try { 1975 mService.releaseWifiLock(mBinder); 1976 synchronized (WifiManager.this) { 1977 mActiveLockCount--; 1978 } 1979 } catch (RemoteException ignore) { 1980 } 1981 } 1982 } 1983 } 1984 } 1985 1986 /** 1987 * Creates a new WifiLock. 1988 * 1989 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL}, 1990 * {@link #WIFI_MODE_FULL_HIGH_PERF} and {@link #WIFI_MODE_SCAN_ONLY} for 1991 * descriptions of the types of Wi-Fi locks. 1992 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 1993 * never shown to the user under normal conditions, but should be descriptive 1994 * enough to identify your application and the specific WifiLock within it, if it 1995 * holds multiple WifiLocks. 1996 * 1997 * @return a new, unacquired WifiLock with the given tag. 1998 * 1999 * @see WifiLock 2000 */ 2001 public WifiLock createWifiLock(int lockType, String tag) { 2002 return new WifiLock(lockType, tag); 2003 } 2004 2005 /** 2006 * Creates a new WifiLock. 2007 * 2008 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 2009 * never shown to the user under normal conditions, but should be descriptive 2010 * enough to identify your application and the specific WifiLock within it, if it 2011 * holds multiple WifiLocks. 2012 * 2013 * @return a new, unacquired WifiLock with the given tag. 2014 * 2015 * @see WifiLock 2016 */ 2017 public WifiLock createWifiLock(String tag) { 2018 return new WifiLock(WIFI_MODE_FULL, tag); 2019 } 2020 2021 2022 /** 2023 * Create a new MulticastLock 2024 * 2025 * @param tag a tag for the MulticastLock to identify it in debugging 2026 * messages. This string is never shown to the user under 2027 * normal conditions, but should be descriptive enough to 2028 * identify your application and the specific MulticastLock 2029 * within it, if it holds multiple MulticastLocks. 2030 * 2031 * @return a new, unacquired MulticastLock with the given tag. 2032 * 2033 * @see MulticastLock 2034 */ 2035 public MulticastLock createMulticastLock(String tag) { 2036 return new MulticastLock(tag); 2037 } 2038 2039 /** 2040 * Allows an application to receive Wifi Multicast packets. 2041 * Normally the Wifi stack filters out packets not explicitly 2042 * addressed to this device. Acquring a MulticastLock will 2043 * cause the stack to receive packets addressed to multicast 2044 * addresses. Processing these extra packets can cause a noticable 2045 * battery drain and should be disabled when not needed. 2046 */ 2047 public class MulticastLock { 2048 private String mTag; 2049 private final IBinder mBinder; 2050 private int mRefCount; 2051 private boolean mRefCounted; 2052 private boolean mHeld; 2053 2054 private MulticastLock(String tag) { 2055 mTag = tag; 2056 mBinder = new Binder(); 2057 mRefCount = 0; 2058 mRefCounted = true; 2059 mHeld = false; 2060 } 2061 2062 /** 2063 * Locks Wifi Multicast on until {@link #release} is called. 2064 * 2065 * If this MulticastLock is reference-counted each call to 2066 * {@code acquire} will increment the reference count, and the 2067 * wifi interface will receive multicast packets as long as the 2068 * reference count is above zero. 2069 * 2070 * If this MulticastLock is not reference-counted, the first call to 2071 * {@code acquire} will turn on the multicast packets, but subsequent 2072 * calls will be ignored. Only one call to {@link #release} will 2073 * be required, regardless of the number of times that {@code acquire} 2074 * is called. 2075 * 2076 * Note that other applications may also lock Wifi Multicast on. 2077 * Only they can relinquish their lock. 2078 * 2079 * Also note that applications cannot leave Multicast locked on. 2080 * When an app exits or crashes, any Multicast locks will be released. 2081 */ 2082 public void acquire() { 2083 synchronized (mBinder) { 2084 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 2085 try { 2086 mService.acquireMulticastLock(mBinder, mTag); 2087 synchronized (WifiManager.this) { 2088 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 2089 mService.releaseMulticastLock(); 2090 throw new UnsupportedOperationException( 2091 "Exceeded maximum number of wifi locks"); 2092 } 2093 mActiveLockCount++; 2094 } 2095 } catch (RemoteException ignore) { 2096 } 2097 mHeld = true; 2098 } 2099 } 2100 } 2101 2102 /** 2103 * Unlocks Wifi Multicast, restoring the filter of packets 2104 * not addressed specifically to this device and saving power. 2105 * 2106 * If this MulticastLock is reference-counted, each call to 2107 * {@code release} will decrement the reference count, and the 2108 * multicast packets will only stop being received when the reference 2109 * count reaches zero. If the reference count goes below zero (that 2110 * is, if {@code release} is called a greater number of times than 2111 * {@link #acquire}), an exception is thrown. 2112 * 2113 * If this MulticastLock is not reference-counted, the first call to 2114 * {@code release} (after the radio was multicast locked using 2115 * {@link #acquire}) will unlock the multicast, and subsequent calls 2116 * will be ignored. 2117 * 2118 * Note that if any other Wifi Multicast Locks are still outstanding 2119 * this {@code release} call will not have an immediate effect. Only 2120 * when all applications have released all their Multicast Locks will 2121 * the Multicast filter be turned back on. 2122 * 2123 * Also note that when an app exits or crashes all of its Multicast 2124 * Locks will be automatically released. 2125 */ 2126 public void release() { 2127 synchronized (mBinder) { 2128 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 2129 try { 2130 mService.releaseMulticastLock(); 2131 synchronized (WifiManager.this) { 2132 mActiveLockCount--; 2133 } 2134 } catch (RemoteException ignore) { 2135 } 2136 mHeld = false; 2137 } 2138 if (mRefCount < 0) { 2139 throw new RuntimeException("MulticastLock under-locked " 2140 + mTag); 2141 } 2142 } 2143 } 2144 2145 /** 2146 * Controls whether this is a reference-counted or non-reference- 2147 * counted MulticastLock. 2148 * 2149 * Reference-counted MulticastLocks keep track of the number of calls 2150 * to {@link #acquire} and {@link #release}, and only stop the 2151 * reception of multicast packets when every call to {@link #acquire} 2152 * has been balanced with a call to {@link #release}. Non-reference- 2153 * counted MulticastLocks allow the reception of multicast packets 2154 * whenever {@link #acquire} is called and stop accepting multicast 2155 * packets whenever {@link #release} is called. 2156 * 2157 * @param refCounted true if this MulticastLock should keep a reference 2158 * count 2159 */ 2160 public void setReferenceCounted(boolean refCounted) { 2161 mRefCounted = refCounted; 2162 } 2163 2164 /** 2165 * Checks whether this MulticastLock is currently held. 2166 * 2167 * @return true if this MulticastLock is held, false otherwise 2168 */ 2169 public boolean isHeld() { 2170 synchronized (mBinder) { 2171 return mHeld; 2172 } 2173 } 2174 2175 public String toString() { 2176 String s1, s2, s3; 2177 synchronized (mBinder) { 2178 s1 = Integer.toHexString(System.identityHashCode(this)); 2179 s2 = mHeld ? "held; " : ""; 2180 if (mRefCounted) { 2181 s3 = "refcounted: refcount = " + mRefCount; 2182 } else { 2183 s3 = "not refcounted"; 2184 } 2185 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 2186 } 2187 } 2188 2189 @Override 2190 protected void finalize() throws Throwable { 2191 super.finalize(); 2192 setReferenceCounted(false); 2193 release(); 2194 } 2195 } 2196 2197 /** 2198 * Check multicast filter status. 2199 * 2200 * @return true if multicast packets are allowed. 2201 * 2202 * @hide pending API council approval 2203 */ 2204 public boolean isMulticastEnabled() { 2205 try { 2206 return mService.isMulticastEnabled(); 2207 } catch (RemoteException e) { 2208 return false; 2209 } 2210 } 2211 2212 /** 2213 * Initialize the multicast filtering to 'on' 2214 * @hide no intent to publish 2215 */ 2216 public boolean initializeMulticastFiltering() { 2217 try { 2218 mService.initializeMulticastFiltering(); 2219 return true; 2220 } catch (RemoteException e) { 2221 return false; 2222 } 2223 } 2224 2225 protected void finalize() throws Throwable { 2226 try { 2227 synchronized (sThreadRefLock) { 2228 if (--sThreadRefCount == 0 && sAsyncChannel != null) { 2229 sAsyncChannel.disconnect(); 2230 } 2231 } 2232 } finally { 2233 super.finalize(); 2234 } 2235 } 2236 2237 /** 2238 * Set wifi verbose log. Called from developer settings. 2239 * @hide 2240 */ 2241 public void enableVerboseLogging (int verbose) { 2242 try { 2243 mService.enableVerboseLogging(verbose); 2244 } catch (Exception e) { 2245 //ignore any failure here 2246 Log.e(TAG, "enableVerboseLogging " + e.toString()); 2247 } 2248 } 2249 2250 /** 2251 * Get the WiFi verbose logging level.This is used by settings 2252 * to decide what to show within the picker. 2253 * @hide 2254 */ 2255 public int getVerboseLoggingLevel() { 2256 try { 2257 return mService.getVerboseLoggingLevel(); 2258 } catch (RemoteException e) { 2259 return 0; 2260 } 2261 } 2262 2263 /** 2264 * Set wifi Aggressive Handover. Called from developer settings. 2265 * @hide 2266 */ 2267 public void enableAggressiveHandover(int enabled) { 2268 try { 2269 mService.enableAggressiveHandover(enabled); 2270 } catch (RemoteException e) { 2271 2272 } 2273 } 2274 2275 /** 2276 * Get the WiFi Handover aggressiveness.This is used by settings 2277 * to decide what to show within the picker. 2278 * @hide 2279 */ 2280 public int getAggressiveHandover() { 2281 try { 2282 return mService.getAggressiveHandover(); 2283 } catch (RemoteException e) { 2284 return 0; 2285 } 2286 } 2287 2288 /** 2289 * Set setting for allowing Scans when traffic is ongoing. 2290 * @hide 2291 */ 2292 public void setAllowScansWithTraffic(int enabled) { 2293 try { 2294 mService.setAllowScansWithTraffic(enabled); 2295 } catch (RemoteException e) { 2296 2297 } 2298 } 2299 2300 /** 2301 * Get setting for allowing Scans when traffic is ongoing. 2302 * @hide 2303 */ 2304 public int getAllowScansWithTraffic() { 2305 try { 2306 return mService.getAllowScansWithTraffic(); 2307 } catch (RemoteException e) { 2308 return 0; 2309 } 2310 } 2311} 2312