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.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SdkConstant; 24 import android.annotation.SuppressLint; 25 import android.annotation.SdkConstant.SdkConstantType; 26 import android.annotation.SystemApi; 27 import android.annotation.SystemService; 28 import android.content.Context; 29 import android.content.pm.ParceledListSlice; 30 import android.net.ConnectivityManager; 31 import android.net.DhcpInfo; 32 import android.net.Network; 33 import android.net.NetworkCapabilities; 34 import android.net.NetworkRequest; 35 import android.net.wifi.hotspot2.OsuProvider; 36 import android.net.wifi.hotspot2.PasspointConfiguration; 37 import android.net.wifi.hotspot2.IProvisioningCallback; 38 import android.net.wifi.hotspot2.ProvisioningCallback; 39 import android.os.Binder; 40 import android.os.Build; 41 import android.os.Handler; 42 import android.os.IBinder; 43 import android.os.Looper; 44 import android.os.Message; 45 import android.os.Messenger; 46 import android.os.RemoteException; 47 import android.os.WorkSource; 48 import android.util.Log; 49 import android.util.SparseArray; 50 51 import com.android.internal.annotations.GuardedBy; 52 import com.android.internal.annotations.VisibleForTesting; 53 import com.android.internal.util.AsyncChannel; 54 import com.android.internal.util.Protocol; 55 import com.android.server.net.NetworkPinner; 56 57 import dalvik.system.CloseGuard; 58 59 import java.lang.annotation.Retention; 60 import java.lang.annotation.RetentionPolicy; 61 import java.lang.ref.WeakReference; 62 import java.net.InetAddress; 63 import java.util.Collections; 64 import java.util.List; 65 import java.util.concurrent.CountDownLatch; 66 67 /** 68 * This class provides the primary API for managing all aspects of Wi-Fi 69 * connectivity. 70 * <p> 71 * On releases before {@link android.os.Build.VERSION_CODES#N}, this object 72 * should only be obtained from an {@linkplain Context#getApplicationContext() 73 * application context}, and not from any other derived context to avoid memory 74 * leaks within the calling process. 75 * <p> 76 * It deals with several categories of items: 77 * </p> 78 * <ul> 79 * <li>The list of configured networks. The list can be viewed and updated, and 80 * attributes of individual entries can be modified.</li> 81 * <li>The currently active Wi-Fi network, if any. Connectivity can be 82 * established or torn down, and dynamic information about the state of the 83 * network can be queried.</li> 84 * <li>Results of access point scans, containing enough information to make 85 * decisions about what access point to connect to.</li> 86 * <li>It defines the names of various Intent actions that are broadcast upon 87 * any sort of change in Wi-Fi state. 88 * </ul> 89 * <p> 90 * This is the API to use when performing Wi-Fi specific operations. To perform 91 * operations that pertain to network connectivity at an abstract level, use 92 * {@link android.net.ConnectivityManager}. 93 * </p> 94 */ 95 @SystemService(Context.WIFI_SERVICE) 96 public class WifiManager { 97 98 private static final String TAG = "WifiManager"; 99 // Supplicant error codes: 100 /** 101 * The error code if there was a problem authenticating. 102 * @deprecated This is no longer supported. 103 */ 104 @Deprecated 105 public static final int ERROR_AUTHENTICATING = 1; 106 107 /** 108 * The reason code if there is no error during authentication. 109 * It could also imply that there no authentication in progress, 110 * this reason code also serves as a reset value. 111 * @deprecated This is no longer supported. 112 * @hide 113 */ 114 @Deprecated 115 public static final int ERROR_AUTH_FAILURE_NONE = 0; 116 117 /** 118 * The reason code if there was a timeout authenticating. 119 * @deprecated This is no longer supported. 120 * @hide 121 */ 122 @Deprecated 123 public static final int ERROR_AUTH_FAILURE_TIMEOUT = 1; 124 125 /** 126 * The reason code if there was a wrong password while 127 * authenticating. 128 * @deprecated This is no longer supported. 129 * @hide 130 */ 131 @Deprecated 132 public static final int ERROR_AUTH_FAILURE_WRONG_PSWD = 2; 133 134 /** 135 * The reason code if there was EAP failure while 136 * authenticating. 137 * @deprecated This is no longer supported. 138 * @hide 139 */ 140 @Deprecated 141 public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3; 142 143 /** 144 * Broadcast intent action indicating whether Wi-Fi scanning is allowed currently 145 * @hide 146 */ 147 public static final String WIFI_SCAN_AVAILABLE = "wifi_scan_available"; 148 149 /** 150 * Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED 151 * @hide 152 */ 153 public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled"; 154 155 /** 156 * Broadcast intent action indicating that the credential of a Wi-Fi network 157 * has been changed. One extra provides the ssid of the network. Another 158 * extra provides the event type, whether the credential is saved or forgot. 159 * @hide 160 */ 161 @SystemApi 162 public static final String WIFI_CREDENTIAL_CHANGED_ACTION = 163 "android.net.wifi.WIFI_CREDENTIAL_CHANGED"; 164 /** @hide */ 165 @SystemApi 166 public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et"; 167 /** @hide */ 168 @SystemApi 169 public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid"; 170 /** @hide */ 171 @SystemApi 172 public static final int WIFI_CREDENTIAL_SAVED = 0; 173 /** @hide */ 174 @SystemApi 175 public static final int WIFI_CREDENTIAL_FORGOT = 1; 176 177 /** 178 * Broadcast intent action indicating that a Passpoint provider icon has been received. 179 * 180 * Included extras: 181 * {@link #EXTRA_BSSID_LONG} 182 * {@link #EXTRA_FILENAME} 183 * {@link #EXTRA_ICON} 184 * 185 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 186 * 187 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 188 * components will be launched. 189 * 190 * @hide 191 */ 192 public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; 193 /** 194 * BSSID of an AP in long representation. The {@link #EXTRA_BSSID} contains BSSID in 195 * String representation. 196 * 197 * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}. 198 * 199 * @hide 200 */ 201 public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; 202 /** 203 * Icon data. 204 * 205 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into 206 * {@link android.graphics.drawable.Icon}. 207 * 208 * @hide 209 */ 210 public static final String EXTRA_ICON = "android.net.wifi.extra.ICON"; 211 /** 212 * Name of a file. 213 * 214 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 215 * 216 * @hide 217 */ 218 public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; 219 220 /** 221 * Broadcast intent action indicating a Passpoint OSU Providers List element has been received. 222 * 223 * Included extras: 224 * {@link #EXTRA_BSSID_LONG} 225 * {@link #EXTRA_ANQP_ELEMENT_DATA} 226 * 227 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 228 * 229 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 230 * components will be launched. 231 * 232 * @hide 233 */ 234 public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = 235 "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; 236 /** 237 * Raw binary data of an ANQP (Access Network Query Protocol) element. 238 * 239 * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}. 240 * 241 * @hide 242 */ 243 public static final String EXTRA_ANQP_ELEMENT_DATA = 244 "android.net.wifi.extra.ANQP_ELEMENT_DATA"; 245 246 /** 247 * Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received. 248 * 249 * Included extras: 250 * {@link #EXTRA_BSSID_LONG} 251 * {@link #EXTRA_ESS} 252 * {@link #EXTRA_DELAY} 253 * {@link #EXTRA_URL} 254 * 255 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 256 * 257 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 258 * components will be launched. 259 * 260 * @hide 261 */ 262 public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT = 263 "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; 264 /** 265 * Flag indicating BSS (Basic Service Set) or ESS (Extended Service Set). This will be set to 266 * {@code true} for ESS. 267 * 268 * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}. 269 * 270 * @hide 271 */ 272 public static final String EXTRA_ESS = "android.net.wifi.extra.ESS"; 273 /** 274 * Delay in seconds. 275 * 276 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 277 * 278 * @hide 279 */ 280 public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; 281 /** 282 * String representation of an URL. 283 * 284 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 285 * 286 * @hide 287 */ 288 public static final String EXTRA_URL = "android.net.wifi.extra.URL"; 289 290 /** 291 * Broadcast intent action indicating a Passpoint subscription remediation frame has been 292 * received. 293 * 294 * Included extras: 295 * {@link #EXTRA_BSSID_LONG} 296 * {@link #EXTRA_SUBSCRIPTION_REMEDIATION_METHOD} 297 * {@link #EXTRA_URL} 298 * 299 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 300 * 301 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 302 * components will be launched. 303 * 304 * @hide 305 */ 306 public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = 307 "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; 308 /** 309 * The protocol supported by the subscription remediation server. The possible values are: 310 * 0 - OMA DM 311 * 1 - SOAP XML SPP 312 * 313 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 314 * 315 * @hide 316 */ 317 public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = 318 "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; 319 320 /** 321 * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, 322 * enabling, disabling, or unknown. One extra provides this state as an int. 323 * Another extra provides the previous state, if available. 324 * 325 * @see #EXTRA_WIFI_STATE 326 * @see #EXTRA_PREVIOUS_WIFI_STATE 327 */ 328 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 329 public static final String WIFI_STATE_CHANGED_ACTION = 330 "android.net.wifi.WIFI_STATE_CHANGED"; 331 /** 332 * The lookup key for an int that indicates whether Wi-Fi is enabled, 333 * disabled, enabling, disabling, or unknown. Retrieve it with 334 * {@link android.content.Intent#getIntExtra(String,int)}. 335 * 336 * @see #WIFI_STATE_DISABLED 337 * @see #WIFI_STATE_DISABLING 338 * @see #WIFI_STATE_ENABLED 339 * @see #WIFI_STATE_ENABLING 340 * @see #WIFI_STATE_UNKNOWN 341 */ 342 public static final String EXTRA_WIFI_STATE = "wifi_state"; 343 /** 344 * The previous Wi-Fi state. 345 * 346 * @see #EXTRA_WIFI_STATE 347 */ 348 public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; 349 350 /** 351 * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if 352 * it finishes successfully. 353 * 354 * @see #WIFI_STATE_CHANGED_ACTION 355 * @see #getWifiState() 356 */ 357 public static final int WIFI_STATE_DISABLING = 0; 358 /** 359 * Wi-Fi is disabled. 360 * 361 * @see #WIFI_STATE_CHANGED_ACTION 362 * @see #getWifiState() 363 */ 364 public static final int WIFI_STATE_DISABLED = 1; 365 /** 366 * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if 367 * it finishes successfully. 368 * 369 * @see #WIFI_STATE_CHANGED_ACTION 370 * @see #getWifiState() 371 */ 372 public static final int WIFI_STATE_ENABLING = 2; 373 /** 374 * Wi-Fi is enabled. 375 * 376 * @see #WIFI_STATE_CHANGED_ACTION 377 * @see #getWifiState() 378 */ 379 public static final int WIFI_STATE_ENABLED = 3; 380 /** 381 * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling 382 * or disabling. 383 * 384 * @see #WIFI_STATE_CHANGED_ACTION 385 * @see #getWifiState() 386 */ 387 public static final int WIFI_STATE_UNKNOWN = 4; 388 389 /** 390 * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled, 391 * enabling, disabling, or failed. 392 * 393 * @hide 394 */ 395 @SystemApi 396 public static final String WIFI_AP_STATE_CHANGED_ACTION = 397 "android.net.wifi.WIFI_AP_STATE_CHANGED"; 398 399 /** 400 * The lookup key for an int that indicates whether Wi-Fi AP is enabled, 401 * disabled, enabling, disabling, or failed. Retrieve it with 402 * {@link android.content.Intent#getIntExtra(String,int)}. 403 * 404 * @see #WIFI_AP_STATE_DISABLED 405 * @see #WIFI_AP_STATE_DISABLING 406 * @see #WIFI_AP_STATE_ENABLED 407 * @see #WIFI_AP_STATE_ENABLING 408 * @see #WIFI_AP_STATE_FAILED 409 * 410 * @hide 411 */ 412 @SystemApi 413 public static final String EXTRA_WIFI_AP_STATE = "wifi_state"; 414 415 /** 416 * The look up key for an int that indicates why softAP started failed 417 * currently support general and no_channel 418 * @see #SAP_START_FAILURE_GENERIC 419 * @see #SAP_START_FAILURE_NO_CHANNEL 420 * 421 * @hide 422 */ 423 public static final String EXTRA_WIFI_AP_FAILURE_REASON = "wifi_ap_error_code"; 424 /** 425 * The previous Wi-Fi state. 426 * 427 * @see #EXTRA_WIFI_AP_STATE 428 * 429 * @hide 430 */ 431 @SystemApi 432 public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; 433 /** 434 * The interface used for the softap. 435 * 436 * @hide 437 */ 438 public static final String EXTRA_WIFI_AP_INTERFACE_NAME = "wifi_ap_interface_name"; 439 /** 440 * The intended ip mode for this softap. 441 * @see #IFACE_IP_MODE_TETHERED 442 * @see #IFACE_IP_MODE_LOCAL_ONLY 443 * 444 * @hide 445 */ 446 public static final String EXTRA_WIFI_AP_MODE = "wifi_ap_mode"; 447 448 /** @hide */ 449 @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = { 450 WIFI_AP_STATE_DISABLING, 451 WIFI_AP_STATE_DISABLED, 452 WIFI_AP_STATE_ENABLING, 453 WIFI_AP_STATE_ENABLED, 454 WIFI_AP_STATE_FAILED, 455 }) 456 @Retention(RetentionPolicy.SOURCE) 457 public @interface WifiApState {} 458 459 /** 460 * Wi-Fi AP is currently being disabled. The state will change to 461 * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully. 462 * 463 * @see #WIFI_AP_STATE_CHANGED_ACTION 464 * @see #getWifiApState() 465 * 466 * @hide 467 */ 468 @SystemApi 469 public static final int WIFI_AP_STATE_DISABLING = 10; 470 /** 471 * Wi-Fi AP is disabled. 472 * 473 * @see #WIFI_AP_STATE_CHANGED_ACTION 474 * @see #getWifiState() 475 * 476 * @hide 477 */ 478 @SystemApi 479 public static final int WIFI_AP_STATE_DISABLED = 11; 480 /** 481 * Wi-Fi AP is currently being enabled. The state will change to 482 * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully. 483 * 484 * @see #WIFI_AP_STATE_CHANGED_ACTION 485 * @see #getWifiApState() 486 * 487 * @hide 488 */ 489 @SystemApi 490 public static final int WIFI_AP_STATE_ENABLING = 12; 491 /** 492 * Wi-Fi AP is enabled. 493 * 494 * @see #WIFI_AP_STATE_CHANGED_ACTION 495 * @see #getWifiApState() 496 * 497 * @hide 498 */ 499 @SystemApi 500 public static final int WIFI_AP_STATE_ENABLED = 13; 501 /** 502 * Wi-Fi AP is in a failed state. This state will occur when an error occurs during 503 * enabling or disabling 504 * 505 * @see #WIFI_AP_STATE_CHANGED_ACTION 506 * @see #getWifiApState() 507 * 508 * @hide 509 */ 510 @SystemApi 511 public static final int WIFI_AP_STATE_FAILED = 14; 512 513 /** @hide */ 514 @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = { 515 SAP_START_FAILURE_GENERAL, 516 SAP_START_FAILURE_NO_CHANNEL, 517 }) 518 @Retention(RetentionPolicy.SOURCE) 519 public @interface SapStartFailure {} 520 521 /** 522 * If WIFI AP start failed, this reason code means there is no legal channel exists on 523 * user selected band by regulatory 524 * 525 * @hide 526 */ 527 public static final int SAP_START_FAILURE_GENERAL= 0; 528 529 /** 530 * All other reason for AP start failed besides SAP_START_FAILURE_GENERAL 531 * 532 * @hide 533 */ 534 public static final int SAP_START_FAILURE_NO_CHANNEL = 1; 535 536 /** 537 * Interface IP mode unspecified. 538 * 539 * @see updateInterfaceIpState(String, int) 540 * 541 * @hide 542 */ 543 public static final int IFACE_IP_MODE_UNSPECIFIED = -1; 544 545 /** 546 * Interface IP mode for configuration error. 547 * 548 * @see updateInterfaceIpState(String, int) 549 * 550 * @hide 551 */ 552 public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; 553 554 /** 555 * Interface IP mode for tethering. 556 * 557 * @see updateInterfaceIpState(String, int) 558 * 559 * @hide 560 */ 561 public static final int IFACE_IP_MODE_TETHERED = 1; 562 563 /** 564 * Interface IP mode for Local Only Hotspot. 565 * 566 * @see updateInterfaceIpState(String, int) 567 * 568 * @hide 569 */ 570 public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; 571 572 /** 573 * Broadcast intent action indicating that a connection to the supplicant has 574 * been established (and it is now possible 575 * to perform Wi-Fi operations) or the connection to the supplicant has been 576 * lost. One extra provides the connection state as a boolean, where {@code true} 577 * means CONNECTED. 578 * @deprecated This is no longer supported. 579 * @see #EXTRA_SUPPLICANT_CONNECTED 580 */ 581 @Deprecated 582 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 583 public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = 584 "android.net.wifi.supplicant.CONNECTION_CHANGE"; 585 /** 586 * The lookup key for a boolean that indicates whether a connection to 587 * the supplicant daemon has been gained or lost. {@code true} means 588 * a connection now exists. 589 * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. 590 * @deprecated This is no longer supported. 591 */ 592 @Deprecated 593 public static final String EXTRA_SUPPLICANT_CONNECTED = "connected"; 594 /** 595 * Broadcast intent action indicating that the state of Wi-Fi connectivity 596 * has changed. An extra provides the new state 597 * in the form of a {@link android.net.NetworkInfo} object. 598 * @see #EXTRA_NETWORK_INFO 599 */ 600 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 601 public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"; 602 /** 603 * The lookup key for a {@link android.net.NetworkInfo} object associated with the 604 * Wi-Fi network. Retrieve with 605 * {@link android.content.Intent#getParcelableExtra(String)}. 606 */ 607 public static final String EXTRA_NETWORK_INFO = "networkInfo"; 608 /** 609 * The lookup key for a String giving the BSSID of the access point to which 610 * we are connected. No longer used. 611 */ 612 @Deprecated 613 public static final String EXTRA_BSSID = "bssid"; 614 /** 615 * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the 616 * information about the access point to which we are connected. 617 * No longer used. 618 */ 619 @Deprecated 620 public static final String EXTRA_WIFI_INFO = "wifiInfo"; 621 /** 622 * Broadcast intent action indicating that the state of establishing a connection to 623 * an access point has changed.One extra provides the new 624 * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and 625 * is not generally the most useful thing to look at if you are just interested in 626 * the overall state of connectivity. 627 * @see #EXTRA_NEW_STATE 628 * @see #EXTRA_SUPPLICANT_ERROR 629 * @deprecated This is no longer supported. 630 */ 631 @Deprecated 632 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 633 public static final String SUPPLICANT_STATE_CHANGED_ACTION = 634 "android.net.wifi.supplicant.STATE_CHANGE"; 635 /** 636 * The lookup key for a {@link SupplicantState} describing the new state 637 * Retrieve with 638 * {@link android.content.Intent#getParcelableExtra(String)}. 639 * @deprecated This is no longer supported. 640 */ 641 @Deprecated 642 public static final String EXTRA_NEW_STATE = "newState"; 643 644 /** 645 * The lookup key for a {@link SupplicantState} describing the supplicant 646 * error code if any 647 * Retrieve with 648 * {@link android.content.Intent#getIntExtra(String, int)}. 649 * @see #ERROR_AUTHENTICATING 650 * @deprecated This is no longer supported. 651 */ 652 @Deprecated 653 public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; 654 655 /** 656 * The lookup key for a {@link SupplicantState} describing the supplicant 657 * error reason if any 658 * Retrieve with 659 * {@link android.content.Intent#getIntExtra(String, int)}. 660 * @see #ERROR_AUTH_FAILURE_#REASON_CODE 661 * @deprecated This is no longer supported. 662 * @hide 663 */ 664 @Deprecated 665 public static final String EXTRA_SUPPLICANT_ERROR_REASON = "supplicantErrorReason"; 666 667 /** 668 * Broadcast intent action indicating that the configured networks changed. 669 * This can be as a result of adding/updating/deleting a network. If 670 * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration 671 * can be retreived with the {@link #EXTRA_WIFI_CONFIGURATION} extra. If multiple 672 * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present. 673 * @hide 674 */ 675 @SystemApi 676 public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = 677 "android.net.wifi.CONFIGURED_NETWORKS_CHANGE"; 678 /** 679 * The lookup key for a (@link android.net.wifi.WifiConfiguration} object representing 680 * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION} 681 * broadcast is sent. 682 * @hide 683 */ 684 @SystemApi 685 public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; 686 /** 687 * Multiple network configurations have changed. 688 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 689 * 690 * @hide 691 */ 692 @SystemApi 693 public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges"; 694 /** 695 * The lookup key for an integer indicating the reason a Wi-Fi network configuration 696 * has changed. Only present if {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is {@code false} 697 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 698 * @hide 699 */ 700 @SystemApi 701 public static final String EXTRA_CHANGE_REASON = "changeReason"; 702 /** 703 * The configuration is new and was added. 704 * @hide 705 */ 706 @SystemApi 707 public static final int CHANGE_REASON_ADDED = 0; 708 /** 709 * The configuration was removed and is no longer present in the system's list of 710 * configured networks. 711 * @hide 712 */ 713 @SystemApi 714 public static final int CHANGE_REASON_REMOVED = 1; 715 /** 716 * The configuration has changed as a result of explicit action or because the system 717 * took an automated action such as disabling a malfunctioning configuration. 718 * @hide 719 */ 720 @SystemApi 721 public static final int CHANGE_REASON_CONFIG_CHANGE = 2; 722 /** 723 * An access point scan has completed, and results are available. 724 * Call {@link #getScanResults()} to obtain the results. 725 * The broadcast intent may contain an extra field with the key {@link #EXTRA_RESULTS_UPDATED} 726 * and a {@code boolean} value indicating if the scan was successful. 727 */ 728 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 729 public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; 730 731 /** 732 * Lookup key for a {@code boolean} extra in intent {@link #SCAN_RESULTS_AVAILABLE_ACTION} 733 * representing if the scan was successful or not. 734 * Scans may fail for multiple reasons, these may include: 735 * <ol> 736 * <li>An app requested too many scans in a certain period of time. 737 * This may lead to additional scan request rejections via "scan throttling" for both 738 * foreground and background apps. 739 * Note: Apps holding android.Manifest.permission.NETWORK_SETTINGS permission are 740 * exempted from scan throttling. 741 * </li> 742 * <li>The device is idle and scanning is disabled.</li> 743 * <li>Wifi hardware reported a scan failure.</li> 744 * </ol> 745 * @return true scan was successful, results are updated 746 * @return false scan was not successful, results haven't been updated since previous scan 747 */ 748 public static final String EXTRA_RESULTS_UPDATED = "resultsUpdated"; 749 750 /** 751 * A batch of access point scans has been completed and the results areavailable. 752 * Call {@link #getBatchedScanResults()} to obtain the results. 753 * @deprecated This API is nolonger supported. 754 * Use {@link android.net.wifi.WifiScanner} API 755 * @hide 756 */ 757 @Deprecated 758 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 759 public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION = 760 "android.net.wifi.BATCHED_RESULTS"; 761 /** 762 * The RSSI (signal strength) has changed. 763 * @see #EXTRA_NEW_RSSI 764 */ 765 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 766 public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; 767 /** 768 * The lookup key for an {@code int} giving the new RSSI in dBm. 769 */ 770 public static final String EXTRA_NEW_RSSI = "newRssi"; 771 772 /** 773 * Broadcast intent action indicating that the link configuration 774 * changed on wifi. 775 * @hide 776 */ 777 public static final String LINK_CONFIGURATION_CHANGED_ACTION = 778 "android.net.wifi.LINK_CONFIGURATION_CHANGED"; 779 780 /** 781 * The lookup key for a {@link android.net.LinkProperties} object associated with the 782 * Wi-Fi network. Retrieve with 783 * {@link android.content.Intent#getParcelableExtra(String)}. 784 * @hide 785 */ 786 public static final String EXTRA_LINK_PROPERTIES = "linkProperties"; 787 788 /** 789 * The lookup key for a {@link android.net.NetworkCapabilities} object associated with the 790 * Wi-Fi network. Retrieve with 791 * {@link android.content.Intent#getParcelableExtra(String)}. 792 * @hide 793 */ 794 public static final String EXTRA_NETWORK_CAPABILITIES = "networkCapabilities"; 795 796 /** 797 * The network IDs of the configured networks could have changed. 798 */ 799 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 800 public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; 801 802 /** 803 * Activity Action: Show a system activity that allows the user to enable 804 * scans to be available even with Wi-Fi turned off. 805 * 806 * <p>Notification of the result of this activity is posted using the 807 * {@link android.app.Activity#onActivityResult} callback. The 808 * <code>resultCode</code> 809 * will be {@link android.app.Activity#RESULT_OK} if scan always mode has 810 * been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user 811 * has rejected the request or an error has occurred. 812 */ 813 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 814 public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = 815 "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; 816 817 /** 818 * Activity Action: Pick a Wi-Fi network to connect to. 819 * <p>Input: Nothing. 820 * <p>Output: Nothing. 821 */ 822 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 823 public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; 824 825 /** 826 * Activity Action: Show UI to get user approval to enable WiFi. 827 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 828 * the name of the app requesting the action. 829 * <p>Output: Nothing. 830 * 831 * @hide 832 */ 833 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 834 public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE"; 835 836 /** 837 * Activity Action: Show UI to get user approval to disable WiFi. 838 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 839 * the name of the app requesting the action. 840 * <p>Output: Nothing. 841 * 842 * @hide 843 */ 844 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 845 public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; 846 847 /** 848 * Internally used Wi-Fi lock mode representing the case were no locks are held. 849 * @hide 850 */ 851 public static final int WIFI_MODE_NO_LOCKS_HELD = 0; 852 853 /** 854 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 855 * and will behave normally, i.e., it will attempt to automatically 856 * establish a connection to a remembered access point that is 857 * within range, and will do periodic scans if there are remembered 858 * access points but none are in range. 859 */ 860 public static final int WIFI_MODE_FULL = 1; 861 /** 862 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 863 * but the only operation that will be supported is initiation of 864 * scans, and the subsequent reporting of scan results. No attempts 865 * will be made to automatically connect to remembered access points, 866 * nor will periodic scans be automatically performed looking for 867 * remembered access points. Scans must be explicitly requested by 868 * an application in this mode. 869 */ 870 public static final int WIFI_MODE_SCAN_ONLY = 2; 871 /** 872 * In this Wi-Fi lock mode, Wi-Fi will be kept active as in mode 873 * {@link #WIFI_MODE_FULL} but it operates at high performance 874 * with minimum packet loss and low packet latency even when 875 * the device screen is off. This mode will consume more power 876 * and hence should be used only when there is a need for such 877 * an active connection. 878 * <p> 879 * An example use case is when a voice connection needs to be 880 * kept active even after the device screen goes off. Holding the 881 * regular {@link #WIFI_MODE_FULL} lock will keep the wifi 882 * connection active, but the connection can be lossy. 883 * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the 884 * duration of the voice call will improve the call quality. 885 * <p> 886 * When there is no support from the hardware, this lock mode 887 * will have the same behavior as {@link #WIFI_MODE_FULL} 888 */ 889 public static final int WIFI_MODE_FULL_HIGH_PERF = 3; 890 891 /** Anything worse than or equal to this will show 0 bars. */ 892 private static final int MIN_RSSI = -100; 893 894 /** Anything better than or equal to this will show the max bars. */ 895 private static final int MAX_RSSI = -55; 896 897 /** 898 * Number of RSSI levels used in the framework to initiate 899 * {@link #RSSI_CHANGED_ACTION} broadcast 900 * @hide 901 */ 902 public static final int RSSI_LEVELS = 5; 903 904 /** 905 * Auto settings in the driver. The driver could choose to operate on both 906 * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band. 907 * @hide 908 */ 909 public static final int WIFI_FREQUENCY_BAND_AUTO = 0; 910 911 /** 912 * Operation on 5 GHz alone 913 * @hide 914 */ 915 public static final int WIFI_FREQUENCY_BAND_5GHZ = 1; 916 917 /** 918 * Operation on 2.4 GHz alone 919 * @hide 920 */ 921 public static final int WIFI_FREQUENCY_BAND_2GHZ = 2; 922 923 /** List of asyncronous notifications 924 * @hide 925 */ 926 public static final int DATA_ACTIVITY_NOTIFICATION = 1; 927 928 //Lowest bit indicates data reception and the second lowest 929 //bit indicates data transmitted 930 /** @hide */ 931 public static final int DATA_ACTIVITY_NONE = 0x00; 932 /** @hide */ 933 public static final int DATA_ACTIVITY_IN = 0x01; 934 /** @hide */ 935 public static final int DATA_ACTIVITY_OUT = 0x02; 936 /** @hide */ 937 public static final int DATA_ACTIVITY_INOUT = 0x03; 938 939 /** @hide */ 940 public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false; 941 942 /* Maximum number of active locks we allow. 943 * This limit was added to prevent apps from creating a ridiculous number 944 * of locks and crashing the system by overflowing the global ref table. 945 */ 946 private static final int MAX_ACTIVE_LOCKS = 50; 947 948 /* Number of currently active WifiLocks and MulticastLocks */ 949 private int mActiveLockCount; 950 951 private Context mContext; 952 IWifiManager mService; 953 private final int mTargetSdkVersion; 954 955 private static final int INVALID_KEY = 0; 956 private int mListenerKey = 1; 957 private final SparseArray mListenerMap = new SparseArray(); 958 private final Object mListenerMapLock = new Object(); 959 960 private AsyncChannel mAsyncChannel; 961 private CountDownLatch mConnected; 962 private Looper mLooper; 963 964 /* LocalOnlyHotspot callback message types */ 965 /** @hide */ 966 public static final int HOTSPOT_STARTED = 0; 967 /** @hide */ 968 public static final int HOTSPOT_STOPPED = 1; 969 /** @hide */ 970 public static final int HOTSPOT_FAILED = 2; 971 /** @hide */ 972 public static final int HOTSPOT_OBSERVER_REGISTERED = 3; 973 974 private final Object mLock = new Object(); // lock guarding access to the following vars 975 @GuardedBy("mLock") 976 private LocalOnlyHotspotCallbackProxy mLOHSCallbackProxy; 977 @GuardedBy("mLock") 978 private LocalOnlyHotspotObserverProxy mLOHSObserverProxy; 979 980 /** 981 * Create a new WifiManager instance. 982 * Applications will almost always want to use 983 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve 984 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. 985 * @param context the application context 986 * @param service the Binder interface 987 * @hide - hide this because it takes in a parameter of type IWifiManager, which 988 * is a system private class. 989 */ WifiManager(Context context, IWifiManager service, Looper looper)990 public WifiManager(Context context, IWifiManager service, Looper looper) { 991 mContext = context; 992 mService = service; 993 mLooper = looper; 994 mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; 995 } 996 997 /** 998 * Return a list of all the networks configured for the current foreground 999 * user. 1000 * Not all fields of WifiConfiguration are returned. Only the following 1001 * fields are filled in: 1002 * <ul> 1003 * <li>networkId</li> 1004 * <li>SSID</li> 1005 * <li>BSSID</li> 1006 * <li>priority</li> 1007 * <li>allowedProtocols</li> 1008 * <li>allowedKeyManagement</li> 1009 * <li>allowedAuthAlgorithms</li> 1010 * <li>allowedPairwiseCiphers</li> 1011 * <li>allowedGroupCiphers</li> 1012 * </ul> 1013 * @return a list of network configurations in the form of a list 1014 * of {@link WifiConfiguration} objects. 1015 */ getConfiguredNetworks()1016 public List<WifiConfiguration> getConfiguredNetworks() { 1017 try { 1018 ParceledListSlice<WifiConfiguration> parceledList = 1019 mService.getConfiguredNetworks(); 1020 if (parceledList == null) { 1021 return Collections.emptyList(); 1022 } 1023 return parceledList.getList(); 1024 } catch (RemoteException e) { 1025 throw e.rethrowFromSystemServer(); 1026 } 1027 } 1028 1029 /** @hide */ 1030 @SystemApi 1031 @RequiresPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL) getPrivilegedConfiguredNetworks()1032 public List<WifiConfiguration> getPrivilegedConfiguredNetworks() { 1033 try { 1034 ParceledListSlice<WifiConfiguration> parceledList = 1035 mService.getPrivilegedConfiguredNetworks(); 1036 if (parceledList == null) { 1037 return Collections.emptyList(); 1038 } 1039 return parceledList.getList(); 1040 } catch (RemoteException e) { 1041 throw e.rethrowFromSystemServer(); 1042 } 1043 } 1044 1045 /** 1046 * Returns a WifiConfiguration matching this ScanResult 1047 * 1048 * @param scanResult scanResult that represents the BSSID 1049 * @return {@link WifiConfiguration} that matches this BSSID or null 1050 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 1051 * @hide 1052 */ getMatchingWifiConfig(ScanResult scanResult)1053 public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) { 1054 try { 1055 return mService.getMatchingWifiConfig(scanResult); 1056 } catch (RemoteException e) { 1057 throw e.rethrowFromSystemServer(); 1058 } 1059 } 1060 1061 /** 1062 * Return all matching WifiConfigurations for this ScanResult. 1063 * 1064 * An empty list will be returned when no configurations are installed or if no configurations 1065 * match the ScanResult. 1066 * 1067 * @param scanResult scanResult that represents the BSSID 1068 * @return A list of {@link WifiConfiguration} 1069 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 1070 * @hide 1071 */ getAllMatchingWifiConfigs(ScanResult scanResult)1072 public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) { 1073 try { 1074 return mService.getAllMatchingWifiConfigs(scanResult); 1075 } catch (RemoteException e) { 1076 throw e.rethrowFromSystemServer(); 1077 } 1078 } 1079 1080 1081 /** 1082 * Returns a list of Hotspot 2.0 OSU (Online Sign-Up) providers associated with the given AP. 1083 * 1084 * An empty list will be returned if no match is found. 1085 * 1086 * @param scanResult scanResult that represents the BSSID 1087 * @return list of {@link OsuProvider} 1088 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 1089 * @hide 1090 */ getMatchingOsuProviders(ScanResult scanResult)1091 public List<OsuProvider> getMatchingOsuProviders(ScanResult scanResult) { 1092 try { 1093 return mService.getMatchingOsuProviders(scanResult); 1094 } catch (RemoteException e) { 1095 throw e.rethrowFromSystemServer(); 1096 } 1097 } 1098 1099 /** 1100 * Add a new network description to the set of configured networks. 1101 * The {@code networkId} field of the supplied configuration object 1102 * is ignored. 1103 * <p/> 1104 * The new network will be marked DISABLED by default. To enable it, 1105 * called {@link #enableNetwork}. 1106 * 1107 * @param config the set of variables that describe the configuration, 1108 * contained in a {@link WifiConfiguration} object. 1109 * If the {@link WifiConfiguration} has an Http Proxy set 1110 * the calling app must be System, or be provisioned as the Profile or Device Owner. 1111 * @return the ID of the newly created network description. This is used in 1112 * other operations to specified the network to be acted upon. 1113 * Returns {@code -1} on failure. 1114 */ addNetwork(WifiConfiguration config)1115 public int addNetwork(WifiConfiguration config) { 1116 if (config == null) { 1117 return -1; 1118 } 1119 config.networkId = -1; 1120 return addOrUpdateNetwork(config); 1121 } 1122 1123 /** 1124 * Update the network description of an existing configured network. 1125 * 1126 * @param config the set of variables that describe the configuration, 1127 * contained in a {@link WifiConfiguration} object. It may 1128 * be sparse, so that only the items that are being changed 1129 * are non-<code>null</code>. The {@code networkId} field 1130 * must be set to the ID of the existing network being updated. 1131 * If the {@link WifiConfiguration} has an Http Proxy set 1132 * the calling app must be System, or be provisioned as the Profile or Device Owner. 1133 * @return Returns the {@code networkId} of the supplied 1134 * {@code WifiConfiguration} on success. 1135 * <br/> 1136 * Returns {@code -1} on failure, including when the {@code networkId} 1137 * field of the {@code WifiConfiguration} does not refer to an 1138 * existing network. 1139 */ updateNetwork(WifiConfiguration config)1140 public int updateNetwork(WifiConfiguration config) { 1141 if (config == null || config.networkId < 0) { 1142 return -1; 1143 } 1144 return addOrUpdateNetwork(config); 1145 } 1146 1147 /** 1148 * Internal method for doing the RPC that creates a new network description 1149 * or updates an existing one. 1150 * 1151 * @param config The possibly sparse object containing the variables that 1152 * are to set or updated in the network description. 1153 * @return the ID of the network on success, {@code -1} on failure. 1154 */ addOrUpdateNetwork(WifiConfiguration config)1155 private int addOrUpdateNetwork(WifiConfiguration config) { 1156 try { 1157 return mService.addOrUpdateNetwork(config, mContext.getOpPackageName()); 1158 } catch (RemoteException e) { 1159 throw e.rethrowFromSystemServer(); 1160 } 1161 } 1162 1163 /** 1164 * Add or update a Passpoint configuration. The configuration provides a credential 1165 * for connecting to Passpoint networks that are operated by the Passpoint 1166 * service provider specified in the configuration. 1167 * 1168 * Each configuration is uniquely identified by its FQDN (Fully Qualified Domain 1169 * Name). In the case when there is an existing configuration with the same 1170 * FQDN, the new configuration will replace the existing configuration. 1171 * 1172 * @param config The Passpoint configuration to be added 1173 * @throws IllegalArgumentException if configuration is invalid 1174 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 1175 */ addOrUpdatePasspointConfiguration(PasspointConfiguration config)1176 public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) { 1177 try { 1178 if (!mService.addOrUpdatePasspointConfiguration(config, mContext.getOpPackageName())) { 1179 throw new IllegalArgumentException(); 1180 } 1181 } catch (RemoteException e) { 1182 throw e.rethrowFromSystemServer(); 1183 } 1184 } 1185 1186 /** 1187 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name). 1188 * 1189 * @param fqdn The FQDN of the Passpoint configuration to be removed 1190 * @throws IllegalArgumentException if no configuration is associated with the given FQDN. 1191 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 1192 */ removePasspointConfiguration(String fqdn)1193 public void removePasspointConfiguration(String fqdn) { 1194 try { 1195 if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) { 1196 throw new IllegalArgumentException(); 1197 } 1198 } catch (RemoteException e) { 1199 throw e.rethrowFromSystemServer(); 1200 } 1201 } 1202 1203 /** 1204 * Return the list of installed Passpoint configurations. 1205 * 1206 * An empty list will be returned when no configurations are installed. 1207 * 1208 * @return A list of {@link PasspointConfiguration} 1209 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 1210 */ getPasspointConfigurations()1211 public List<PasspointConfiguration> getPasspointConfigurations() { 1212 try { 1213 return mService.getPasspointConfigurations(); 1214 } catch (RemoteException e) { 1215 throw e.rethrowFromSystemServer(); 1216 } 1217 } 1218 1219 /** 1220 * Query for a Hotspot 2.0 release 2 OSU icon file. An {@link #ACTION_PASSPOINT_ICON} intent 1221 * will be broadcasted once the request is completed. The presence of the intent extra 1222 * {@link #EXTRA_ICON} will indicate the result of the request. 1223 * A missing intent extra {@link #EXTRA_ICON} will indicate a failure. 1224 * 1225 * @param bssid The BSSID of the AP 1226 * @param fileName Name of the icon file (remote file) to query from the AP 1227 * 1228 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 1229 * @hide 1230 */ queryPasspointIcon(long bssid, String fileName)1231 public void queryPasspointIcon(long bssid, String fileName) { 1232 try { 1233 mService.queryPasspointIcon(bssid, fileName); 1234 } catch (RemoteException e) { 1235 throw e.rethrowFromSystemServer(); 1236 } 1237 } 1238 1239 /** 1240 * Match the currently associated network against the SP matching the given FQDN 1241 * @param fqdn FQDN of the SP 1242 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 1243 * @hide 1244 */ matchProviderWithCurrentNetwork(String fqdn)1245 public int matchProviderWithCurrentNetwork(String fqdn) { 1246 try { 1247 return mService.matchProviderWithCurrentNetwork(fqdn); 1248 } catch (RemoteException e) { 1249 throw e.rethrowFromSystemServer(); 1250 } 1251 } 1252 1253 /** 1254 * Deauthenticate and set the re-authentication hold off time for the current network 1255 * @param holdoff hold off time in milliseconds 1256 * @param ess set if the hold off pertains to an ESS rather than a BSS 1257 * @hide 1258 */ deauthenticateNetwork(long holdoff, boolean ess)1259 public void deauthenticateNetwork(long holdoff, boolean ess) { 1260 try { 1261 mService.deauthenticateNetwork(holdoff, ess); 1262 } catch (RemoteException e) { 1263 throw e.rethrowFromSystemServer(); 1264 } 1265 } 1266 1267 /** 1268 * Remove the specified network from the list of configured networks. 1269 * This may result in the asynchronous delivery of state change 1270 * events. 1271 * 1272 * Applications are not allowed to remove networks created by other 1273 * applications. 1274 * 1275 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 1276 * #getConfiguredNetworks}. 1277 * @return {@code true} if the operation succeeded 1278 */ removeNetwork(int netId)1279 public boolean removeNetwork(int netId) { 1280 try { 1281 return mService.removeNetwork(netId, mContext.getOpPackageName()); 1282 } catch (RemoteException e) { 1283 throw e.rethrowFromSystemServer(); 1284 } 1285 } 1286 1287 /** 1288 * Allow a previously configured network to be associated with. If 1289 * <code>attemptConnect</code> is true, an attempt to connect to the selected 1290 * network is initiated. This may result in the asynchronous delivery 1291 * of state change events. 1292 * <p> 1293 * <b>Note:</b> If an application's target SDK version is 1294 * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or newer, network 1295 * communication may not use Wi-Fi even if Wi-Fi is connected; traffic may 1296 * instead be sent through another network, such as cellular data, 1297 * Bluetooth tethering, or Ethernet. For example, traffic will never use a 1298 * Wi-Fi network that does not provide Internet access (e.g. a wireless 1299 * printer), if another network that does offer Internet access (e.g. 1300 * cellular data) is available. Applications that need to ensure that their 1301 * network traffic uses Wi-Fi should use APIs such as 1302 * {@link Network#bindSocket(java.net.Socket)}, 1303 * {@link Network#openConnection(java.net.URL)}, or 1304 * {@link ConnectivityManager#bindProcessToNetwork} to do so. 1305 * 1306 * Applications are not allowed to enable networks created by other 1307 * applications. 1308 * 1309 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 1310 * #getConfiguredNetworks}. 1311 * @param attemptConnect The way to select a particular network to connect to is specify 1312 * {@code true} for this parameter. 1313 * @return {@code true} if the operation succeeded 1314 */ enableNetwork(int netId, boolean attemptConnect)1315 public boolean enableNetwork(int netId, boolean attemptConnect) { 1316 final boolean pin = attemptConnect && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP; 1317 if (pin) { 1318 NetworkRequest request = new NetworkRequest.Builder() 1319 .clearCapabilities() 1320 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 1321 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 1322 .build(); 1323 NetworkPinner.pin(mContext, request); 1324 } 1325 1326 boolean success; 1327 try { 1328 success = mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName()); 1329 } catch (RemoteException e) { 1330 throw e.rethrowFromSystemServer(); 1331 } 1332 1333 if (pin && !success) { 1334 NetworkPinner.unpin(); 1335 } 1336 1337 return success; 1338 } 1339 1340 /** 1341 * Disable a configured network. The specified network will not be 1342 * a candidate for associating. This may result in the asynchronous 1343 * delivery of state change events. 1344 * 1345 * Applications are not allowed to disable networks created by other 1346 * applications. 1347 * 1348 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 1349 * #getConfiguredNetworks}. 1350 * @return {@code true} if the operation succeeded 1351 */ 1352 public boolean disableNetwork(int netId) { 1353 try { 1354 return mService.disableNetwork(netId, mContext.getOpPackageName()); 1355 } catch (RemoteException e) { 1356 throw e.rethrowFromSystemServer(); 1357 } 1358 } 1359 1360 /** 1361 * Disassociate from the currently active access point. This may result 1362 * in the asynchronous delivery of state change events. 1363 * @return {@code true} if the operation succeeded 1364 */ 1365 public boolean disconnect() { 1366 try { 1367 mService.disconnect(mContext.getOpPackageName()); 1368 return true; 1369 } catch (RemoteException e) { 1370 throw e.rethrowFromSystemServer(); 1371 } 1372 } 1373 1374 /** 1375 * Reconnect to the currently active access point, if we are currently 1376 * disconnected. This may result in the asynchronous delivery of state 1377 * change events. 1378 * @return {@code true} if the operation succeeded 1379 */ 1380 public boolean reconnect() { 1381 try { 1382 mService.reconnect(mContext.getOpPackageName()); 1383 return true; 1384 } catch (RemoteException e) { 1385 throw e.rethrowFromSystemServer(); 1386 } 1387 } 1388 1389 /** 1390 * Reconnect to the currently active access point, even if we are already 1391 * connected. This may result in the asynchronous delivery of state 1392 * change events. 1393 * @return {@code true} if the operation succeeded 1394 */ 1395 public boolean reassociate() { 1396 try { 1397 mService.reassociate(mContext.getOpPackageName()); 1398 return true; 1399 } catch (RemoteException e) { 1400 throw e.rethrowFromSystemServer(); 1401 } 1402 } 1403 1404 /** 1405 * Check that the supplicant daemon is responding to requests. 1406 * @return {@code true} if we were able to communicate with the supplicant and 1407 * it returned the expected response to the PING message. 1408 * @deprecated Will return the output of {@link #isWifiEnabled()} instead. 1409 */ 1410 @Deprecated 1411 public boolean pingSupplicant() { 1412 return isWifiEnabled(); 1413 } 1414 1415 /** @hide */ 1416 public static final int WIFI_FEATURE_INFRA = 0x0001; // Basic infrastructure mode 1417 /** @hide */ 1418 public static final int WIFI_FEATURE_INFRA_5G = 0x0002; // Support for 5 GHz Band 1419 /** @hide */ 1420 public static final int WIFI_FEATURE_PASSPOINT = 0x0004; // Support for GAS/ANQP 1421 /** @hide */ 1422 public static final int WIFI_FEATURE_P2P = 0x0008; // Wifi-Direct 1423 /** @hide */ 1424 public static final int WIFI_FEATURE_MOBILE_HOTSPOT = 0x0010; // Soft AP 1425 /** @hide */ 1426 public static final int WIFI_FEATURE_SCANNER = 0x0020; // WifiScanner APIs 1427 /** @hide */ 1428 public static final int WIFI_FEATURE_AWARE = 0x0040; // Wi-Fi AWare networking 1429 /** @hide */ 1430 public static final int WIFI_FEATURE_D2D_RTT = 0x0080; // Device-to-device RTT 1431 /** @hide */ 1432 public static final int WIFI_FEATURE_D2AP_RTT = 0x0100; // Device-to-AP RTT 1433 /** @hide */ 1434 public static final int WIFI_FEATURE_BATCH_SCAN = 0x0200; // Batched Scan (deprecated) 1435 /** @hide */ 1436 public static final int WIFI_FEATURE_PNO = 0x0400; // Preferred network offload 1437 /** @hide */ 1438 public static final int WIFI_FEATURE_ADDITIONAL_STA = 0x0800; // Support for two STAs 1439 /** @hide */ 1440 public static final int WIFI_FEATURE_TDLS = 0x1000; // Tunnel directed link setup 1441 /** @hide */ 1442 public static final int WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000; // Support for TDLS off channel 1443 /** @hide */ 1444 public static final int WIFI_FEATURE_EPR = 0x4000; // Enhanced power reporting 1445 /** @hide */ 1446 public static final int WIFI_FEATURE_AP_STA = 0x8000; // AP STA Concurrency 1447 /** @hide */ 1448 public static final int WIFI_FEATURE_LINK_LAYER_STATS = 0x10000; // Link layer stats collection 1449 /** @hide */ 1450 public static final int WIFI_FEATURE_LOGGER = 0x20000; // WiFi Logger 1451 /** @hide */ 1452 public static final int WIFI_FEATURE_HAL_EPNO = 0x40000; // Enhanced PNO 1453 /** @hide */ 1454 public static final int WIFI_FEATURE_RSSI_MONITOR = 0x80000; // RSSI Monitor 1455 /** @hide */ 1456 public static final int WIFI_FEATURE_MKEEP_ALIVE = 0x100000; // mkeep_alive 1457 /** @hide */ 1458 public static final int WIFI_FEATURE_CONFIG_NDO = 0x200000; // ND offload 1459 /** @hide */ 1460 public static final int WIFI_FEATURE_TRANSMIT_POWER = 0x400000; // Capture transmit power 1461 /** @hide */ 1462 public static final int WIFI_FEATURE_CONTROL_ROAMING = 0x800000; // Control firmware roaming 1463 /** @hide */ 1464 public static final int WIFI_FEATURE_IE_WHITELIST = 0x1000000; // Probe IE white listing 1465 /** @hide */ 1466 public static final int WIFI_FEATURE_SCAN_RAND = 0x2000000; // Random MAC & Probe seq 1467 /** @hide */ 1468 public static final int WIFI_FEATURE_TX_POWER_LIMIT = 0x4000000; // Set Tx power limit 1469 1470 1471 private int getSupportedFeatures() { 1472 try { 1473 return mService.getSupportedFeatures(); 1474 } catch (RemoteException e) { 1475 throw e.rethrowFromSystemServer(); 1476 } 1477 } 1478 1479 private boolean isFeatureSupported(int feature) { 1480 return (getSupportedFeatures() & feature) == feature; 1481 } 1482 /** 1483 * @return true if this adapter supports 5 GHz band 1484 */ 1485 public boolean is5GHzBandSupported() { 1486 return isFeatureSupported(WIFI_FEATURE_INFRA_5G); 1487 } 1488 1489 /** 1490 * @return true if this adapter supports Passpoint 1491 * @hide 1492 */ 1493 public boolean isPasspointSupported() { 1494 return isFeatureSupported(WIFI_FEATURE_PASSPOINT); 1495 } 1496 1497 /** 1498 * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct) 1499 */ 1500 public boolean isP2pSupported() { 1501 return isFeatureSupported(WIFI_FEATURE_P2P); 1502 } 1503 1504 /** 1505 * @return true if this adapter supports portable Wi-Fi hotspot 1506 * @hide 1507 */ 1508 @SystemApi 1509 public boolean isPortableHotspotSupported() { 1510 return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT); 1511 } 1512 1513 /** 1514 * @return true if this adapter supports WifiScanner APIs 1515 * @hide 1516 */ 1517 @SystemApi 1518 public boolean isWifiScannerSupported() { 1519 return isFeatureSupported(WIFI_FEATURE_SCANNER); 1520 } 1521 1522 /** 1523 * @return true if this adapter supports Neighbour Awareness Network APIs 1524 * @hide 1525 */ 1526 public boolean isWifiAwareSupported() { 1527 return isFeatureSupported(WIFI_FEATURE_AWARE); 1528 } 1529 1530 /** 1531 * @return true if this adapter supports Device-to-device RTT 1532 * @hide 1533 */ 1534 @SystemApi 1535 public boolean isDeviceToDeviceRttSupported() { 1536 return isFeatureSupported(WIFI_FEATURE_D2D_RTT); 1537 } 1538 1539 /** 1540 * @return true if this adapter supports Device-to-AP RTT 1541 */ 1542 @SystemApi 1543 public boolean isDeviceToApRttSupported() { 1544 return isFeatureSupported(WIFI_FEATURE_D2AP_RTT); 1545 } 1546 1547 /** 1548 * @return true if this adapter supports offloaded connectivity scan 1549 */ 1550 public boolean isPreferredNetworkOffloadSupported() { 1551 return isFeatureSupported(WIFI_FEATURE_PNO); 1552 } 1553 1554 /** 1555 * @return true if this adapter supports multiple simultaneous connections 1556 * @hide 1557 */ 1558 public boolean isAdditionalStaSupported() { 1559 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA); 1560 } 1561 1562 /** 1563 * @return true if this adapter supports Tunnel Directed Link Setup 1564 */ 1565 public boolean isTdlsSupported() { 1566 return isFeatureSupported(WIFI_FEATURE_TDLS); 1567 } 1568 1569 /** 1570 * @return true if this adapter supports Off Channel Tunnel Directed Link Setup 1571 * @hide 1572 */ 1573 public boolean isOffChannelTdlsSupported() { 1574 return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL); 1575 } 1576 1577 /** 1578 * @return true if this adapter supports advanced power/performance counters 1579 */ 1580 public boolean isEnhancedPowerReportingSupported() { 1581 return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS); 1582 } 1583 1584 /** 1585 * Return the record of {@link WifiActivityEnergyInfo} object that 1586 * has the activity and energy info. This can be used to ascertain what 1587 * the controller has been up to, since the last sample. 1588 * @param updateType Type of info, cached vs refreshed. 1589 * 1590 * @return a record with {@link WifiActivityEnergyInfo} or null if 1591 * report is unavailable or unsupported 1592 * @hide 1593 */ 1594 public WifiActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { 1595 if (mService == null) return null; 1596 try { 1597 synchronized(this) { 1598 return mService.reportActivityInfo(); 1599 } 1600 } catch (RemoteException e) { 1601 throw e.rethrowFromSystemServer(); 1602 } 1603 } 1604 1605 /** 1606 * Request a scan for access points. Returns immediately. The availability 1607 * of the results is made known later by means of an asynchronous event sent 1608 * on completion of the scan. 1609 * <p> 1610 * To initiate a Wi-Fi scan, declare the 1611 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} 1612 * permission in the manifest, and perform these steps: 1613 * </p> 1614 * <ol style="1"> 1615 * <li>Invoke the following method: 1616 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).startScan()}</li> 1617 * <li> 1618 * Register a BroadcastReceiver to listen to 1619 * {@code SCAN_RESULTS_AVAILABLE_ACTION}.</li> 1620 * <li>When a broadcast is received, call: 1621 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).getScanResults()}</li> 1622 * </ol> 1623 * @return {@code true} if the operation succeeded, i.e., the scan was initiated. 1624 * @deprecated The ability for apps to trigger scan requests will be removed in a future 1625 * release. 1626 */ 1627 @Deprecated 1628 public boolean startScan() { 1629 return startScan(null); 1630 } 1631 1632 /** @hide */ 1633 @SystemApi 1634 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) 1635 public boolean startScan(WorkSource workSource) { 1636 try { 1637 String packageName = mContext.getOpPackageName(); 1638 return mService.startScan(packageName); 1639 } catch (RemoteException e) { 1640 throw e.rethrowFromSystemServer(); 1641 } 1642 } 1643 1644 /** 1645 * WPS has been deprecated from Client mode operation. 1646 * 1647 * @return null 1648 * @hide 1649 * @deprecated This API is deprecated 1650 */ 1651 public String getCurrentNetworkWpsNfcConfigurationToken() { 1652 return null; 1653 } 1654 1655 /** 1656 * Return dynamic information about the current Wi-Fi connection, if any is active. 1657 * <p> 1658 * In the connected state, access to the SSID and BSSID requires 1659 * the same permissions as {@link #getScanResults}. If such access is not allowed, 1660 * {@link WifiInfo#getSSID} will return {@code "<unknown ssid>"} and 1661 * {@link WifiInfo#getBSSID} will return {@code "02:00:00:00:00:00"}. 1662 * 1663 * @return the Wi-Fi information, contained in {@link WifiInfo}. 1664 */ 1665 public WifiInfo getConnectionInfo() { 1666 try { 1667 return mService.getConnectionInfo(mContext.getOpPackageName()); 1668 } catch (RemoteException e) { 1669 throw e.rethrowFromSystemServer(); 1670 } 1671 } 1672 1673 /** 1674 * Return the results of the latest access point scan. 1675 * @return the list of access points found in the most recent scan. An app must hold 1676 * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or 1677 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission 1678 * in order to get valid results. If there is a remote exception (e.g., either a communication 1679 * problem with the system service or an exception within the framework) an empty list will be 1680 * returned. 1681 */ 1682 public List<ScanResult> getScanResults() { 1683 try { 1684 return mService.getScanResults(mContext.getOpPackageName()); 1685 } catch (RemoteException e) { 1686 throw e.rethrowFromSystemServer(); 1687 } 1688 } 1689 1690 /** 1691 * Check if scanning is always available. 1692 * 1693 * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results 1694 * even when Wi-Fi is turned off. 1695 * 1696 * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}. 1697 */ 1698 public boolean isScanAlwaysAvailable() { 1699 try { 1700 return mService.isScanAlwaysAvailable(); 1701 } catch (RemoteException e) { 1702 throw e.rethrowFromSystemServer(); 1703 } 1704 } 1705 1706 /** 1707 * Tell the device to persist the current list of configured networks. 1708 * <p> 1709 * Note: It is possible for this method to change the network IDs of 1710 * existing networks. You should assume the network IDs can be different 1711 * after calling this method. 1712 * 1713 * @return {@code false} Will always return true. 1714 * @deprecated There is no need to call this method - 1715 * {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)} 1716 * and {@link #removeNetwork(int)} already persist the configurations automatically. 1717 */ 1718 @Deprecated 1719 public boolean saveConfiguration() { 1720 return true; 1721 } 1722 1723 /** 1724 * Set the country code. 1725 * @param countryCode country code in ISO 3166 format. 1726 * 1727 * @hide 1728 */ 1729 public void setCountryCode(@NonNull String country) { 1730 try { 1731 mService.setCountryCode(country); 1732 } catch (RemoteException e) { 1733 throw e.rethrowFromSystemServer(); 1734 } 1735 } 1736 1737 /** 1738 * get the country code. 1739 * @return the country code in ISO 3166 format. 1740 * 1741 * @hide 1742 */ 1743 public String getCountryCode() { 1744 try { 1745 String country = mService.getCountryCode(); 1746 return country; 1747 } catch (RemoteException e) { 1748 throw e.rethrowFromSystemServer(); 1749 } 1750 } 1751 1752 /** 1753 * Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz) 1754 * @return {@code true} if supported, {@code false} otherwise. 1755 * @hide 1756 */ 1757 public boolean isDualBandSupported() { 1758 try { 1759 return mService.isDualBandSupported(); 1760 } catch (RemoteException e) { 1761 throw e.rethrowFromSystemServer(); 1762 } 1763 } 1764 1765 /** 1766 * Check if the chipset requires conversion of 5GHz Only apBand to ANY. 1767 * @return {@code true} if required, {@code false} otherwise. 1768 * @hide 1769 */ 1770 public boolean isDualModeSupported() { 1771 try { 1772 return mService.needs5GHzToAnyApBandConversion(); 1773 } catch (RemoteException e) { 1774 throw e.rethrowFromSystemServer(); 1775 } 1776 } 1777 1778 /** 1779 * Return the DHCP-assigned addresses from the last successful DHCP request, 1780 * if any. 1781 * @return the DHCP information 1782 */ 1783 public DhcpInfo getDhcpInfo() { 1784 try { 1785 return mService.getDhcpInfo(); 1786 } catch (RemoteException e) { 1787 throw e.rethrowFromSystemServer(); 1788 } 1789 } 1790 1791 /** 1792 * Enable or disable Wi-Fi. 1793 * <p> 1794 * Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE} 1795 * permission to toggle wifi. 1796 * 1797 * @param enabled {@code true} to enable, {@code false} to disable. 1798 * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is 1799 * either already in the requested state, or in progress toward the requested state. 1800 * @throws {@link java.lang.SecurityException} if the caller is missing required permissions. 1801 */ 1802 public boolean setWifiEnabled(boolean enabled) { 1803 try { 1804 return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); 1805 } catch (RemoteException e) { 1806 throw e.rethrowFromSystemServer(); 1807 } 1808 } 1809 1810 /** 1811 * Gets the Wi-Fi enabled state. 1812 * @return One of {@link #WIFI_STATE_DISABLED}, 1813 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 1814 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 1815 * @see #isWifiEnabled() 1816 */ 1817 public int getWifiState() { 1818 try { 1819 return mService.getWifiEnabledState(); 1820 } catch (RemoteException e) { 1821 throw e.rethrowFromSystemServer(); 1822 } 1823 } 1824 1825 /** 1826 * Return whether Wi-Fi is enabled or disabled. 1827 * @return {@code true} if Wi-Fi is enabled 1828 * @see #getWifiState() 1829 */ 1830 public boolean isWifiEnabled() { 1831 return getWifiState() == WIFI_STATE_ENABLED; 1832 } 1833 1834 /** 1835 * Return TX packet counter, for CTS test of WiFi watchdog. 1836 * @param listener is the interface to receive result 1837 * 1838 * @hide for CTS test only 1839 */ 1840 public void getTxPacketCount(TxPacketCountListener listener) { 1841 getChannel().sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener)); 1842 } 1843 1844 /** 1845 * Calculates the level of the signal. This should be used any time a signal 1846 * is being shown. 1847 * 1848 * @param rssi The power of the signal measured in RSSI. 1849 * @param numLevels The number of levels to consider in the calculated 1850 * level. 1851 * @return A level of the signal, given in the range of 0 to numLevels-1 1852 * (both inclusive). 1853 */ 1854 public static int calculateSignalLevel(int rssi, int numLevels) { 1855 if (rssi <= MIN_RSSI) { 1856 return 0; 1857 } else if (rssi >= MAX_RSSI) { 1858 return numLevels - 1; 1859 } else { 1860 float inputRange = (MAX_RSSI - MIN_RSSI); 1861 float outputRange = (numLevels - 1); 1862 return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange); 1863 } 1864 } 1865 1866 /** 1867 * Compares two signal strengths. 1868 * 1869 * @param rssiA The power of the first signal measured in RSSI. 1870 * @param rssiB The power of the second signal measured in RSSI. 1871 * @return Returns <0 if the first signal is weaker than the second signal, 1872 * 0 if the two signals have the same strength, and >0 if the first 1873 * signal is stronger than the second signal. 1874 */ 1875 public static int compareSignalLevel(int rssiA, int rssiB) { 1876 return rssiA - rssiB; 1877 } 1878 1879 /** 1880 * Call allowing ConnectivityService to update WifiService with interface mode changes. 1881 * 1882 * The possible modes include: {@link IFACE_IP_MODE_TETHERED}, 1883 * {@link IFACE_IP_MODE_LOCAL_ONLY}, 1884 * {@link IFACE_IP_MODE_CONFIGURATION_ERROR} 1885 * 1886 * @param ifaceName String name of the updated interface 1887 * @param mode int representing the new mode 1888 * 1889 * @hide 1890 */ 1891 public void updateInterfaceIpState(String ifaceName, int mode) { 1892 try { 1893 mService.updateInterfaceIpState(ifaceName, mode); 1894 } catch (RemoteException e) { 1895 throw e.rethrowFromSystemServer(); 1896 } 1897 } 1898 1899 /** 1900 * Start SoftAp mode with the specified configuration. 1901 * Note that starting in access point mode disables station 1902 * mode operation 1903 * @param wifiConfig SSID, security and channel details as 1904 * part of WifiConfiguration 1905 * @return {@code true} if the operation succeeds, {@code false} otherwise 1906 * 1907 * @hide 1908 */ 1909 public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) { 1910 try { 1911 return mService.startSoftAp(wifiConfig); 1912 } catch (RemoteException e) { 1913 throw e.rethrowFromSystemServer(); 1914 } 1915 } 1916 1917 /** 1918 * Stop SoftAp mode. 1919 * Note that stopping softap mode will restore the previous wifi mode. 1920 * @return {@code true} if the operation succeeds, {@code false} otherwise 1921 * 1922 * @hide 1923 */ 1924 public boolean stopSoftAp() { 1925 try { 1926 return mService.stopSoftAp(); 1927 } catch (RemoteException e) { 1928 throw e.rethrowFromSystemServer(); 1929 } 1930 } 1931 1932 /** 1933 * Request a local only hotspot that an application can use to communicate between co-located 1934 * devices connected to the created WiFi hotspot. The network created by this method will not 1935 * have Internet access. Each application can make a single request for the hotspot, but 1936 * multiple applications could be requesting the hotspot at the same time. When multiple 1937 * applications have successfully registered concurrently, they will be sharing the underlying 1938 * hotspot. {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} is called 1939 * when the hotspot is ready for use by the application. 1940 * <p> 1941 * Each application can make a single active call to this method. The {@link 1942 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} callback supplies the 1943 * requestor with a {@link LocalOnlyHotspotReservation} that contains a 1944 * {@link WifiConfiguration} with the SSID, security type and credentials needed to connect 1945 * to the hotspot. Communicating this information is up to the application. 1946 * <p> 1947 * If the LocalOnlyHotspot cannot be created, the {@link LocalOnlyHotspotCallback#onFailed(int)} 1948 * method will be called. Example failures include errors bringing up the network or if 1949 * there is an incompatible operating mode. For example, if the user is currently using Wifi 1950 * Tethering to provide an upstream to another device, LocalOnlyHotspot will not start due to 1951 * an incompatible mode. The possible error codes include: 1952 * {@link LocalOnlyHotspotCallback#ERROR_NO_CHANNEL}, 1953 * {@link LocalOnlyHotspotCallback#ERROR_GENERIC}, 1954 * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE} and 1955 * {@link LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED}. 1956 * <p> 1957 * Internally, requests will be tracked to prevent the hotspot from being torn down while apps 1958 * are still using it. The {@link LocalOnlyHotspotReservation} object passed in the {@link 1959 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call should be closed when 1960 * the LocalOnlyHotspot is no longer needed using {@link LocalOnlyHotspotReservation#close()}. 1961 * Since the hotspot may be shared among multiple applications, removing the final registered 1962 * application request will trigger the hotspot teardown. This means that applications should 1963 * not listen to broadcasts containing wifi state to determine if the hotspot was stopped after 1964 * they are done using it. Additionally, once {@link LocalOnlyHotspotReservation#close()} is 1965 * called, applications will not receive callbacks of any kind. 1966 * <p> 1967 * Applications should be aware that the user may also stop the LocalOnlyHotspot through the 1968 * Settings UI; it is not guaranteed to stay up as long as there is a requesting application. 1969 * The requestors will be notified of this case via 1970 * {@link LocalOnlyHotspotCallback#onStopped()}. Other cases may arise where the hotspot is 1971 * torn down (Emergency mode, etc). Application developers should be aware that it can stop 1972 * unexpectedly, but they will receive a notification if they have properly registered. 1973 * <p> 1974 * Applications should also be aware that this network will be shared with other applications. 1975 * Applications are responsible for protecting their data on this network (e.g., TLS). 1976 * <p> 1977 * Applications need to have the following permissions to start LocalOnlyHotspot: {@link 1978 * android.Manifest.permission#CHANGE_WIFI_STATE} and {@link 1979 * android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION}. Callers without 1980 * the permissions will trigger a {@link java.lang.SecurityException}. 1981 * <p> 1982 * @param callback LocalOnlyHotspotCallback for the application to receive updates about 1983 * operating status. 1984 * @param handler Handler to be used for callbacks. If the caller passes a null Handler, the 1985 * main thread will be used. 1986 */ 1987 public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback, 1988 @Nullable Handler handler) { 1989 synchronized (mLock) { 1990 Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); 1991 LocalOnlyHotspotCallbackProxy proxy = 1992 new LocalOnlyHotspotCallbackProxy(this, looper, callback); 1993 try { 1994 String packageName = mContext.getOpPackageName(); 1995 int returnCode = mService.startLocalOnlyHotspot( 1996 proxy.getMessenger(), new Binder(), packageName); 1997 if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) { 1998 // Send message to the proxy to make sure we call back on the correct thread 1999 proxy.notifyFailed(returnCode); 2000 return; 2001 } 2002 mLOHSCallbackProxy = proxy; 2003 } catch (RemoteException e) { 2004 throw e.rethrowFromSystemServer(); 2005 } 2006 } 2007 } 2008 2009 /** 2010 * Cancels a pending local only hotspot request. This can be used by the calling application to 2011 * cancel the existing request if the provided callback has not been triggered. Calling this 2012 * method will be equivalent to closing the returned LocalOnlyHotspotReservation, but it is not 2013 * explicitly required. 2014 * <p> 2015 * When cancelling this request, application developers should be aware that there may still be 2016 * outstanding local only hotspot requests and the hotspot may still start, or continue running. 2017 * Additionally, if a callback was registered, it will no longer be triggered after calling 2018 * cancel. 2019 * 2020 * @hide 2021 */ 2022 public void cancelLocalOnlyHotspotRequest() { 2023 synchronized (mLock) { 2024 stopLocalOnlyHotspot(); 2025 } 2026 } 2027 2028 /** 2029 * Method used to inform WifiService that the LocalOnlyHotspot is no longer needed. This 2030 * method is used by WifiManager to release LocalOnlyHotspotReservations held by calling 2031 * applications and removes the internal tracking for the hotspot request. When all requesting 2032 * applications are finished using the hotspot, it will be stopped and WiFi will return to the 2033 * previous operational mode. 2034 * 2035 * This method should not be called by applications. Instead, they should call the close() 2036 * method on their LocalOnlyHotspotReservation. 2037 */ 2038 private void stopLocalOnlyHotspot() { 2039 synchronized (mLock) { 2040 if (mLOHSCallbackProxy == null) { 2041 // nothing to do, the callback was already cleaned up. 2042 return; 2043 } 2044 mLOHSCallbackProxy = null; 2045 try { 2046 mService.stopLocalOnlyHotspot(); 2047 } catch (RemoteException e) { 2048 throw e.rethrowFromSystemServer(); 2049 } 2050 } 2051 } 2052 2053 /** 2054 * Allow callers (Settings UI) to watch LocalOnlyHotspot state changes. Callers will 2055 * receive a {@link LocalOnlyHotspotSubscription} object as a parameter of the 2056 * {@link LocalOnlyHotspotObserver#onRegistered(LocalOnlyHotspotSubscription)}. The registered 2057 * callers will receive the {@link LocalOnlyHotspotObserver#onStarted(WifiConfiguration)} and 2058 * {@link LocalOnlyHotspotObserver#onStopped()} callbacks. 2059 * <p> 2060 * Applications should have the 2061 * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} 2062 * permission. Callers without the permission will trigger a 2063 * {@link java.lang.SecurityException}. 2064 * <p> 2065 * @param observer LocalOnlyHotspotObserver callback. 2066 * @param handler Handler to use for callbacks 2067 * 2068 * @hide 2069 */ 2070 public void watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer, 2071 @Nullable Handler handler) { 2072 synchronized (mLock) { 2073 Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); 2074 mLOHSObserverProxy = new LocalOnlyHotspotObserverProxy(this, looper, observer); 2075 try { 2076 mService.startWatchLocalOnlyHotspot( 2077 mLOHSObserverProxy.getMessenger(), new Binder()); 2078 mLOHSObserverProxy.registered(); 2079 } catch (RemoteException e) { 2080 mLOHSObserverProxy = null; 2081 throw e.rethrowFromSystemServer(); 2082 } 2083 } 2084 } 2085 2086 /** 2087 * Allow callers to stop watching LocalOnlyHotspot state changes. After calling this method, 2088 * applications will no longer receive callbacks. 2089 * 2090 * @hide 2091 */ 2092 public void unregisterLocalOnlyHotspotObserver() { 2093 synchronized (mLock) { 2094 if (mLOHSObserverProxy == null) { 2095 // nothing to do, the callback was already cleaned up 2096 return; 2097 } 2098 mLOHSObserverProxy = null; 2099 try { 2100 mService.stopWatchLocalOnlyHotspot(); 2101 } catch (RemoteException e) { 2102 throw e.rethrowFromSystemServer(); 2103 } 2104 } 2105 } 2106 2107 /** 2108 * Gets the Wi-Fi enabled state. 2109 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 2110 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 2111 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 2112 * @see #isWifiApEnabled() 2113 * 2114 * @hide 2115 */ 2116 @SystemApi 2117 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 2118 public int getWifiApState() { 2119 try { 2120 return mService.getWifiApEnabledState(); 2121 } catch (RemoteException e) { 2122 throw e.rethrowFromSystemServer(); 2123 } 2124 } 2125 2126 /** 2127 * Return whether Wi-Fi AP is enabled or disabled. 2128 * @return {@code true} if Wi-Fi AP is enabled 2129 * @see #getWifiApState() 2130 * 2131 * @hide 2132 */ 2133 @SystemApi 2134 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 2135 public boolean isWifiApEnabled() { 2136 return getWifiApState() == WIFI_AP_STATE_ENABLED; 2137 } 2138 2139 /** 2140 * Gets the Wi-Fi AP Configuration. 2141 * @return AP details in WifiConfiguration 2142 * 2143 * @hide 2144 */ 2145 @SystemApi 2146 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 2147 public WifiConfiguration getWifiApConfiguration() { 2148 try { 2149 return mService.getWifiApConfiguration(); 2150 } catch (RemoteException e) { 2151 throw e.rethrowFromSystemServer(); 2152 } 2153 } 2154 2155 /** 2156 * Sets the Wi-Fi AP Configuration. The AP configuration must either be open or 2157 * WPA2 PSK networks. 2158 * @return {@code true} if the operation succeeded, {@code false} otherwise 2159 * 2160 * @hide 2161 */ 2162 @SystemApi 2163 @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) 2164 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { 2165 try { 2166 return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName()); 2167 } catch (RemoteException e) { 2168 throw e.rethrowFromSystemServer(); 2169 } 2170 } 2171 2172 /** 2173 * Enable/Disable TDLS on a specific local route. 2174 * 2175 * <p> 2176 * TDLS enables two wireless endpoints to talk to each other directly 2177 * without going through the access point that is managing the local 2178 * network. It saves bandwidth and improves quality of the link. 2179 * </p> 2180 * <p> 2181 * This API enables/disables the option of using TDLS. If enabled, the 2182 * underlying hardware is free to use TDLS or a hop through the access 2183 * point. If disabled, existing TDLS session is torn down and 2184 * hardware is restricted to use access point for transferring wireless 2185 * packets. Default value for all routes is 'disabled', meaning restricted 2186 * to use access point for transferring packets. 2187 * </p> 2188 * 2189 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 2190 * @param enable true = setup and false = tear down TDLS 2191 */ 2192 public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) { 2193 try { 2194 mService.enableTdls(remoteIPAddress.getHostAddress(), enable); 2195 } catch (RemoteException e) { 2196 throw e.rethrowFromSystemServer(); 2197 } 2198 } 2199 2200 /** 2201 * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except 2202 * this version allows you to specify remote endpoint with a MAC address. 2203 * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab 2204 * @param enable true = setup and false = tear down TDLS 2205 */ 2206 public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) { 2207 try { 2208 mService.enableTdlsWithMacAddress(remoteMacAddress, enable); 2209 } catch (RemoteException e) { 2210 throw e.rethrowFromSystemServer(); 2211 } 2212 } 2213 2214 /* TODO: deprecate synchronous API and open up the following API */ 2215 2216 private static final int BASE = Protocol.BASE_WIFI_MANAGER; 2217 2218 /* Commands to WifiService */ 2219 /** @hide */ 2220 public static final int CONNECT_NETWORK = BASE + 1; 2221 /** @hide */ 2222 public static final int CONNECT_NETWORK_FAILED = BASE + 2; 2223 /** @hide */ 2224 public static final int CONNECT_NETWORK_SUCCEEDED = BASE + 3; 2225 2226 /** @hide */ 2227 public static final int FORGET_NETWORK = BASE + 4; 2228 /** @hide */ 2229 public static final int FORGET_NETWORK_FAILED = BASE + 5; 2230 /** @hide */ 2231 public static final int FORGET_NETWORK_SUCCEEDED = BASE + 6; 2232 2233 /** @hide */ 2234 public static final int SAVE_NETWORK = BASE + 7; 2235 /** @hide */ 2236 public static final int SAVE_NETWORK_FAILED = BASE + 8; 2237 /** @hide */ 2238 public static final int SAVE_NETWORK_SUCCEEDED = BASE + 9; 2239 2240 /** @hide 2241 * @deprecated This is deprecated 2242 */ 2243 public static final int START_WPS = BASE + 10; 2244 /** @hide 2245 * @deprecated This is deprecated 2246 */ 2247 public static final int START_WPS_SUCCEEDED = BASE + 11; 2248 /** @hide 2249 * @deprecated This is deprecated 2250 */ 2251 public static final int WPS_FAILED = BASE + 12; 2252 /** @hide 2253 * @deprecated This is deprecated 2254 */ 2255 public static final int WPS_COMPLETED = BASE + 13; 2256 2257 /** @hide 2258 * @deprecated This is deprecated 2259 */ 2260 public static final int CANCEL_WPS = BASE + 14; 2261 /** @hide 2262 * @deprecated This is deprecated 2263 */ 2264 public static final int CANCEL_WPS_FAILED = BASE + 15; 2265 /** @hide 2266 * @deprecated This is deprecated 2267 */ 2268 public static final int CANCEL_WPS_SUCCEDED = BASE + 16; 2269 2270 /** @hide */ 2271 public static final int DISABLE_NETWORK = BASE + 17; 2272 /** @hide */ 2273 public static final int DISABLE_NETWORK_FAILED = BASE + 18; 2274 /** @hide */ 2275 public static final int DISABLE_NETWORK_SUCCEEDED = BASE + 19; 2276 2277 /** @hide */ 2278 public static final int RSSI_PKTCNT_FETCH = BASE + 20; 2279 /** @hide */ 2280 public static final int RSSI_PKTCNT_FETCH_SUCCEEDED = BASE + 21; 2281 /** @hide */ 2282 public static final int RSSI_PKTCNT_FETCH_FAILED = BASE + 22; 2283 2284 /** 2285 * Passed with {@link ActionListener#onFailure}. 2286 * Indicates that the operation failed due to an internal error. 2287 * @hide 2288 */ 2289 public static final int ERROR = 0; 2290 2291 /** 2292 * Passed with {@link ActionListener#onFailure}. 2293 * Indicates that the operation is already in progress 2294 * @hide 2295 */ 2296 public static final int IN_PROGRESS = 1; 2297 2298 /** 2299 * Passed with {@link ActionListener#onFailure}. 2300 * Indicates that the operation failed because the framework is busy and 2301 * unable to service the request 2302 * @hide 2303 */ 2304 public static final int BUSY = 2; 2305 2306 /* WPS specific errors */ 2307 /** WPS overlap detected 2308 * @deprecated This is deprecated 2309 */ 2310 public static final int WPS_OVERLAP_ERROR = 3; 2311 /** WEP on WPS is prohibited 2312 * @deprecated This is deprecated 2313 */ 2314 public static final int WPS_WEP_PROHIBITED = 4; 2315 /** TKIP only prohibited 2316 * @deprecated This is deprecated 2317 */ 2318 public static final int WPS_TKIP_ONLY_PROHIBITED = 5; 2319 /** Authentication failure on WPS 2320 * @deprecated This is deprecated 2321 */ 2322 public static final int WPS_AUTH_FAILURE = 6; 2323 /** WPS timed out 2324 * @deprecated This is deprecated 2325 */ 2326 public static final int WPS_TIMED_OUT = 7; 2327 2328 /** 2329 * Passed with {@link ActionListener#onFailure}. 2330 * Indicates that the operation failed due to invalid inputs 2331 * @hide 2332 */ 2333 public static final int INVALID_ARGS = 8; 2334 2335 /** 2336 * Passed with {@link ActionListener#onFailure}. 2337 * Indicates that the operation failed due to user permissions. 2338 * @hide 2339 */ 2340 public static final int NOT_AUTHORIZED = 9; 2341 2342 /** 2343 * Interface for callback invocation on an application action 2344 * @hide 2345 */ 2346 @SystemApi 2347 public interface ActionListener { 2348 /** 2349 * The operation succeeded. 2350 * This is called when the scan request has been validated and ready 2351 * to sent to driver. 2352 */ 2353 public void onSuccess(); 2354 /** 2355 * The operation failed. 2356 * This is called when the scan request failed. 2357 * @param reason The reason for failure could be one of the following: 2358 * {@link #REASON_INVALID_REQUEST}} is specified when scan request parameters are invalid. 2359 * {@link #REASON_NOT_AUTHORIZED} is specified when requesting app doesn't have the required 2360 * permission to request a scan. 2361 * {@link #REASON_UNSPECIFIED} is specified when driver reports a scan failure. 2362 */ 2363 public void onFailure(int reason); 2364 } 2365 2366 /** Interface for callback invocation on a start WPS action 2367 * @deprecated This is deprecated 2368 */ 2369 public static abstract class WpsCallback { 2370 2371 /** WPS start succeeded 2372 * @deprecated This API is deprecated 2373 */ 2374 public abstract void onStarted(String pin); 2375 2376 /** WPS operation completed successfully 2377 * @deprecated This API is deprecated 2378 */ 2379 public abstract void onSucceeded(); 2380 2381 /** 2382 * WPS operation failed 2383 * @param reason The reason for failure could be one of 2384 * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR}, 2385 * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE} 2386 * and some generic errors. 2387 * @deprecated This API is deprecated 2388 */ 2389 public abstract void onFailed(int reason); 2390 } 2391 2392 /** Interface for callback invocation on a TX packet count poll action {@hide} */ 2393 public interface TxPacketCountListener { 2394 /** 2395 * The operation succeeded 2396 * @param count TX packet counter 2397 */ 2398 public void onSuccess(int count); 2399 /** 2400 * The operation failed 2401 * @param reason The reason for failure could be one of 2402 * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY} 2403 */ 2404 public void onFailure(int reason); 2405 } 2406 2407 /** 2408 * Base class for soft AP callback. Should be extended by applications and set when calling 2409 * {@link WifiManager#registerSoftApCallback(SoftApCallback, Handler)}. 2410 * 2411 * @hide 2412 */ 2413 public interface SoftApCallback { 2414 /** 2415 * Called when soft AP state changes. 2416 * 2417 * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, 2418 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 2419 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 2420 * @param failureReason reason when in failed state. One of 2421 * {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL} 2422 */ 2423 public abstract void onStateChanged(@WifiApState int state, 2424 @SapStartFailure int failureReason); 2425 2426 /** 2427 * Called when number of connected clients to soft AP changes. 2428 * 2429 * @param numClients number of connected clients 2430 */ 2431 public abstract void onNumClientsChanged(int numClients); 2432 } 2433 2434 /** 2435 * Callback proxy for SoftApCallback objects. 2436 * 2437 * @hide 2438 */ 2439 private static class SoftApCallbackProxy extends ISoftApCallback.Stub { 2440 private final Handler mHandler; 2441 private final SoftApCallback mCallback; 2442 2443 SoftApCallbackProxy(Looper looper, SoftApCallback callback) { 2444 mHandler = new Handler(looper); 2445 mCallback = callback; 2446 } 2447 2448 @Override 2449 public void onStateChanged(int state, int failureReason) throws RemoteException { 2450 Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + ", failureReason=" + 2451 failureReason); 2452 mHandler.post(() -> { 2453 mCallback.onStateChanged(state, failureReason); 2454 }); 2455 } 2456 2457 @Override onNumClientsChanged(int numClients)2458 public void onNumClientsChanged(int numClients) throws RemoteException { 2459 Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients); 2460 mHandler.post(() -> { 2461 mCallback.onNumClientsChanged(numClients); 2462 }); 2463 } 2464 } 2465 2466 /** 2467 * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the current 2468 * soft AP state and number of connected devices immediately after a successful call to this API 2469 * via callback. Note that receiving an immediate WIFI_AP_STATE_FAILED value for soft AP state 2470 * indicates that the latest attempt to start soft AP has failed. Caller can unregister a 2471 * previously registered callback using {@link unregisterSoftApCallback} 2472 * <p> 2473 * Applications should have the 2474 * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers 2475 * without the permission will trigger a {@link java.lang.SecurityException}. 2476 * <p> 2477 * 2478 * @param callback Callback for soft AP events 2479 * @param handler The Handler on whose thread to execute the callbacks of the {@code callback} 2480 * object. If null, then the application's main thread will be used. 2481 * 2482 * @hide 2483 */ 2484 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) registerSoftApCallback(@onNull SoftApCallback callback, @Nullable Handler handler)2485 public void registerSoftApCallback(@NonNull SoftApCallback callback, 2486 @Nullable Handler handler) { 2487 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 2488 Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", handler=" + handler); 2489 2490 Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); 2491 Binder binder = new Binder(); 2492 try { 2493 mService.registerSoftApCallback(binder, new SoftApCallbackProxy(looper, callback), 2494 callback.hashCode()); 2495 } catch (RemoteException e) { 2496 throw e.rethrowFromSystemServer(); 2497 } 2498 } 2499 2500 /** 2501 * Allow callers to unregister a previously registered callback. After calling this method, 2502 * applications will no longer receive soft AP events. 2503 * 2504 * @param callback Callback to unregister for soft AP events 2505 * 2506 * @hide 2507 */ 2508 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) unregisterSoftApCallback(@onNull SoftApCallback callback)2509 public void unregisterSoftApCallback(@NonNull SoftApCallback callback) { 2510 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 2511 Log.v(TAG, "unregisterSoftApCallback: callback=" + callback); 2512 2513 try { 2514 mService.unregisterSoftApCallback(callback.hashCode()); 2515 } catch (RemoteException e) { 2516 throw e.rethrowFromSystemServer(); 2517 } 2518 } 2519 2520 /** 2521 * LocalOnlyHotspotReservation that contains the {@link WifiConfiguration} for the active 2522 * LocalOnlyHotspot request. 2523 * <p> 2524 * Applications requesting LocalOnlyHotspot for sharing will receive an instance of the 2525 * LocalOnlyHotspotReservation in the 2526 * {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call. This 2527 * reservation contains the relevant {@link WifiConfiguration}. 2528 * When an application is done with the LocalOnlyHotspot, they should call {@link 2529 * LocalOnlyHotspotReservation#close()}. Once this happens, the application will not receive 2530 * any further callbacks. If the LocalOnlyHotspot is stopped due to a 2531 * user triggered mode change, applications will be notified via the {@link 2532 * LocalOnlyHotspotCallback#onStopped()} callback. 2533 */ 2534 public class LocalOnlyHotspotReservation implements AutoCloseable { 2535 2536 private final CloseGuard mCloseGuard = CloseGuard.get(); 2537 private final WifiConfiguration mConfig; 2538 2539 /** @hide */ 2540 @VisibleForTesting LocalOnlyHotspotReservation(WifiConfiguration config)2541 public LocalOnlyHotspotReservation(WifiConfiguration config) { 2542 mConfig = config; 2543 mCloseGuard.open("close"); 2544 } 2545 getWifiConfiguration()2546 public WifiConfiguration getWifiConfiguration() { 2547 return mConfig; 2548 } 2549 2550 @Override close()2551 public void close() { 2552 try { 2553 stopLocalOnlyHotspot(); 2554 mCloseGuard.close(); 2555 } catch (Exception e) { 2556 Log.e(TAG, "Failed to stop Local Only Hotspot."); 2557 } 2558 } 2559 2560 @Override finalize()2561 protected void finalize() throws Throwable { 2562 try { 2563 if (mCloseGuard != null) { 2564 mCloseGuard.warnIfOpen(); 2565 } 2566 close(); 2567 } finally { 2568 super.finalize(); 2569 } 2570 } 2571 } 2572 2573 /** 2574 * Callback class for applications to receive updates about the LocalOnlyHotspot status. 2575 */ 2576 public static class LocalOnlyHotspotCallback { 2577 /** @hide */ 2578 public static final int REQUEST_REGISTERED = 0; 2579 2580 public static final int ERROR_NO_CHANNEL = 1; 2581 public static final int ERROR_GENERIC = 2; 2582 public static final int ERROR_INCOMPATIBLE_MODE = 3; 2583 public static final int ERROR_TETHERING_DISALLOWED = 4; 2584 2585 /** LocalOnlyHotspot start succeeded. */ onStarted(LocalOnlyHotspotReservation reservation)2586 public void onStarted(LocalOnlyHotspotReservation reservation) {}; 2587 2588 /** 2589 * LocalOnlyHotspot stopped. 2590 * <p> 2591 * The LocalOnlyHotspot can be disabled at any time by the user. When this happens, 2592 * applications will be notified that it was stopped. This will not be invoked when an 2593 * application calls {@link LocalOnlyHotspotReservation#close()}. 2594 */ onStopped()2595 public void onStopped() {}; 2596 2597 /** 2598 * LocalOnlyHotspot failed to start. 2599 * <p> 2600 * Applications can attempt to call 2601 * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} again at 2602 * a later time. 2603 * <p> 2604 * @param reason The reason for failure could be one of: {@link 2605 * #ERROR_TETHERING_DISALLOWED}, {@link #ERROR_INCOMPATIBLE_MODE}, 2606 * {@link #ERROR_NO_CHANNEL}, or {@link #ERROR_GENERIC}. 2607 */ onFailed(int reason)2608 public void onFailed(int reason) { }; 2609 } 2610 2611 /** 2612 * Callback proxy for LocalOnlyHotspotCallback objects. 2613 */ 2614 private static class LocalOnlyHotspotCallbackProxy { 2615 private final Handler mHandler; 2616 private final WeakReference<WifiManager> mWifiManager; 2617 private final Looper mLooper; 2618 private final Messenger mMessenger; 2619 2620 /** 2621 * Constructs a {@link LocalOnlyHotspotCallback} using the specified looper. All callbacks 2622 * will be delivered on the thread of the specified looper. 2623 * 2624 * @param manager WifiManager 2625 * @param looper Looper for delivering callbacks 2626 * @param callback LocalOnlyHotspotCallback to notify the calling application. 2627 */ LocalOnlyHotspotCallbackProxy(WifiManager manager, Looper looper, final LocalOnlyHotspotCallback callback)2628 LocalOnlyHotspotCallbackProxy(WifiManager manager, Looper looper, 2629 final LocalOnlyHotspotCallback callback) { 2630 mWifiManager = new WeakReference<>(manager); 2631 mLooper = looper; 2632 2633 mHandler = new Handler(looper) { 2634 @Override 2635 public void handleMessage(Message msg) { 2636 Log.d(TAG, "LocalOnlyHotspotCallbackProxy: handle message what: " 2637 + msg.what + " msg: " + msg); 2638 2639 WifiManager manager = mWifiManager.get(); 2640 if (manager == null) { 2641 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: handle message post GC"); 2642 return; 2643 } 2644 2645 switch (msg.what) { 2646 case HOTSPOT_STARTED: 2647 WifiConfiguration config = (WifiConfiguration) msg.obj; 2648 if (config == null) { 2649 Log.e(TAG, "LocalOnlyHotspotCallbackProxy: config cannot be null."); 2650 callback.onFailed(LocalOnlyHotspotCallback.ERROR_GENERIC); 2651 return; 2652 } 2653 callback.onStarted(manager.new LocalOnlyHotspotReservation(config)); 2654 break; 2655 case HOTSPOT_STOPPED: 2656 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: hotspot stopped"); 2657 callback.onStopped(); 2658 break; 2659 case HOTSPOT_FAILED: 2660 int reasonCode = msg.arg1; 2661 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: failed to start. reason: " 2662 + reasonCode); 2663 callback.onFailed(reasonCode); 2664 Log.w(TAG, "done with the callback..."); 2665 break; 2666 default: 2667 Log.e(TAG, "LocalOnlyHotspotCallbackProxy unhandled message. type: " 2668 + msg.what); 2669 } 2670 } 2671 }; 2672 mMessenger = new Messenger(mHandler); 2673 } 2674 getMessenger()2675 public Messenger getMessenger() { 2676 return mMessenger; 2677 } 2678 2679 /** 2680 * Helper method allowing the the incoming application call to move the onFailed callback 2681 * over to the desired callback thread. 2682 * 2683 * @param reason int representing the error type 2684 */ notifyFailed(int reason)2685 public void notifyFailed(int reason) throws RemoteException { 2686 Message msg = Message.obtain(); 2687 msg.what = HOTSPOT_FAILED; 2688 msg.arg1 = reason; 2689 mMessenger.send(msg); 2690 } 2691 } 2692 2693 /** 2694 * LocalOnlyHotspotSubscription that is an AutoCloseable object for tracking applications 2695 * watching for LocalOnlyHotspot changes. 2696 * 2697 * @hide 2698 */ 2699 public class LocalOnlyHotspotSubscription implements AutoCloseable { 2700 private final CloseGuard mCloseGuard = CloseGuard.get(); 2701 2702 /** @hide */ 2703 @VisibleForTesting LocalOnlyHotspotSubscription()2704 public LocalOnlyHotspotSubscription() { 2705 mCloseGuard.open("close"); 2706 } 2707 2708 @Override close()2709 public void close() { 2710 try { 2711 unregisterLocalOnlyHotspotObserver(); 2712 mCloseGuard.close(); 2713 } catch (Exception e) { 2714 Log.e(TAG, "Failed to unregister LocalOnlyHotspotObserver."); 2715 } 2716 } 2717 2718 @Override finalize()2719 protected void finalize() throws Throwable { 2720 try { 2721 if (mCloseGuard != null) { 2722 mCloseGuard.warnIfOpen(); 2723 } 2724 close(); 2725 } finally { 2726 super.finalize(); 2727 } 2728 } 2729 } 2730 2731 /** 2732 * Class to notify calling applications that watch for changes in LocalOnlyHotspot of updates. 2733 * 2734 * @hide 2735 */ 2736 public static class LocalOnlyHotspotObserver { 2737 /** 2738 * Confirm registration for LocalOnlyHotspotChanges by returning a 2739 * LocalOnlyHotspotSubscription. 2740 */ onRegistered(LocalOnlyHotspotSubscription subscription)2741 public void onRegistered(LocalOnlyHotspotSubscription subscription) {}; 2742 2743 /** 2744 * LocalOnlyHotspot started with the supplied config. 2745 */ onStarted(WifiConfiguration config)2746 public void onStarted(WifiConfiguration config) {}; 2747 2748 /** 2749 * LocalOnlyHotspot stopped. 2750 */ onStopped()2751 public void onStopped() {}; 2752 } 2753 2754 /** 2755 * Callback proxy for LocalOnlyHotspotObserver objects. 2756 */ 2757 private static class LocalOnlyHotspotObserverProxy { 2758 private final Handler mHandler; 2759 private final WeakReference<WifiManager> mWifiManager; 2760 private final Looper mLooper; 2761 private final Messenger mMessenger; 2762 2763 /** 2764 * Constructs a {@link LocalOnlyHotspotObserverProxy} using the specified looper. 2765 * All callbacks will be delivered on the thread of the specified looper. 2766 * 2767 * @param manager WifiManager 2768 * @param looper Looper for delivering callbacks 2769 * @param observer LocalOnlyHotspotObserver to notify the calling application. 2770 */ LocalOnlyHotspotObserverProxy(WifiManager manager, Looper looper, final LocalOnlyHotspotObserver observer)2771 LocalOnlyHotspotObserverProxy(WifiManager manager, Looper looper, 2772 final LocalOnlyHotspotObserver observer) { 2773 mWifiManager = new WeakReference<>(manager); 2774 mLooper = looper; 2775 2776 mHandler = new Handler(looper) { 2777 @Override 2778 public void handleMessage(Message msg) { 2779 Log.d(TAG, "LocalOnlyHotspotObserverProxy: handle message what: " 2780 + msg.what + " msg: " + msg); 2781 2782 WifiManager manager = mWifiManager.get(); 2783 if (manager == null) { 2784 Log.w(TAG, "LocalOnlyHotspotObserverProxy: handle message post GC"); 2785 return; 2786 } 2787 2788 switch (msg.what) { 2789 case HOTSPOT_OBSERVER_REGISTERED: 2790 observer.onRegistered(manager.new LocalOnlyHotspotSubscription()); 2791 break; 2792 case HOTSPOT_STARTED: 2793 WifiConfiguration config = (WifiConfiguration) msg.obj; 2794 if (config == null) { 2795 Log.e(TAG, "LocalOnlyHotspotObserverProxy: config cannot be null."); 2796 return; 2797 } 2798 observer.onStarted(config); 2799 break; 2800 case HOTSPOT_STOPPED: 2801 observer.onStopped(); 2802 break; 2803 default: 2804 Log.e(TAG, "LocalOnlyHotspotObserverProxy unhandled message. type: " 2805 + msg.what); 2806 } 2807 } 2808 }; 2809 mMessenger = new Messenger(mHandler); 2810 } 2811 getMessenger()2812 public Messenger getMessenger() { 2813 return mMessenger; 2814 } 2815 registered()2816 public void registered() throws RemoteException { 2817 Message msg = Message.obtain(); 2818 msg.what = HOTSPOT_OBSERVER_REGISTERED; 2819 mMessenger.send(msg); 2820 } 2821 } 2822 2823 // Ensure that multiple ServiceHandler threads do not interleave message dispatch. 2824 private static final Object sServiceHandlerDispatchLock = new Object(); 2825 2826 private class ServiceHandler extends Handler { ServiceHandler(Looper looper)2827 ServiceHandler(Looper looper) { 2828 super(looper); 2829 } 2830 2831 @Override handleMessage(Message message)2832 public void handleMessage(Message message) { 2833 synchronized (sServiceHandlerDispatchLock) { 2834 dispatchMessageToListeners(message); 2835 } 2836 } 2837 dispatchMessageToListeners(Message message)2838 private void dispatchMessageToListeners(Message message) { 2839 Object listener = removeListener(message.arg2); 2840 switch (message.what) { 2841 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 2842 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 2843 mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 2844 } else { 2845 Log.e(TAG, "Failed to set up channel connection"); 2846 // This will cause all further async API calls on the WifiManager 2847 // to fail and throw an exception 2848 mAsyncChannel = null; 2849 } 2850 mConnected.countDown(); 2851 break; 2852 case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: 2853 // Ignore 2854 break; 2855 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 2856 Log.e(TAG, "Channel connection lost"); 2857 // This will cause all further async API calls on the WifiManager 2858 // to fail and throw an exception 2859 mAsyncChannel = null; 2860 getLooper().quit(); 2861 break; 2862 /* ActionListeners grouped together */ 2863 case WifiManager.CONNECT_NETWORK_FAILED: 2864 case WifiManager.FORGET_NETWORK_FAILED: 2865 case WifiManager.SAVE_NETWORK_FAILED: 2866 case WifiManager.DISABLE_NETWORK_FAILED: 2867 if (listener != null) { 2868 ((ActionListener) listener).onFailure(message.arg1); 2869 } 2870 break; 2871 /* ActionListeners grouped together */ 2872 case WifiManager.CONNECT_NETWORK_SUCCEEDED: 2873 case WifiManager.FORGET_NETWORK_SUCCEEDED: 2874 case WifiManager.SAVE_NETWORK_SUCCEEDED: 2875 case WifiManager.DISABLE_NETWORK_SUCCEEDED: 2876 if (listener != null) { 2877 ((ActionListener) listener).onSuccess(); 2878 } 2879 break; 2880 case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED: 2881 if (listener != null) { 2882 RssiPacketCountInfo info = (RssiPacketCountInfo) message.obj; 2883 if (info != null) 2884 ((TxPacketCountListener) listener).onSuccess(info.txgood + info.txbad); 2885 else 2886 ((TxPacketCountListener) listener).onFailure(ERROR); 2887 } 2888 break; 2889 case WifiManager.RSSI_PKTCNT_FETCH_FAILED: 2890 if (listener != null) { 2891 ((TxPacketCountListener) listener).onFailure(message.arg1); 2892 } 2893 break; 2894 default: 2895 //ignore 2896 break; 2897 } 2898 } 2899 } 2900 putListener(Object listener)2901 private int putListener(Object listener) { 2902 if (listener == null) return INVALID_KEY; 2903 int key; 2904 synchronized (mListenerMapLock) { 2905 do { 2906 key = mListenerKey++; 2907 } while (key == INVALID_KEY); 2908 mListenerMap.put(key, listener); 2909 } 2910 return key; 2911 } 2912 removeListener(int key)2913 private Object removeListener(int key) { 2914 if (key == INVALID_KEY) return null; 2915 synchronized (mListenerMapLock) { 2916 Object listener = mListenerMap.get(key); 2917 mListenerMap.remove(key); 2918 return listener; 2919 } 2920 } 2921 getChannel()2922 private synchronized AsyncChannel getChannel() { 2923 if (mAsyncChannel == null) { 2924 Messenger messenger = getWifiServiceMessenger(); 2925 if (messenger == null) { 2926 throw new IllegalStateException( 2927 "getWifiServiceMessenger() returned null! This is invalid."); 2928 } 2929 2930 mAsyncChannel = new AsyncChannel(); 2931 mConnected = new CountDownLatch(1); 2932 2933 Handler handler = new ServiceHandler(mLooper); 2934 mAsyncChannel.connect(mContext, handler, messenger); 2935 try { 2936 mConnected.await(); 2937 } catch (InterruptedException e) { 2938 Log.e(TAG, "interrupted wait at init"); 2939 } 2940 } 2941 return mAsyncChannel; 2942 } 2943 2944 /** 2945 * Connect to a network with the given configuration. The network also 2946 * gets added to the list of configured networks for the foreground user. 2947 * 2948 * For a new network, this function is used instead of a 2949 * sequence of addNetwork(), enableNetwork(), and reconnect() 2950 * 2951 * @param config the set of variables that describe the configuration, 2952 * contained in a {@link WifiConfiguration} object. 2953 * @param listener for callbacks on success or failure. Can be null. 2954 * @throws IllegalStateException if the WifiManager instance needs to be 2955 * initialized again 2956 * 2957 * @hide 2958 */ 2959 @SystemApi connect(WifiConfiguration config, ActionListener listener)2960 public void connect(WifiConfiguration config, ActionListener listener) { 2961 if (config == null) throw new IllegalArgumentException("config cannot be null"); 2962 // Use INVALID_NETWORK_ID for arg1 when passing a config object 2963 // arg1 is used to pass network id when the network already exists 2964 getChannel().sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, 2965 putListener(listener), config); 2966 } 2967 2968 /** 2969 * Connect to a network with the given networkId. 2970 * 2971 * This function is used instead of a enableNetwork() and reconnect() 2972 * 2973 * @param networkId the ID of the network as returned by {@link #addNetwork} or {@link 2974 * getConfiguredNetworks}. 2975 * @param listener for callbacks on success or failure. Can be null. 2976 * @throws IllegalStateException if the WifiManager instance needs to be 2977 * initialized again 2978 * @hide 2979 */ connect(int networkId, ActionListener listener)2980 public void connect(int networkId, ActionListener listener) { 2981 if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 2982 getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener)); 2983 } 2984 2985 /** 2986 * Save the given network to the list of configured networks for the 2987 * foreground user. If the network already exists, the configuration 2988 * is updated. Any new network is enabled by default. 2989 * 2990 * For a new network, this function is used instead of a 2991 * sequence of addNetwork() and enableNetwork(). 2992 * 2993 * For an existing network, it accomplishes the task of updateNetwork() 2994 * 2995 * This API will cause reconnect if the crecdentials of the current active 2996 * connection has been changed. 2997 * 2998 * @param config the set of variables that describe the configuration, 2999 * contained in a {@link WifiConfiguration} object. 3000 * @param listener for callbacks on success or failure. Can be null. 3001 * @throws IllegalStateException if the WifiManager instance needs to be 3002 * initialized again 3003 * @hide 3004 */ save(WifiConfiguration config, ActionListener listener)3005 public void save(WifiConfiguration config, ActionListener listener) { 3006 if (config == null) throw new IllegalArgumentException("config cannot be null"); 3007 getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config); 3008 } 3009 3010 /** 3011 * Delete the network from the list of configured networks for the 3012 * foreground user. 3013 * 3014 * This function is used instead of a sequence of removeNetwork() 3015 * 3016 * @param config the set of variables that describe the configuration, 3017 * contained in a {@link WifiConfiguration} object. 3018 * @param listener for callbacks on success or failure. Can be null. 3019 * @throws IllegalStateException if the WifiManager instance needs to be 3020 * initialized again 3021 * @hide 3022 */ forget(int netId, ActionListener listener)3023 public void forget(int netId, ActionListener listener) { 3024 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 3025 getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener)); 3026 } 3027 3028 /** 3029 * Disable network 3030 * 3031 * @param netId is the network Id 3032 * @param listener for callbacks on success or failure. Can be null. 3033 * @throws IllegalStateException if the WifiManager instance needs to be 3034 * initialized again 3035 * @hide 3036 */ disable(int netId, ActionListener listener)3037 public void disable(int netId, ActionListener listener) { 3038 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 3039 getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener)); 3040 } 3041 3042 /** 3043 * Disable ephemeral Network 3044 * 3045 * @param SSID, in the format of WifiConfiguration's SSID. 3046 * @hide 3047 */ disableEphemeralNetwork(String SSID)3048 public void disableEphemeralNetwork(String SSID) { 3049 if (SSID == null) throw new IllegalArgumentException("SSID cannot be null"); 3050 try { 3051 mService.disableEphemeralNetwork(SSID, mContext.getOpPackageName()); 3052 } catch (RemoteException e) { 3053 throw e.rethrowFromSystemServer(); 3054 } 3055 } 3056 3057 /** 3058 * WPS suport has been deprecated from Client mode and this method will immediately trigger 3059 * {@link WpsCallback#onFailed(int)} with a generic error. 3060 * 3061 * @param config WPS configuration (does not support {@link WpsInfo#LABEL}) 3062 * @param listener for callbacks on success or failure. Can be null. 3063 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 3064 * @deprecated This API is deprecated 3065 */ startWps(WpsInfo config, WpsCallback listener)3066 public void startWps(WpsInfo config, WpsCallback listener) { 3067 if (listener != null ) { 3068 listener.onFailed(ERROR); 3069 } 3070 } 3071 3072 /** 3073 * WPS support has been deprecated from Client mode and this method will immediately trigger 3074 * {@link WpsCallback#onFailed(int)} with a generic error. 3075 * 3076 * @param listener for callbacks on success or failure. Can be null. 3077 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 3078 * @deprecated This API is deprecated 3079 */ cancelWps(WpsCallback listener)3080 public void cancelWps(WpsCallback listener) { 3081 if (listener != null) { 3082 listener.onFailed(ERROR); 3083 } 3084 } 3085 3086 /** 3087 * Get a reference to WifiService handler. This is used by a client to establish 3088 * an AsyncChannel communication with WifiService 3089 * 3090 * @return Messenger pointing to the WifiService handler 3091 * @hide 3092 */ getWifiServiceMessenger()3093 public Messenger getWifiServiceMessenger() { 3094 try { 3095 return mService.getWifiServiceMessenger(mContext.getOpPackageName()); 3096 } catch (RemoteException e) { 3097 throw e.rethrowFromSystemServer(); 3098 } 3099 } 3100 3101 3102 /** 3103 * Allows an application to keep the Wi-Fi radio awake. 3104 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 3105 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 3106 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 3107 * WifiLocks are held in any application. 3108 * <p> 3109 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 3110 * could function over a mobile network, if available. A program that needs to download large 3111 * files should hold a WifiLock to ensure that the download will complete, but a program whose 3112 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 3113 * affecting battery life. 3114 * <p> 3115 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 3116 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 3117 * is idle. 3118 * <p> 3119 * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK} 3120 * permission in an {@code <uses-permission>} element of the application's manifest. 3121 */ 3122 public class WifiLock { 3123 private String mTag; 3124 private final IBinder mBinder; 3125 private int mRefCount; 3126 int mLockType; 3127 private boolean mRefCounted; 3128 private boolean mHeld; 3129 private WorkSource mWorkSource; 3130 WifiLock(int lockType, String tag)3131 private WifiLock(int lockType, String tag) { 3132 mTag = tag; 3133 mLockType = lockType; 3134 mBinder = new Binder(); 3135 mRefCount = 0; 3136 mRefCounted = true; 3137 mHeld = false; 3138 } 3139 3140 /** 3141 * Locks the Wi-Fi radio on until {@link #release} is called. 3142 * 3143 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 3144 * reference count, and the radio will remain locked as long as the reference count is 3145 * above zero. 3146 * 3147 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 3148 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 3149 * will be required, regardless of the number of times that {@code acquire} is called. 3150 */ acquire()3151 public void acquire() { 3152 synchronized (mBinder) { 3153 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 3154 try { 3155 mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); 3156 synchronized (WifiManager.this) { 3157 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 3158 mService.releaseWifiLock(mBinder); 3159 throw new UnsupportedOperationException( 3160 "Exceeded maximum number of wifi locks"); 3161 } 3162 mActiveLockCount++; 3163 } 3164 } catch (RemoteException e) { 3165 throw e.rethrowFromSystemServer(); 3166 } 3167 mHeld = true; 3168 } 3169 } 3170 } 3171 3172 /** 3173 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 3174 * 3175 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 3176 * reference count, and the radio will be unlocked only when the reference count reaches 3177 * zero. If the reference count goes below zero (that is, if {@code release} is called 3178 * a greater number of times than {@link #acquire}), an exception is thrown. 3179 * 3180 * If this WifiLock is not reference-counted, the first call to {@code release} (after 3181 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 3182 * calls will be ignored. 3183 */ release()3184 public void release() { 3185 synchronized (mBinder) { 3186 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 3187 try { 3188 mService.releaseWifiLock(mBinder); 3189 synchronized (WifiManager.this) { 3190 mActiveLockCount--; 3191 } 3192 } catch (RemoteException e) { 3193 throw e.rethrowFromSystemServer(); 3194 } 3195 mHeld = false; 3196 } 3197 if (mRefCount < 0) { 3198 throw new RuntimeException("WifiLock under-locked " + mTag); 3199 } 3200 } 3201 } 3202 3203 /** 3204 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 3205 * 3206 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 3207 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 3208 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 3209 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 3210 * radio whenever {@link #release} is called and it is locked. 3211 * 3212 * @param refCounted true if this WifiLock should keep a reference count 3213 */ setReferenceCounted(boolean refCounted)3214 public void setReferenceCounted(boolean refCounted) { 3215 mRefCounted = refCounted; 3216 } 3217 3218 /** 3219 * Checks whether this WifiLock is currently held. 3220 * 3221 * @return true if this WifiLock is held, false otherwise 3222 */ isHeld()3223 public boolean isHeld() { 3224 synchronized (mBinder) { 3225 return mHeld; 3226 } 3227 } 3228 setWorkSource(WorkSource ws)3229 public void setWorkSource(WorkSource ws) { 3230 synchronized (mBinder) { 3231 if (ws != null && ws.isEmpty()) { 3232 ws = null; 3233 } 3234 boolean changed = true; 3235 if (ws == null) { 3236 mWorkSource = null; 3237 } else { 3238 ws.clearNames(); 3239 if (mWorkSource == null) { 3240 changed = mWorkSource != null; 3241 mWorkSource = new WorkSource(ws); 3242 } else { 3243 changed = !mWorkSource.equals(ws); 3244 if (changed) { 3245 mWorkSource.set(ws); 3246 } 3247 } 3248 } 3249 if (changed && mHeld) { 3250 try { 3251 mService.updateWifiLockWorkSource(mBinder, mWorkSource); 3252 } catch (RemoteException e) { 3253 throw e.rethrowFromSystemServer(); 3254 } 3255 } 3256 } 3257 } 3258 toString()3259 public String toString() { 3260 String s1, s2, s3; 3261 synchronized (mBinder) { 3262 s1 = Integer.toHexString(System.identityHashCode(this)); 3263 s2 = mHeld ? "held; " : ""; 3264 if (mRefCounted) { 3265 s3 = "refcounted: refcount = " + mRefCount; 3266 } else { 3267 s3 = "not refcounted"; 3268 } 3269 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 3270 } 3271 } 3272 3273 @Override finalize()3274 protected void finalize() throws Throwable { 3275 super.finalize(); 3276 synchronized (mBinder) { 3277 if (mHeld) { 3278 try { 3279 mService.releaseWifiLock(mBinder); 3280 synchronized (WifiManager.this) { 3281 mActiveLockCount--; 3282 } 3283 } catch (RemoteException e) { 3284 throw e.rethrowFromSystemServer(); 3285 } 3286 } 3287 } 3288 } 3289 } 3290 3291 /** 3292 * Creates a new WifiLock. 3293 * 3294 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL}, 3295 * {@link #WIFI_MODE_FULL_HIGH_PERF} and {@link #WIFI_MODE_SCAN_ONLY} for 3296 * descriptions of the types of Wi-Fi locks. 3297 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 3298 * never shown to the user under normal conditions, but should be descriptive 3299 * enough to identify your application and the specific WifiLock within it, if it 3300 * holds multiple WifiLocks. 3301 * 3302 * @return a new, unacquired WifiLock with the given tag. 3303 * 3304 * @see WifiLock 3305 */ createWifiLock(int lockType, String tag)3306 public WifiLock createWifiLock(int lockType, String tag) { 3307 return new WifiLock(lockType, tag); 3308 } 3309 3310 /** 3311 * Creates a new WifiLock. 3312 * 3313 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 3314 * never shown to the user under normal conditions, but should be descriptive 3315 * enough to identify your application and the specific WifiLock within it, if it 3316 * holds multiple WifiLocks. 3317 * 3318 * @return a new, unacquired WifiLock with the given tag. 3319 * 3320 * @see WifiLock 3321 */ createWifiLock(String tag)3322 public WifiLock createWifiLock(String tag) { 3323 return new WifiLock(WIFI_MODE_FULL, tag); 3324 } 3325 3326 3327 /** 3328 * Create a new MulticastLock 3329 * 3330 * @param tag a tag for the MulticastLock to identify it in debugging 3331 * messages. This string is never shown to the user under 3332 * normal conditions, but should be descriptive enough to 3333 * identify your application and the specific MulticastLock 3334 * within it, if it holds multiple MulticastLocks. 3335 * 3336 * @return a new, unacquired MulticastLock with the given tag. 3337 * 3338 * @see MulticastLock 3339 */ createMulticastLock(String tag)3340 public MulticastLock createMulticastLock(String tag) { 3341 return new MulticastLock(tag); 3342 } 3343 3344 /** 3345 * Allows an application to receive Wifi Multicast packets. 3346 * Normally the Wifi stack filters out packets not explicitly 3347 * addressed to this device. Acquring a MulticastLock will 3348 * cause the stack to receive packets addressed to multicast 3349 * addresses. Processing these extra packets can cause a noticeable 3350 * battery drain and should be disabled when not needed. 3351 */ 3352 public class MulticastLock { 3353 private String mTag; 3354 private final IBinder mBinder; 3355 private int mRefCount; 3356 private boolean mRefCounted; 3357 private boolean mHeld; 3358 MulticastLock(String tag)3359 private MulticastLock(String tag) { 3360 mTag = tag; 3361 mBinder = new Binder(); 3362 mRefCount = 0; 3363 mRefCounted = true; 3364 mHeld = false; 3365 } 3366 3367 /** 3368 * Locks Wifi Multicast on until {@link #release} is called. 3369 * 3370 * If this MulticastLock is reference-counted each call to 3371 * {@code acquire} will increment the reference count, and the 3372 * wifi interface will receive multicast packets as long as the 3373 * reference count is above zero. 3374 * 3375 * If this MulticastLock is not reference-counted, the first call to 3376 * {@code acquire} will turn on the multicast packets, but subsequent 3377 * calls will be ignored. Only one call to {@link #release} will 3378 * be required, regardless of the number of times that {@code acquire} 3379 * is called. 3380 * 3381 * Note that other applications may also lock Wifi Multicast on. 3382 * Only they can relinquish their lock. 3383 * 3384 * Also note that applications cannot leave Multicast locked on. 3385 * When an app exits or crashes, any Multicast locks will be released. 3386 */ acquire()3387 public void acquire() { 3388 synchronized (mBinder) { 3389 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 3390 try { 3391 mService.acquireMulticastLock(mBinder, mTag); 3392 synchronized (WifiManager.this) { 3393 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 3394 mService.releaseMulticastLock(); 3395 throw new UnsupportedOperationException( 3396 "Exceeded maximum number of wifi locks"); 3397 } 3398 mActiveLockCount++; 3399 } 3400 } catch (RemoteException e) { 3401 throw e.rethrowFromSystemServer(); 3402 } 3403 mHeld = true; 3404 } 3405 } 3406 } 3407 3408 /** 3409 * Unlocks Wifi Multicast, restoring the filter of packets 3410 * not addressed specifically to this device and saving power. 3411 * 3412 * If this MulticastLock is reference-counted, each call to 3413 * {@code release} will decrement the reference count, and the 3414 * multicast packets will only stop being received when the reference 3415 * count reaches zero. If the reference count goes below zero (that 3416 * is, if {@code release} is called a greater number of times than 3417 * {@link #acquire}), an exception is thrown. 3418 * 3419 * If this MulticastLock is not reference-counted, the first call to 3420 * {@code release} (after the radio was multicast locked using 3421 * {@link #acquire}) will unlock the multicast, and subsequent calls 3422 * will be ignored. 3423 * 3424 * Note that if any other Wifi Multicast Locks are still outstanding 3425 * this {@code release} call will not have an immediate effect. Only 3426 * when all applications have released all their Multicast Locks will 3427 * the Multicast filter be turned back on. 3428 * 3429 * Also note that when an app exits or crashes all of its Multicast 3430 * Locks will be automatically released. 3431 */ release()3432 public void release() { 3433 synchronized (mBinder) { 3434 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 3435 try { 3436 mService.releaseMulticastLock(); 3437 synchronized (WifiManager.this) { 3438 mActiveLockCount--; 3439 } 3440 } catch (RemoteException e) { 3441 throw e.rethrowFromSystemServer(); 3442 } 3443 mHeld = false; 3444 } 3445 if (mRefCount < 0) { 3446 throw new RuntimeException("MulticastLock under-locked " 3447 + mTag); 3448 } 3449 } 3450 } 3451 3452 /** 3453 * Controls whether this is a reference-counted or non-reference- 3454 * counted MulticastLock. 3455 * 3456 * Reference-counted MulticastLocks keep track of the number of calls 3457 * to {@link #acquire} and {@link #release}, and only stop the 3458 * reception of multicast packets when every call to {@link #acquire} 3459 * has been balanced with a call to {@link #release}. Non-reference- 3460 * counted MulticastLocks allow the reception of multicast packets 3461 * whenever {@link #acquire} is called and stop accepting multicast 3462 * packets whenever {@link #release} is called. 3463 * 3464 * @param refCounted true if this MulticastLock should keep a reference 3465 * count 3466 */ setReferenceCounted(boolean refCounted)3467 public void setReferenceCounted(boolean refCounted) { 3468 mRefCounted = refCounted; 3469 } 3470 3471 /** 3472 * Checks whether this MulticastLock is currently held. 3473 * 3474 * @return true if this MulticastLock is held, false otherwise 3475 */ isHeld()3476 public boolean isHeld() { 3477 synchronized (mBinder) { 3478 return mHeld; 3479 } 3480 } 3481 toString()3482 public String toString() { 3483 String s1, s2, s3; 3484 synchronized (mBinder) { 3485 s1 = Integer.toHexString(System.identityHashCode(this)); 3486 s2 = mHeld ? "held; " : ""; 3487 if (mRefCounted) { 3488 s3 = "refcounted: refcount = " + mRefCount; 3489 } else { 3490 s3 = "not refcounted"; 3491 } 3492 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 3493 } 3494 } 3495 3496 @Override finalize()3497 protected void finalize() throws Throwable { 3498 super.finalize(); 3499 setReferenceCounted(false); 3500 release(); 3501 } 3502 } 3503 3504 /** 3505 * Check multicast filter status. 3506 * 3507 * @return true if multicast packets are allowed. 3508 * 3509 * @hide pending API council approval 3510 */ isMulticastEnabled()3511 public boolean isMulticastEnabled() { 3512 try { 3513 return mService.isMulticastEnabled(); 3514 } catch (RemoteException e) { 3515 throw e.rethrowFromSystemServer(); 3516 } 3517 } 3518 3519 /** 3520 * Initialize the multicast filtering to 'on' 3521 * @hide no intent to publish 3522 */ initializeMulticastFiltering()3523 public boolean initializeMulticastFiltering() { 3524 try { 3525 mService.initializeMulticastFiltering(); 3526 return true; 3527 } catch (RemoteException e) { 3528 throw e.rethrowFromSystemServer(); 3529 } 3530 } 3531 finalize()3532 protected void finalize() throws Throwable { 3533 try { 3534 if (mAsyncChannel != null) { 3535 mAsyncChannel.disconnect(); 3536 } 3537 } finally { 3538 super.finalize(); 3539 } 3540 } 3541 3542 /** 3543 * Set wifi verbose log. Called from developer settings. 3544 * @hide 3545 */ 3546 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) enableVerboseLogging(int verbose)3547 public void enableVerboseLogging (int verbose) { 3548 try { 3549 mService.enableVerboseLogging(verbose); 3550 } catch (Exception e) { 3551 //ignore any failure here 3552 Log.e(TAG, "enableVerboseLogging " + e.toString()); 3553 } 3554 } 3555 3556 /** 3557 * Get the WiFi verbose logging level.This is used by settings 3558 * to decide what to show within the picker. 3559 * @hide 3560 */ getVerboseLoggingLevel()3561 public int getVerboseLoggingLevel() { 3562 try { 3563 return mService.getVerboseLoggingLevel(); 3564 } catch (RemoteException e) { 3565 throw e.rethrowFromSystemServer(); 3566 } 3567 } 3568 3569 /** 3570 * Removes all saved wifi networks. 3571 * 3572 * @hide 3573 */ factoryReset()3574 public void factoryReset() { 3575 try { 3576 mService.factoryReset(mContext.getOpPackageName()); 3577 } catch (RemoteException e) { 3578 throw e.rethrowFromSystemServer(); 3579 } 3580 } 3581 3582 /** 3583 * Get Network object of current wifi network 3584 * @return Get Network object of current wifi network 3585 * @hide 3586 */ getCurrentNetwork()3587 public Network getCurrentNetwork() { 3588 try { 3589 return mService.getCurrentNetwork(); 3590 } catch (RemoteException e) { 3591 throw e.rethrowFromSystemServer(); 3592 } 3593 } 3594 3595 /** 3596 * Deprecated 3597 * returns false 3598 * @hide 3599 * @deprecated 3600 */ setEnableAutoJoinWhenAssociated(boolean enabled)3601 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 3602 return false; 3603 } 3604 3605 /** 3606 * Deprecated 3607 * returns false 3608 * @hide 3609 * @deprecated 3610 */ getEnableAutoJoinWhenAssociated()3611 public boolean getEnableAutoJoinWhenAssociated() { 3612 return false; 3613 } 3614 3615 /** 3616 * Enable/disable WifiConnectivityManager 3617 * @hide 3618 */ enableWifiConnectivityManager(boolean enabled)3619 public void enableWifiConnectivityManager(boolean enabled) { 3620 try { 3621 mService.enableWifiConnectivityManager(enabled); 3622 } catch (RemoteException e) { 3623 throw e.rethrowFromSystemServer(); 3624 } 3625 } 3626 3627 /** 3628 * Retrieve the data to be backed to save the current state. 3629 * @hide 3630 */ retrieveBackupData()3631 public byte[] retrieveBackupData() { 3632 try { 3633 return mService.retrieveBackupData(); 3634 } catch (RemoteException e) { 3635 throw e.rethrowFromSystemServer(); 3636 } 3637 } 3638 3639 /** 3640 * Restore state from the backed up data. 3641 * @hide 3642 */ restoreBackupData(byte[] data)3643 public void restoreBackupData(byte[] data) { 3644 try { 3645 mService.restoreBackupData(data); 3646 } catch (RemoteException e) { 3647 throw e.rethrowFromSystemServer(); 3648 } 3649 } 3650 3651 /** 3652 * Restore state from the older version of back up data. 3653 * The old backup data was essentially a backup of wpa_supplicant.conf 3654 * and ipconfig.txt file. 3655 * @deprecated this is no longer supported. 3656 * @hide 3657 */ 3658 @Deprecated restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData)3659 public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { 3660 try { 3661 mService.restoreSupplicantBackupData(supplicantData, ipConfigData); 3662 } catch (RemoteException e) { 3663 throw e.rethrowFromSystemServer(); 3664 } 3665 } 3666 3667 /** 3668 * Start subscription provisioning flow 3669 * @param provider {@link OsuProvider} to provision with 3670 * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow 3671 * @hide 3672 */ startSubscriptionProvisioning(OsuProvider provider, ProvisioningCallback callback, @Nullable Handler handler)3673 public void startSubscriptionProvisioning(OsuProvider provider, ProvisioningCallback callback, 3674 @Nullable Handler handler) { 3675 Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper(); 3676 try { 3677 mService.startSubscriptionProvisioning(provider, 3678 new ProvisioningCallbackProxy(looper, callback)); 3679 } catch (RemoteException e) { 3680 throw e.rethrowFromSystemServer(); 3681 } 3682 } 3683 3684 private static class ProvisioningCallbackProxy extends IProvisioningCallback.Stub { 3685 private final Handler mHandler; 3686 private final ProvisioningCallback mCallback; 3687 ProvisioningCallbackProxy(Looper looper, ProvisioningCallback callback)3688 ProvisioningCallbackProxy(Looper looper, ProvisioningCallback callback) { 3689 mHandler = new Handler(looper); 3690 mCallback = callback; 3691 } 3692 3693 @Override onProvisioningStatus(int status)3694 public void onProvisioningStatus(int status) { 3695 mHandler.post(() -> { 3696 mCallback.onProvisioningStatus(status); 3697 }); 3698 } 3699 3700 @Override onProvisioningFailure(int status)3701 public void onProvisioningFailure(int status) { 3702 mHandler.post(() -> { 3703 mCallback.onProvisioningFailure(status); 3704 }); 3705 } 3706 } 3707 } 3708