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 */ WifiManager(Context context, IWifiManager service)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 */ getConfiguredNetworks()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 getPrivilegedConfiguredNetworks()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 getConnectionStatistics()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 */ addNetwork(WifiConfiguration config)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 */ updateNetwork(WifiConfiguration config)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 */ addOrUpdateNetwork(WifiConfiguration config)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 */ removeNetwork(int netId)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 */ enableNetwork(int netId, boolean disableOthers)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 */ disableNetwork(int netId)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 */ disconnect()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 */ reconnect()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 */ reassociate()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 */ pingSupplicant()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 */ getChannelList()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 getSupportedFeatures()843 private int getSupportedFeatures() { 844 try { 845 return mService.getSupportedFeatures(); 846 } catch (RemoteException e) { 847 return 0; 848 } 849 } 850 isFeatureSupported(int feature)851 private boolean isFeatureSupported(int feature) { 852 return (getSupportedFeatures() & feature) == feature; 853 } 854 /** 855 * @return true if this adapter supports 5 GHz band 856 */ is5GHzBandSupported()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 */ isPasspointSupported()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 */ isP2pSupported()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 isPortableHotspotSupported()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 isWifiScannerSupported()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 */ isNanSupported()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 isDeviceToDeviceRttSupported()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 isDeviceToApRttSupported()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 */ isPreferredNetworkOffloadSupported()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 */ isAdditionalStaSupported()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 */ isTdlsSupported()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 */ isOffChannelTdlsSupported()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 */ isEnhancedPowerReportingSupported()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 */ getControllerActivityEnergyInfo(int updateType)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 */ startScan()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 startScan(WorkSource workSource)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 * startLocationRestrictedScan() 1015 * Trigger a scan which will not make use of DFS channels and is thus not suitable for 1016 * establishing wifi connection. 1017 * @hide 1018 */ 1019 @SystemApi startLocationRestrictedScan(WorkSource workSource)1020 public boolean startLocationRestrictedScan(WorkSource workSource) { 1021 try { 1022 mService.startLocationRestrictedScan(workSource); 1023 return true; 1024 } catch (RemoteException e) { 1025 return false; 1026 } 1027 } 1028 1029 /** 1030 * Request a scan for access points in specified channel list. Each channel is specified by its 1031 * frequency in MHz, e.g. "5500" (do NOT include "DFS" even though it is). The availability of 1032 * the results is made known later in the same way as {@link #startScan}. 1033 * 1034 * Note: 1035 * 1036 * 1. Customized scan is for non-connection purposes, i.e. it won't trigger a wifi connection 1037 * even though it finds some known networks. 1038 * 1039 * 2. Customized scan result may include access points that is not specified in the channel 1040 * list. An app will need to do frequency filtering if it wants to get pure results for the 1041 * channel list it specified. 1042 * 1043 * @hide 1044 */ startCustomizedScan(ScanSettings requested)1045 public boolean startCustomizedScan(ScanSettings requested) { 1046 try { 1047 mService.startScan(requested, null); 1048 return true; 1049 } catch (RemoteException e) { 1050 return false; 1051 } 1052 } 1053 1054 /** @hide */ startCustomizedScan(ScanSettings requested, WorkSource workSource)1055 public boolean startCustomizedScan(ScanSettings requested, WorkSource workSource) { 1056 try { 1057 mService.startScan(requested, workSource); 1058 return true; 1059 } catch (RemoteException e) { 1060 return false; 1061 } 1062 } 1063 1064 /** 1065 * Request a batched scan for access points. To end your requested batched scan, 1066 * call stopBatchedScan with the same Settings. 1067 * 1068 * If there are mulitple requests for batched scans, the more demanding settings will 1069 * take precidence. 1070 * 1071 * @param requested {@link BatchedScanSettings} the scan settings requested. 1072 * @return false on known error 1073 * @hide 1074 */ requestBatchedScan(BatchedScanSettings requested)1075 public boolean requestBatchedScan(BatchedScanSettings requested) { 1076 try { 1077 return mService.requestBatchedScan(requested, new Binder(), null); 1078 } catch (RemoteException e) { return false; } 1079 } 1080 /** @hide */ requestBatchedScan(BatchedScanSettings requested, WorkSource workSource)1081 public boolean requestBatchedScan(BatchedScanSettings requested, WorkSource workSource) { 1082 try { 1083 return mService.requestBatchedScan(requested, new Binder(), workSource); 1084 } catch (RemoteException e) { return false; } 1085 } 1086 1087 /** 1088 * Check if the Batched Scan feature is supported. 1089 * 1090 * @return false if not supported. 1091 * @hide 1092 */ 1093 @SystemApi isBatchedScanSupported()1094 public boolean isBatchedScanSupported() { 1095 try { 1096 return mService.isBatchedScanSupported(); 1097 } catch (RemoteException e) { return false; } 1098 } 1099 1100 /** 1101 * End a requested batch scan for this applicaiton. Note that batched scan may 1102 * still occur if other apps are using them. 1103 * 1104 * @param requested {@link BatchedScanSettings} the scan settings you previously requested 1105 * and now wish to stop. A value of null here will stop all scans requested by the 1106 * calling App. 1107 * @hide 1108 */ stopBatchedScan(BatchedScanSettings requested)1109 public void stopBatchedScan(BatchedScanSettings requested) { 1110 try { 1111 mService.stopBatchedScan(requested); 1112 } catch (RemoteException e) {} 1113 } 1114 1115 /** 1116 * Retrieve the latest batched scan result. This should be called immediately after 1117 * {@link BATCHED_SCAN_RESULTS_AVAILABLE_ACTION} is received. 1118 * @hide 1119 */ 1120 @SystemApi getBatchedScanResults()1121 public List<BatchedScanResult> getBatchedScanResults() { 1122 try { 1123 return mService.getBatchedScanResults(mContext.getOpPackageName()); 1124 } catch (RemoteException e) { 1125 return null; 1126 } 1127 } 1128 1129 /** 1130 * Force a re-reading of batched scan results. This will attempt 1131 * to read more information from the chip, but will do so at the expense 1132 * of previous data. Rate limited to the current scan frequency. 1133 * 1134 * pollBatchedScan will always wait 1 period from the start of the batch 1135 * before trying to read from the chip, so if your #scans/batch == 1 this will 1136 * have no effect. 1137 * 1138 * If you had already waited 1 period before calling, this should have 1139 * immediate (though async) effect. 1140 * 1141 * If you call before that 1 period is up this will set up a timer and fetch 1142 * results when the 1 period is up. 1143 * 1144 * Servicing a pollBatchedScan request (immediate or after timed delay) starts a 1145 * new batch, so if you were doing 10 scans/batch and called in the 4th scan, you 1146 * would get data in the 4th and then again 10 scans later. 1147 * @hide 1148 */ pollBatchedScan()1149 public void pollBatchedScan() { 1150 try { 1151 mService.pollBatchedScan(); 1152 } catch (RemoteException e) { } 1153 } 1154 1155 /** 1156 * Creates a configuration token describing the network referenced by {@code netId} 1157 * of MIME type application/vnd.wfa.wsc. Can be used to configure WiFi networks via NFC. 1158 * 1159 * @return hex-string encoded configuration token 1160 * @hide 1161 */ getWpsNfcConfigurationToken(int netId)1162 public String getWpsNfcConfigurationToken(int netId) { 1163 try { 1164 return mService.getWpsNfcConfigurationToken(netId); 1165 } catch (RemoteException e) { 1166 return null; 1167 } 1168 } 1169 1170 /** 1171 * Return dynamic information about the current Wi-Fi connection, if any is active. 1172 * @return the Wi-Fi information, contained in {@link WifiInfo}. 1173 */ getConnectionInfo()1174 public WifiInfo getConnectionInfo() { 1175 try { 1176 return mService.getConnectionInfo(); 1177 } catch (RemoteException e) { 1178 return null; 1179 } 1180 } 1181 1182 /** 1183 * Return the results of the latest access point scan. 1184 * @return the list of access points found in the most recent scan. 1185 */ getScanResults()1186 public List<ScanResult> getScanResults() { 1187 try { 1188 return mService.getScanResults(mContext.getOpPackageName()); 1189 } catch (RemoteException e) { 1190 return null; 1191 } 1192 } 1193 1194 /** 1195 * Check if scanning is always available. 1196 * 1197 * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results 1198 * even when Wi-Fi is turned off. 1199 * 1200 * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}. 1201 */ isScanAlwaysAvailable()1202 public boolean isScanAlwaysAvailable() { 1203 try { 1204 return mService.isScanAlwaysAvailable(); 1205 } catch (RemoteException e) { 1206 return false; 1207 } 1208 } 1209 1210 /** 1211 * Tell the supplicant to persist the current list of configured networks. 1212 * <p> 1213 * Note: It is possible for this method to change the network IDs of 1214 * existing networks. You should assume the network IDs can be different 1215 * after calling this method. 1216 * 1217 * @return {@code true} if the operation succeeded 1218 */ saveConfiguration()1219 public boolean saveConfiguration() { 1220 try { 1221 return mService.saveConfiguration(); 1222 } catch (RemoteException e) { 1223 return false; 1224 } 1225 } 1226 1227 /** 1228 * Set the country code. 1229 * @param countryCode country code in ISO 3166 format. 1230 * @param persist {@code true} if this needs to be remembered 1231 * 1232 * @hide 1233 */ setCountryCode(String country, boolean persist)1234 public void setCountryCode(String country, boolean persist) { 1235 try { 1236 mService.setCountryCode(country, persist); 1237 } catch (RemoteException e) { } 1238 } 1239 1240 /** 1241 * Set the operational frequency band. 1242 * @param band One of 1243 * {@link #WIFI_FREQUENCY_BAND_AUTO}, 1244 * {@link #WIFI_FREQUENCY_BAND_5GHZ}, 1245 * {@link #WIFI_FREQUENCY_BAND_2GHZ}, 1246 * @param persist {@code true} if this needs to be remembered 1247 * @hide 1248 */ setFrequencyBand(int band, boolean persist)1249 public void setFrequencyBand(int band, boolean persist) { 1250 try { 1251 mService.setFrequencyBand(band, persist); 1252 } catch (RemoteException e) { } 1253 } 1254 1255 /** 1256 * Get the operational frequency band. 1257 * @return One of 1258 * {@link #WIFI_FREQUENCY_BAND_AUTO}, 1259 * {@link #WIFI_FREQUENCY_BAND_5GHZ}, 1260 * {@link #WIFI_FREQUENCY_BAND_2GHZ} or 1261 * {@code -1} on failure. 1262 * @hide 1263 */ getFrequencyBand()1264 public int getFrequencyBand() { 1265 try { 1266 return mService.getFrequencyBand(); 1267 } catch (RemoteException e) { 1268 return -1; 1269 } 1270 } 1271 1272 /** 1273 * Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz) 1274 * @return {@code true} if supported, {@code false} otherwise. 1275 * @hide 1276 */ isDualBandSupported()1277 public boolean isDualBandSupported() { 1278 try { 1279 return mService.isDualBandSupported(); 1280 } catch (RemoteException e) { 1281 return false; 1282 } 1283 } 1284 1285 /** 1286 * Return the DHCP-assigned addresses from the last successful DHCP request, 1287 * if any. 1288 * @return the DHCP information 1289 */ getDhcpInfo()1290 public DhcpInfo getDhcpInfo() { 1291 try { 1292 return mService.getDhcpInfo(); 1293 } catch (RemoteException e) { 1294 return null; 1295 } 1296 } 1297 1298 /** 1299 * Enable or disable Wi-Fi. 1300 * @param enabled {@code true} to enable, {@code false} to disable. 1301 * @return {@code true} if the operation succeeds (or if the existing state 1302 * is the same as the requested state). 1303 */ setWifiEnabled(boolean enabled)1304 public boolean setWifiEnabled(boolean enabled) { 1305 try { 1306 return mService.setWifiEnabled(enabled); 1307 } catch (RemoteException e) { 1308 return false; 1309 } 1310 } 1311 1312 /** 1313 * Gets the Wi-Fi enabled state. 1314 * @return One of {@link #WIFI_STATE_DISABLED}, 1315 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 1316 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 1317 * @see #isWifiEnabled() 1318 */ getWifiState()1319 public int getWifiState() { 1320 try { 1321 return mService.getWifiEnabledState(); 1322 } catch (RemoteException e) { 1323 return WIFI_STATE_UNKNOWN; 1324 } 1325 } 1326 1327 /** 1328 * Return whether Wi-Fi is enabled or disabled. 1329 * @return {@code true} if Wi-Fi is enabled 1330 * @see #getWifiState() 1331 */ isWifiEnabled()1332 public boolean isWifiEnabled() { 1333 return getWifiState() == WIFI_STATE_ENABLED; 1334 } 1335 1336 /** 1337 * Return TX packet counter, for CTS test of WiFi watchdog. 1338 * @param listener is the interface to receive result 1339 * 1340 * @hide for CTS test only 1341 */ getTxPacketCount(TxPacketCountListener listener)1342 public void getTxPacketCount(TxPacketCountListener listener) { 1343 validateChannel(); 1344 sAsyncChannel.sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener)); 1345 } 1346 1347 /** 1348 * Calculates the level of the signal. This should be used any time a signal 1349 * is being shown. 1350 * 1351 * @param rssi The power of the signal measured in RSSI. 1352 * @param numLevels The number of levels to consider in the calculated 1353 * level. 1354 * @return A level of the signal, given in the range of 0 to numLevels-1 1355 * (both inclusive). 1356 */ calculateSignalLevel(int rssi, int numLevels)1357 public static int calculateSignalLevel(int rssi, int numLevels) { 1358 if (rssi <= MIN_RSSI) { 1359 return 0; 1360 } else if (rssi >= MAX_RSSI) { 1361 return numLevels - 1; 1362 } else { 1363 float inputRange = (MAX_RSSI - MIN_RSSI); 1364 float outputRange = (numLevels - 1); 1365 return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange); 1366 } 1367 } 1368 1369 /** 1370 * Compares two signal strengths. 1371 * 1372 * @param rssiA The power of the first signal measured in RSSI. 1373 * @param rssiB The power of the second signal measured in RSSI. 1374 * @return Returns <0 if the first signal is weaker than the second signal, 1375 * 0 if the two signals have the same strength, and >0 if the first 1376 * signal is stronger than the second signal. 1377 */ compareSignalLevel(int rssiA, int rssiB)1378 public static int compareSignalLevel(int rssiA, int rssiB) { 1379 return rssiA - rssiB; 1380 } 1381 1382 /** 1383 * Start AccessPoint mode with the specified 1384 * configuration. If the radio is already running in 1385 * AP mode, update the new configuration 1386 * Note that starting in access point mode disables station 1387 * mode operation 1388 * @param wifiConfig SSID, security and channel details as 1389 * part of WifiConfiguration 1390 * @return {@code true} if the operation succeeds, {@code false} otherwise 1391 * 1392 * @hide Dont open up yet 1393 */ setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)1394 public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) { 1395 try { 1396 mService.setWifiApEnabled(wifiConfig, enabled); 1397 return true; 1398 } catch (RemoteException e) { 1399 return false; 1400 } 1401 } 1402 1403 /** 1404 * Gets the Wi-Fi enabled state. 1405 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 1406 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 1407 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 1408 * @see #isWifiApEnabled() 1409 * 1410 * @hide Dont open yet 1411 */ getWifiApState()1412 public int getWifiApState() { 1413 try { 1414 return mService.getWifiApEnabledState(); 1415 } catch (RemoteException e) { 1416 return WIFI_AP_STATE_FAILED; 1417 } 1418 } 1419 1420 /** 1421 * Return whether Wi-Fi AP is enabled or disabled. 1422 * @return {@code true} if Wi-Fi AP is enabled 1423 * @see #getWifiApState() 1424 * 1425 * @hide Dont open yet 1426 */ isWifiApEnabled()1427 public boolean isWifiApEnabled() { 1428 return getWifiApState() == WIFI_AP_STATE_ENABLED; 1429 } 1430 1431 /** 1432 * Gets the Wi-Fi AP Configuration. 1433 * @return AP details in WifiConfiguration 1434 * 1435 * @hide Dont open yet 1436 */ getWifiApConfiguration()1437 public WifiConfiguration getWifiApConfiguration() { 1438 try { 1439 return mService.getWifiApConfiguration(); 1440 } catch (RemoteException e) { 1441 return null; 1442 } 1443 } 1444 1445 /** 1446 * Sets the Wi-Fi AP Configuration. 1447 * @return {@code true} if the operation succeeded, {@code false} otherwise 1448 * 1449 * @hide Dont open yet 1450 */ setWifiApConfiguration(WifiConfiguration wifiConfig)1451 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { 1452 try { 1453 mService.setWifiApConfiguration(wifiConfig); 1454 return true; 1455 } catch (RemoteException e) { 1456 return false; 1457 } 1458 } 1459 1460 /** 1461 * Start the driver and connect to network. 1462 * 1463 * This function will over-ride WifiLock and device idle status. For example, 1464 * even if the device is idle or there is only a scan-only lock held, 1465 * a start wifi would mean that wifi connection is kept active until 1466 * a stopWifi() is sent. 1467 * 1468 * This API is used by WifiStateTracker 1469 * 1470 * @return {@code true} if the operation succeeds else {@code false} 1471 * @hide 1472 */ startWifi()1473 public boolean startWifi() { 1474 try { 1475 mService.startWifi(); 1476 return true; 1477 } catch (RemoteException e) { 1478 return false; 1479 } 1480 } 1481 1482 /** 1483 * Disconnect from a network (if any) and stop the driver. 1484 * 1485 * This function will over-ride WifiLock and device idle status. Wi-Fi 1486 * stays inactive until a startWifi() is issued. 1487 * 1488 * This API is used by WifiStateTracker 1489 * 1490 * @return {@code true} if the operation succeeds else {@code false} 1491 * @hide 1492 */ stopWifi()1493 public boolean stopWifi() { 1494 try { 1495 mService.stopWifi(); 1496 return true; 1497 } catch (RemoteException e) { 1498 return false; 1499 } 1500 } 1501 1502 /** 1503 * Add a bssid to the supplicant blacklist 1504 * 1505 * This API is used by WifiWatchdogService 1506 * 1507 * @return {@code true} if the operation succeeds else {@code false} 1508 * @hide 1509 */ addToBlacklist(String bssid)1510 public boolean addToBlacklist(String bssid) { 1511 try { 1512 mService.addToBlacklist(bssid); 1513 return true; 1514 } catch (RemoteException e) { 1515 return false; 1516 } 1517 } 1518 1519 /** 1520 * Clear the supplicant blacklist 1521 * 1522 * This API is used by WifiWatchdogService 1523 * 1524 * @return {@code true} if the operation succeeds else {@code false} 1525 * @hide 1526 */ clearBlacklist()1527 public boolean clearBlacklist() { 1528 try { 1529 mService.clearBlacklist(); 1530 return true; 1531 } catch (RemoteException e) { 1532 return false; 1533 } 1534 } 1535 1536 1537 /** 1538 * Enable/Disable TDLS on a specific local route. 1539 * 1540 * <p> 1541 * TDLS enables two wireless endpoints to talk to each other directly 1542 * without going through the access point that is managing the local 1543 * network. It saves bandwidth and improves quality of the link. 1544 * </p> 1545 * <p> 1546 * This API enables/disables the option of using TDLS. If enabled, the 1547 * underlying hardware is free to use TDLS or a hop through the access 1548 * point. If disabled, existing TDLS session is torn down and 1549 * hardware is restricted to use access point for transferring wireless 1550 * packets. Default value for all routes is 'disabled', meaning restricted 1551 * to use access point for transferring packets. 1552 * </p> 1553 * 1554 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 1555 * @param enable true = setup and false = tear down TDLS 1556 */ setTdlsEnabled(InetAddress remoteIPAddress, boolean enable)1557 public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) { 1558 try { 1559 mService.enableTdls(remoteIPAddress.getHostAddress(), enable); 1560 } catch (RemoteException e) { 1561 // Just ignore the exception 1562 } 1563 } 1564 1565 /** 1566 * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except 1567 * this version allows you to specify remote endpoint with a MAC address. 1568 * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab 1569 * @param enable true = setup and false = tear down TDLS 1570 */ setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable)1571 public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) { 1572 try { 1573 mService.enableTdlsWithMacAddress(remoteMacAddress, enable); 1574 } catch (RemoteException e) { 1575 // Just ignore the exception 1576 } 1577 } 1578 1579 /* TODO: deprecate synchronous API and open up the following API */ 1580 1581 private static final int BASE = Protocol.BASE_WIFI_MANAGER; 1582 1583 /* Commands to WifiService */ 1584 /** @hide */ 1585 public static final int CONNECT_NETWORK = BASE + 1; 1586 /** @hide */ 1587 public static final int CONNECT_NETWORK_FAILED = BASE + 2; 1588 /** @hide */ 1589 public static final int CONNECT_NETWORK_SUCCEEDED = BASE + 3; 1590 1591 /** @hide */ 1592 public static final int FORGET_NETWORK = BASE + 4; 1593 /** @hide */ 1594 public static final int FORGET_NETWORK_FAILED = BASE + 5; 1595 /** @hide */ 1596 public static final int FORGET_NETWORK_SUCCEEDED = BASE + 6; 1597 1598 /** @hide */ 1599 public static final int SAVE_NETWORK = BASE + 7; 1600 /** @hide */ 1601 public static final int SAVE_NETWORK_FAILED = BASE + 8; 1602 /** @hide */ 1603 public static final int SAVE_NETWORK_SUCCEEDED = BASE + 9; 1604 1605 /** @hide */ 1606 public static final int START_WPS = BASE + 10; 1607 /** @hide */ 1608 public static final int START_WPS_SUCCEEDED = BASE + 11; 1609 /** @hide */ 1610 public static final int WPS_FAILED = BASE + 12; 1611 /** @hide */ 1612 public static final int WPS_COMPLETED = BASE + 13; 1613 1614 /** @hide */ 1615 public static final int CANCEL_WPS = BASE + 14; 1616 /** @hide */ 1617 public static final int CANCEL_WPS_FAILED = BASE + 15; 1618 /** @hide */ 1619 public static final int CANCEL_WPS_SUCCEDED = BASE + 16; 1620 1621 /** @hide */ 1622 public static final int DISABLE_NETWORK = BASE + 17; 1623 /** @hide */ 1624 public static final int DISABLE_NETWORK_FAILED = BASE + 18; 1625 /** @hide */ 1626 public static final int DISABLE_NETWORK_SUCCEEDED = BASE + 19; 1627 1628 /** @hide */ 1629 public static final int RSSI_PKTCNT_FETCH = BASE + 20; 1630 /** @hide */ 1631 public static final int RSSI_PKTCNT_FETCH_SUCCEEDED = BASE + 21; 1632 /** @hide */ 1633 public static final int RSSI_PKTCNT_FETCH_FAILED = BASE + 22; 1634 1635 /** 1636 * Passed with {@link ActionListener#onFailure}. 1637 * Indicates that the operation failed due to an internal error. 1638 * @hide 1639 */ 1640 public static final int ERROR = 0; 1641 1642 /** 1643 * Passed with {@link ActionListener#onFailure}. 1644 * Indicates that the operation is already in progress 1645 * @hide 1646 */ 1647 public static final int IN_PROGRESS = 1; 1648 1649 /** 1650 * Passed with {@link ActionListener#onFailure}. 1651 * Indicates that the operation failed because the framework is busy and 1652 * unable to service the request 1653 * @hide 1654 */ 1655 public static final int BUSY = 2; 1656 1657 /* WPS specific errors */ 1658 /** WPS overlap detected */ 1659 public static final int WPS_OVERLAP_ERROR = 3; 1660 /** WEP on WPS is prohibited */ 1661 public static final int WPS_WEP_PROHIBITED = 4; 1662 /** TKIP only prohibited */ 1663 public static final int WPS_TKIP_ONLY_PROHIBITED = 5; 1664 /** Authentication failure on WPS */ 1665 public static final int WPS_AUTH_FAILURE = 6; 1666 /** WPS timed out */ 1667 public static final int WPS_TIMED_OUT = 7; 1668 1669 /** 1670 * Passed with {@link ActionListener#onFailure}. 1671 * Indicates that the operation failed due to invalid inputs 1672 * @hide 1673 */ 1674 public static final int INVALID_ARGS = 8; 1675 1676 /** 1677 * Passed with {@link ActionListener#onFailure}. 1678 * Indicates that the operation failed due to user permissions. 1679 * @hide 1680 */ 1681 public static final int NOT_AUTHORIZED = 9; 1682 1683 /** 1684 * Interface for callback invocation on an application action 1685 * @hide 1686 */ 1687 public interface ActionListener { 1688 /** The operation succeeded */ onSuccess()1689 public void onSuccess(); 1690 /** 1691 * The operation failed 1692 * @param reason The reason for failure could be one of 1693 * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY} 1694 */ onFailure(int reason)1695 public void onFailure(int reason); 1696 } 1697 1698 /** Interface for callback invocation on a start WPS action */ 1699 public static abstract class WpsCallback { 1700 /** WPS start succeeded */ onStarted(String pin)1701 public abstract void onStarted(String pin); 1702 1703 /** WPS operation completed succesfully */ onSucceeded()1704 public abstract void onSucceeded(); 1705 1706 /** 1707 * WPS operation failed 1708 * @param reason The reason for failure could be one of 1709 * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR}, 1710 * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE} 1711 * and some generic errors. 1712 */ onFailed(int reason)1713 public abstract void onFailed(int reason); 1714 } 1715 1716 /** Interface for callback invocation on a TX packet count poll action {@hide} */ 1717 public interface TxPacketCountListener { 1718 /** 1719 * The operation succeeded 1720 * @param count TX packet counter 1721 */ onSuccess(int count)1722 public void onSuccess(int count); 1723 /** 1724 * The operation failed 1725 * @param reason The reason for failure could be one of 1726 * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY} 1727 */ onFailure(int reason)1728 public void onFailure(int reason); 1729 } 1730 1731 private static class ServiceHandler extends Handler { ServiceHandler(Looper looper)1732 ServiceHandler(Looper looper) { 1733 super(looper); 1734 } 1735 1736 @Override handleMessage(Message message)1737 public void handleMessage(Message message) { 1738 Object listener = removeListener(message.arg2); 1739 switch (message.what) { 1740 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 1741 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 1742 sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 1743 } else { 1744 Log.e(TAG, "Failed to set up channel connection"); 1745 // This will cause all further async API calls on the WifiManager 1746 // to fail and throw an exception 1747 sAsyncChannel = null; 1748 } 1749 sConnected.countDown(); 1750 break; 1751 case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: 1752 // Ignore 1753 break; 1754 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 1755 Log.e(TAG, "Channel connection lost"); 1756 // This will cause all further async API calls on the WifiManager 1757 // to fail and throw an exception 1758 sAsyncChannel = null; 1759 getLooper().quit(); 1760 break; 1761 /* ActionListeners grouped together */ 1762 case WifiManager.CONNECT_NETWORK_FAILED: 1763 case WifiManager.FORGET_NETWORK_FAILED: 1764 case WifiManager.SAVE_NETWORK_FAILED: 1765 case WifiManager.DISABLE_NETWORK_FAILED: 1766 if (listener != null) { 1767 ((ActionListener) listener).onFailure(message.arg1); 1768 } 1769 break; 1770 /* ActionListeners grouped together */ 1771 case WifiManager.CONNECT_NETWORK_SUCCEEDED: 1772 case WifiManager.FORGET_NETWORK_SUCCEEDED: 1773 case WifiManager.SAVE_NETWORK_SUCCEEDED: 1774 case WifiManager.DISABLE_NETWORK_SUCCEEDED: 1775 if (listener != null) { 1776 ((ActionListener) listener).onSuccess(); 1777 } 1778 break; 1779 case WifiManager.START_WPS_SUCCEEDED: 1780 if (listener != null) { 1781 WpsResult result = (WpsResult) message.obj; 1782 ((WpsCallback) listener).onStarted(result.pin); 1783 //Listener needs to stay until completion or failure 1784 synchronized(sListenerMapLock) { 1785 sListenerMap.put(message.arg2, listener); 1786 } 1787 } 1788 break; 1789 case WifiManager.WPS_COMPLETED: 1790 if (listener != null) { 1791 ((WpsCallback) listener).onSucceeded(); 1792 } 1793 break; 1794 case WifiManager.WPS_FAILED: 1795 if (listener != null) { 1796 ((WpsCallback) listener).onFailed(message.arg1); 1797 } 1798 break; 1799 case WifiManager.CANCEL_WPS_SUCCEDED: 1800 if (listener != null) { 1801 ((WpsCallback) listener).onSucceeded(); 1802 } 1803 break; 1804 case WifiManager.CANCEL_WPS_FAILED: 1805 if (listener != null) { 1806 ((WpsCallback) listener).onFailed(message.arg1); 1807 } 1808 break; 1809 case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED: 1810 if (listener != null) { 1811 RssiPacketCountInfo info = (RssiPacketCountInfo) message.obj; 1812 if (info != null) 1813 ((TxPacketCountListener) listener).onSuccess(info.txgood + info.txbad); 1814 else 1815 ((TxPacketCountListener) listener).onFailure(ERROR); 1816 } 1817 break; 1818 case WifiManager.RSSI_PKTCNT_FETCH_FAILED: 1819 if (listener != null) { 1820 ((TxPacketCountListener) listener).onFailure(message.arg1); 1821 } 1822 break; 1823 default: 1824 //ignore 1825 break; 1826 } 1827 } 1828 } 1829 putListener(Object listener)1830 private static int putListener(Object listener) { 1831 if (listener == null) return INVALID_KEY; 1832 int key; 1833 synchronized (sListenerMapLock) { 1834 do { 1835 key = sListenerKey++; 1836 } while (key == INVALID_KEY); 1837 sListenerMap.put(key, listener); 1838 } 1839 return key; 1840 } 1841 removeListener(int key)1842 private static Object removeListener(int key) { 1843 if (key == INVALID_KEY) return null; 1844 synchronized (sListenerMapLock) { 1845 Object listener = sListenerMap.get(key); 1846 sListenerMap.remove(key); 1847 return listener; 1848 } 1849 } 1850 init()1851 private void init() { 1852 synchronized (sThreadRefLock) { 1853 if (++sThreadRefCount == 1) { 1854 Messenger messenger = getWifiServiceMessenger(); 1855 if (messenger == null) { 1856 sAsyncChannel = null; 1857 return; 1858 } 1859 1860 sHandlerThread = new HandlerThread("WifiManager"); 1861 sAsyncChannel = new AsyncChannel(); 1862 sConnected = new CountDownLatch(1); 1863 1864 sHandlerThread.start(); 1865 Handler handler = new ServiceHandler(sHandlerThread.getLooper()); 1866 sAsyncChannel.connect(mContext, handler, messenger); 1867 try { 1868 sConnected.await(); 1869 } catch (InterruptedException e) { 1870 Log.e(TAG, "interrupted wait at init"); 1871 } 1872 } 1873 } 1874 } 1875 validateChannel()1876 private void validateChannel() { 1877 if (sAsyncChannel == null) throw new IllegalStateException( 1878 "No permission to access and change wifi or a bad initialization"); 1879 } 1880 1881 /** 1882 * Connect to a network with the given configuration. The network also 1883 * gets added to the supplicant configuration. 1884 * 1885 * For a new network, this function is used instead of a 1886 * sequence of addNetwork(), enableNetwork(), saveConfiguration() and 1887 * reconnect() 1888 * 1889 * @param config the set of variables that describe the configuration, 1890 * contained in a {@link WifiConfiguration} object. 1891 * @param listener for callbacks on success or failure. Can be null. 1892 * @throws IllegalStateException if the WifiManager instance needs to be 1893 * initialized again 1894 * 1895 * @hide 1896 */ connect(WifiConfiguration config, ActionListener listener)1897 public void connect(WifiConfiguration config, ActionListener listener) { 1898 if (config == null) throw new IllegalArgumentException("config cannot be null"); 1899 validateChannel(); 1900 // Use INVALID_NETWORK_ID for arg1 when passing a config object 1901 // arg1 is used to pass network id when the network already exists 1902 sAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, 1903 putListener(listener), config); 1904 } 1905 1906 /** 1907 * Connect to a network with the given networkId. 1908 * 1909 * This function is used instead of a enableNetwork(), saveConfiguration() and 1910 * reconnect() 1911 * 1912 * @param networkId the network id identifiying the network in the 1913 * supplicant configuration list 1914 * @param listener for callbacks on success or failure. Can be null. 1915 * @throws IllegalStateException if the WifiManager instance needs to be 1916 * initialized again 1917 * @hide 1918 */ connect(int networkId, ActionListener listener)1919 public void connect(int networkId, ActionListener listener) { 1920 if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 1921 validateChannel(); 1922 sAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener)); 1923 } 1924 1925 /** 1926 * Save the given network in the supplicant config. If the network already 1927 * exists, the configuration is updated. A new network is enabled 1928 * by default. 1929 * 1930 * For a new network, this function is used instead of a 1931 * sequence of addNetwork(), enableNetwork() and saveConfiguration(). 1932 * 1933 * For an existing network, it accomplishes the task of updateNetwork() 1934 * and saveConfiguration() 1935 * 1936 * @param config the set of variables that describe the configuration, 1937 * contained in a {@link WifiConfiguration} object. 1938 * @param listener for callbacks on success or failure. Can be null. 1939 * @throws IllegalStateException if the WifiManager instance needs to be 1940 * initialized again 1941 * @hide 1942 */ save(WifiConfiguration config, ActionListener listener)1943 public void save(WifiConfiguration config, ActionListener listener) { 1944 if (config == null) throw new IllegalArgumentException("config cannot be null"); 1945 validateChannel(); 1946 sAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config); 1947 } 1948 1949 /** 1950 * Delete the network in the supplicant config. 1951 * 1952 * This function is used instead of a sequence of removeNetwork() 1953 * and saveConfiguration(). 1954 * 1955 * @param config the set of variables that describe the configuration, 1956 * contained in a {@link WifiConfiguration} object. 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 */ forget(int netId, ActionListener listener)1962 public void forget(int netId, ActionListener listener) { 1963 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 1964 validateChannel(); 1965 sAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener)); 1966 } 1967 1968 /** 1969 * Disable network 1970 * 1971 * @param netId is the network Id 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 * @hide 1976 */ disable(int netId, ActionListener listener)1977 public void disable(int netId, ActionListener listener) { 1978 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 1979 validateChannel(); 1980 sAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener)); 1981 } 1982 1983 /** 1984 * Disable ephemeral Network 1985 * 1986 * @param SSID, in the format of WifiConfiguration's SSID. 1987 * @hide 1988 */ disableEphemeralNetwork(String SSID)1989 public void disableEphemeralNetwork(String SSID) { 1990 if (SSID == null) throw new IllegalArgumentException("SSID cannot be null"); 1991 try { 1992 mService.disableEphemeralNetwork(SSID); 1993 } catch (RemoteException e) { 1994 } 1995 } 1996 1997 /** 1998 * Start Wi-fi Protected Setup 1999 * 2000 * @param config WPS configuration (does not support {@link WpsInfo#LABEL}) 2001 * @param listener for callbacks on success or failure. Can be null. 2002 * @throws IllegalStateException if the WifiManager instance needs to be 2003 * initialized again 2004 */ startWps(WpsInfo config, WpsCallback listener)2005 public void startWps(WpsInfo config, WpsCallback listener) { 2006 if (config == null) throw new IllegalArgumentException("config cannot be null"); 2007 validateChannel(); 2008 sAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config); 2009 } 2010 2011 /** 2012 * Cancel any ongoing Wi-fi Protected Setup 2013 * 2014 * @param listener for callbacks on success or failure. Can be null. 2015 * @throws IllegalStateException if the WifiManager instance needs to be 2016 * initialized again 2017 */ cancelWps(WpsCallback listener)2018 public void cancelWps(WpsCallback listener) { 2019 validateChannel(); 2020 sAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener)); 2021 } 2022 2023 /** 2024 * Get a reference to WifiService handler. This is used by a client to establish 2025 * an AsyncChannel communication with WifiService 2026 * 2027 * @return Messenger pointing to the WifiService handler 2028 * @hide 2029 */ getWifiServiceMessenger()2030 public Messenger getWifiServiceMessenger() { 2031 try { 2032 return mService.getWifiServiceMessenger(); 2033 } catch (RemoteException e) { 2034 return null; 2035 } catch (SecurityException e) { 2036 return null; 2037 } 2038 } 2039 2040 2041 /** 2042 * Returns the file in which IP and proxy configuration data is stored 2043 * @hide 2044 */ getConfigFile()2045 public String getConfigFile() { 2046 try { 2047 return mService.getConfigFile(); 2048 } catch (RemoteException e) { 2049 return null; 2050 } 2051 } 2052 2053 /** 2054 * Allows an application to keep the Wi-Fi radio awake. 2055 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 2056 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 2057 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 2058 * WifiLocks are held in any application. 2059 * <p> 2060 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 2061 * could function over a mobile network, if available. A program that needs to download large 2062 * files should hold a WifiLock to ensure that the download will complete, but a program whose 2063 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 2064 * affecting battery life. 2065 * <p> 2066 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 2067 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 2068 * is idle. 2069 * <p> 2070 * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK} 2071 * permission in an {@code <uses-permission>} element of the application's manifest. 2072 */ 2073 public class WifiLock { 2074 private String mTag; 2075 private final IBinder mBinder; 2076 private int mRefCount; 2077 int mLockType; 2078 private boolean mRefCounted; 2079 private boolean mHeld; 2080 private WorkSource mWorkSource; 2081 WifiLock(int lockType, String tag)2082 private WifiLock(int lockType, String tag) { 2083 mTag = tag; 2084 mLockType = lockType; 2085 mBinder = new Binder(); 2086 mRefCount = 0; 2087 mRefCounted = true; 2088 mHeld = false; 2089 } 2090 2091 /** 2092 * Locks the Wi-Fi radio on until {@link #release} is called. 2093 * 2094 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 2095 * reference count, and the radio will remain locked as long as the reference count is 2096 * above zero. 2097 * 2098 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 2099 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 2100 * will be required, regardless of the number of times that {@code acquire} is called. 2101 */ acquire()2102 public void acquire() { 2103 synchronized (mBinder) { 2104 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 2105 try { 2106 mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); 2107 synchronized (WifiManager.this) { 2108 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 2109 mService.releaseWifiLock(mBinder); 2110 throw new UnsupportedOperationException( 2111 "Exceeded maximum number of wifi locks"); 2112 } 2113 mActiveLockCount++; 2114 } 2115 } catch (RemoteException ignore) { 2116 } 2117 mHeld = true; 2118 } 2119 } 2120 } 2121 2122 /** 2123 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 2124 * 2125 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 2126 * reference count, and the radio will be unlocked only when the reference count reaches 2127 * zero. If the reference count goes below zero (that is, if {@code release} is called 2128 * a greater number of times than {@link #acquire}), an exception is thrown. 2129 * 2130 * If this WifiLock is not reference-counted, the first call to {@code release} (after 2131 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 2132 * calls will be ignored. 2133 */ release()2134 public void release() { 2135 synchronized (mBinder) { 2136 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 2137 try { 2138 mService.releaseWifiLock(mBinder); 2139 synchronized (WifiManager.this) { 2140 mActiveLockCount--; 2141 } 2142 } catch (RemoteException ignore) { 2143 } 2144 mHeld = false; 2145 } 2146 if (mRefCount < 0) { 2147 throw new RuntimeException("WifiLock under-locked " + mTag); 2148 } 2149 } 2150 } 2151 2152 /** 2153 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 2154 * 2155 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 2156 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 2157 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 2158 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 2159 * radio whenever {@link #release} is called and it is locked. 2160 * 2161 * @param refCounted true if this WifiLock should keep a reference count 2162 */ setReferenceCounted(boolean refCounted)2163 public void setReferenceCounted(boolean refCounted) { 2164 mRefCounted = refCounted; 2165 } 2166 2167 /** 2168 * Checks whether this WifiLock is currently held. 2169 * 2170 * @return true if this WifiLock is held, false otherwise 2171 */ isHeld()2172 public boolean isHeld() { 2173 synchronized (mBinder) { 2174 return mHeld; 2175 } 2176 } 2177 setWorkSource(WorkSource ws)2178 public void setWorkSource(WorkSource ws) { 2179 synchronized (mBinder) { 2180 if (ws != null && ws.size() == 0) { 2181 ws = null; 2182 } 2183 boolean changed = true; 2184 if (ws == null) { 2185 mWorkSource = null; 2186 } else { 2187 ws.clearNames(); 2188 if (mWorkSource == null) { 2189 changed = mWorkSource != null; 2190 mWorkSource = new WorkSource(ws); 2191 } else { 2192 changed = mWorkSource.diff(ws); 2193 if (changed) { 2194 mWorkSource.set(ws); 2195 } 2196 } 2197 } 2198 if (changed && mHeld) { 2199 try { 2200 mService.updateWifiLockWorkSource(mBinder, mWorkSource); 2201 } catch (RemoteException e) { 2202 } 2203 } 2204 } 2205 } 2206 toString()2207 public String toString() { 2208 String s1, s2, s3; 2209 synchronized (mBinder) { 2210 s1 = Integer.toHexString(System.identityHashCode(this)); 2211 s2 = mHeld ? "held; " : ""; 2212 if (mRefCounted) { 2213 s3 = "refcounted: refcount = " + mRefCount; 2214 } else { 2215 s3 = "not refcounted"; 2216 } 2217 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 2218 } 2219 } 2220 2221 @Override finalize()2222 protected void finalize() throws Throwable { 2223 super.finalize(); 2224 synchronized (mBinder) { 2225 if (mHeld) { 2226 try { 2227 mService.releaseWifiLock(mBinder); 2228 synchronized (WifiManager.this) { 2229 mActiveLockCount--; 2230 } 2231 } catch (RemoteException ignore) { 2232 } 2233 } 2234 } 2235 } 2236 } 2237 2238 /** 2239 * Creates a new WifiLock. 2240 * 2241 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL}, 2242 * {@link #WIFI_MODE_FULL_HIGH_PERF} and {@link #WIFI_MODE_SCAN_ONLY} for 2243 * descriptions of the types of Wi-Fi locks. 2244 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 2245 * never shown to the user under normal conditions, but should be descriptive 2246 * enough to identify your application and the specific WifiLock within it, if it 2247 * holds multiple WifiLocks. 2248 * 2249 * @return a new, unacquired WifiLock with the given tag. 2250 * 2251 * @see WifiLock 2252 */ createWifiLock(int lockType, String tag)2253 public WifiLock createWifiLock(int lockType, String tag) { 2254 return new WifiLock(lockType, tag); 2255 } 2256 2257 /** 2258 * Creates a new WifiLock. 2259 * 2260 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 2261 * never shown to the user under normal conditions, but should be descriptive 2262 * enough to identify your application and the specific WifiLock within it, if it 2263 * holds multiple WifiLocks. 2264 * 2265 * @return a new, unacquired WifiLock with the given tag. 2266 * 2267 * @see WifiLock 2268 */ createWifiLock(String tag)2269 public WifiLock createWifiLock(String tag) { 2270 return new WifiLock(WIFI_MODE_FULL, tag); 2271 } 2272 2273 2274 /** 2275 * Create a new MulticastLock 2276 * 2277 * @param tag a tag for the MulticastLock to identify it in debugging 2278 * messages. This string is never shown to the user under 2279 * normal conditions, but should be descriptive enough to 2280 * identify your application and the specific MulticastLock 2281 * within it, if it holds multiple MulticastLocks. 2282 * 2283 * @return a new, unacquired MulticastLock with the given tag. 2284 * 2285 * @see MulticastLock 2286 */ createMulticastLock(String tag)2287 public MulticastLock createMulticastLock(String tag) { 2288 return new MulticastLock(tag); 2289 } 2290 2291 /** 2292 * Allows an application to receive Wifi Multicast packets. 2293 * Normally the Wifi stack filters out packets not explicitly 2294 * addressed to this device. Acquring a MulticastLock will 2295 * cause the stack to receive packets addressed to multicast 2296 * addresses. Processing these extra packets can cause a noticable 2297 * battery drain and should be disabled when not needed. 2298 */ 2299 public class MulticastLock { 2300 private String mTag; 2301 private final IBinder mBinder; 2302 private int mRefCount; 2303 private boolean mRefCounted; 2304 private boolean mHeld; 2305 MulticastLock(String tag)2306 private MulticastLock(String tag) { 2307 mTag = tag; 2308 mBinder = new Binder(); 2309 mRefCount = 0; 2310 mRefCounted = true; 2311 mHeld = false; 2312 } 2313 2314 /** 2315 * Locks Wifi Multicast on until {@link #release} is called. 2316 * 2317 * If this MulticastLock is reference-counted each call to 2318 * {@code acquire} will increment the reference count, and the 2319 * wifi interface will receive multicast packets as long as the 2320 * reference count is above zero. 2321 * 2322 * If this MulticastLock is not reference-counted, the first call to 2323 * {@code acquire} will turn on the multicast packets, but subsequent 2324 * calls will be ignored. Only one call to {@link #release} will 2325 * be required, regardless of the number of times that {@code acquire} 2326 * is called. 2327 * 2328 * Note that other applications may also lock Wifi Multicast on. 2329 * Only they can relinquish their lock. 2330 * 2331 * Also note that applications cannot leave Multicast locked on. 2332 * When an app exits or crashes, any Multicast locks will be released. 2333 */ acquire()2334 public void acquire() { 2335 synchronized (mBinder) { 2336 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 2337 try { 2338 mService.acquireMulticastLock(mBinder, mTag); 2339 synchronized (WifiManager.this) { 2340 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 2341 mService.releaseMulticastLock(); 2342 throw new UnsupportedOperationException( 2343 "Exceeded maximum number of wifi locks"); 2344 } 2345 mActiveLockCount++; 2346 } 2347 } catch (RemoteException ignore) { 2348 } 2349 mHeld = true; 2350 } 2351 } 2352 } 2353 2354 /** 2355 * Unlocks Wifi Multicast, restoring the filter of packets 2356 * not addressed specifically to this device and saving power. 2357 * 2358 * If this MulticastLock is reference-counted, each call to 2359 * {@code release} will decrement the reference count, and the 2360 * multicast packets will only stop being received when the reference 2361 * count reaches zero. If the reference count goes below zero (that 2362 * is, if {@code release} is called a greater number of times than 2363 * {@link #acquire}), an exception is thrown. 2364 * 2365 * If this MulticastLock is not reference-counted, the first call to 2366 * {@code release} (after the radio was multicast locked using 2367 * {@link #acquire}) will unlock the multicast, and subsequent calls 2368 * will be ignored. 2369 * 2370 * Note that if any other Wifi Multicast Locks are still outstanding 2371 * this {@code release} call will not have an immediate effect. Only 2372 * when all applications have released all their Multicast Locks will 2373 * the Multicast filter be turned back on. 2374 * 2375 * Also note that when an app exits or crashes all of its Multicast 2376 * Locks will be automatically released. 2377 */ release()2378 public void release() { 2379 synchronized (mBinder) { 2380 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 2381 try { 2382 mService.releaseMulticastLock(); 2383 synchronized (WifiManager.this) { 2384 mActiveLockCount--; 2385 } 2386 } catch (RemoteException ignore) { 2387 } 2388 mHeld = false; 2389 } 2390 if (mRefCount < 0) { 2391 throw new RuntimeException("MulticastLock under-locked " 2392 + mTag); 2393 } 2394 } 2395 } 2396 2397 /** 2398 * Controls whether this is a reference-counted or non-reference- 2399 * counted MulticastLock. 2400 * 2401 * Reference-counted MulticastLocks keep track of the number of calls 2402 * to {@link #acquire} and {@link #release}, and only stop the 2403 * reception of multicast packets when every call to {@link #acquire} 2404 * has been balanced with a call to {@link #release}. Non-reference- 2405 * counted MulticastLocks allow the reception of multicast packets 2406 * whenever {@link #acquire} is called and stop accepting multicast 2407 * packets whenever {@link #release} is called. 2408 * 2409 * @param refCounted true if this MulticastLock should keep a reference 2410 * count 2411 */ setReferenceCounted(boolean refCounted)2412 public void setReferenceCounted(boolean refCounted) { 2413 mRefCounted = refCounted; 2414 } 2415 2416 /** 2417 * Checks whether this MulticastLock is currently held. 2418 * 2419 * @return true if this MulticastLock is held, false otherwise 2420 */ isHeld()2421 public boolean isHeld() { 2422 synchronized (mBinder) { 2423 return mHeld; 2424 } 2425 } 2426 toString()2427 public String toString() { 2428 String s1, s2, s3; 2429 synchronized (mBinder) { 2430 s1 = Integer.toHexString(System.identityHashCode(this)); 2431 s2 = mHeld ? "held; " : ""; 2432 if (mRefCounted) { 2433 s3 = "refcounted: refcount = " + mRefCount; 2434 } else { 2435 s3 = "not refcounted"; 2436 } 2437 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 2438 } 2439 } 2440 2441 @Override finalize()2442 protected void finalize() throws Throwable { 2443 super.finalize(); 2444 setReferenceCounted(false); 2445 release(); 2446 } 2447 } 2448 2449 /** 2450 * Check multicast filter status. 2451 * 2452 * @return true if multicast packets are allowed. 2453 * 2454 * @hide pending API council approval 2455 */ isMulticastEnabled()2456 public boolean isMulticastEnabled() { 2457 try { 2458 return mService.isMulticastEnabled(); 2459 } catch (RemoteException e) { 2460 return false; 2461 } 2462 } 2463 2464 /** 2465 * Initialize the multicast filtering to 'on' 2466 * @hide no intent to publish 2467 */ initializeMulticastFiltering()2468 public boolean initializeMulticastFiltering() { 2469 try { 2470 mService.initializeMulticastFiltering(); 2471 return true; 2472 } catch (RemoteException e) { 2473 return false; 2474 } 2475 } 2476 finalize()2477 protected void finalize() throws Throwable { 2478 try { 2479 synchronized (sThreadRefLock) { 2480 if (--sThreadRefCount == 0 && sAsyncChannel != null) { 2481 sAsyncChannel.disconnect(); 2482 } 2483 } 2484 } finally { 2485 super.finalize(); 2486 } 2487 } 2488 2489 /** 2490 * Set wifi verbose log. Called from developer settings. 2491 * @hide 2492 */ enableVerboseLogging(int verbose)2493 public void enableVerboseLogging (int verbose) { 2494 try { 2495 mService.enableVerboseLogging(verbose); 2496 } catch (Exception e) { 2497 //ignore any failure here 2498 Log.e(TAG, "enableVerboseLogging " + e.toString()); 2499 } 2500 } 2501 2502 /** 2503 * Get the WiFi verbose logging level.This is used by settings 2504 * to decide what to show within the picker. 2505 * @hide 2506 */ getVerboseLoggingLevel()2507 public int getVerboseLoggingLevel() { 2508 try { 2509 return mService.getVerboseLoggingLevel(); 2510 } catch (RemoteException e) { 2511 return 0; 2512 } 2513 } 2514 2515 /** 2516 * Set wifi Aggressive Handover. Called from developer settings. 2517 * @hide 2518 */ enableAggressiveHandover(int enabled)2519 public void enableAggressiveHandover(int enabled) { 2520 try { 2521 mService.enableAggressiveHandover(enabled); 2522 } catch (RemoteException e) { 2523 2524 } 2525 } 2526 2527 /** 2528 * Get the WiFi Handover aggressiveness.This is used by settings 2529 * to decide what to show within the picker. 2530 * @hide 2531 */ getAggressiveHandover()2532 public int getAggressiveHandover() { 2533 try { 2534 return mService.getAggressiveHandover(); 2535 } catch (RemoteException e) { 2536 return 0; 2537 } 2538 } 2539 2540 /** 2541 * Set setting for allowing Scans when traffic is ongoing. 2542 * @hide 2543 */ setAllowScansWithTraffic(int enabled)2544 public void setAllowScansWithTraffic(int enabled) { 2545 try { 2546 mService.setAllowScansWithTraffic(enabled); 2547 } catch (RemoteException e) { 2548 2549 } 2550 } 2551 2552 /** 2553 * Get setting for allowing Scans when traffic is ongoing. 2554 * @hide 2555 */ getAllowScansWithTraffic()2556 public int getAllowScansWithTraffic() { 2557 try { 2558 return mService.getAllowScansWithTraffic(); 2559 } catch (RemoteException e) { 2560 return 0; 2561 } 2562 } 2563 2564 2565 2566 } 2567