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