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