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 static android.Manifest.permission.ACCESS_FINE_LOCATION; 20 import static android.Manifest.permission.ACCESS_WIFI_STATE; 21 import static android.Manifest.permission.READ_WIFI_CREDENTIAL; 22 23 import android.annotation.CallbackExecutor; 24 import android.annotation.IntDef; 25 import android.annotation.IntRange; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.RequiresPermission; 29 import android.annotation.SdkConstant; 30 import android.annotation.SdkConstant.SdkConstantType; 31 import android.annotation.SuppressLint; 32 import android.annotation.SystemApi; 33 import android.annotation.SystemService; 34 import android.app.ActivityManager; 35 import android.compat.annotation.UnsupportedAppUsage; 36 import android.content.Context; 37 import android.net.ConnectivityManager; 38 import android.net.ConnectivityManager.NetworkCallback; 39 import android.net.DhcpInfo; 40 import android.net.LinkProperties; 41 import android.net.MacAddress; 42 import android.net.Network; 43 import android.net.NetworkCapabilities; 44 import android.net.NetworkStack; 45 import android.net.Uri; 46 import android.net.wifi.hotspot2.IProvisioningCallback; 47 import android.net.wifi.hotspot2.OsuProvider; 48 import android.net.wifi.hotspot2.PasspointConfiguration; 49 import android.net.wifi.hotspot2.ProvisioningCallback; 50 import android.os.Binder; 51 import android.os.Build; 52 import android.os.Handler; 53 import android.os.HandlerExecutor; 54 import android.os.IBinder; 55 import android.os.Looper; 56 import android.os.Parcel; 57 import android.os.Parcelable; 58 import android.os.RemoteException; 59 import android.os.WorkSource; 60 import android.os.connectivity.WifiActivityEnergyInfo; 61 import android.telephony.SubscriptionInfo; 62 import android.telephony.TelephonyManager; 63 import android.text.TextUtils; 64 import android.util.CloseGuard; 65 import android.util.Log; 66 import android.util.Pair; 67 import android.util.SparseArray; 68 69 import androidx.annotation.RequiresApi; 70 71 import com.android.internal.annotations.GuardedBy; 72 import com.android.internal.annotations.VisibleForTesting; 73 import com.android.modules.utils.ParceledListSlice; 74 import com.android.modules.utils.build.SdkLevel; 75 76 import java.lang.annotation.Retention; 77 import java.lang.annotation.RetentionPolicy; 78 import java.lang.ref.Reference; 79 import java.lang.ref.WeakReference; 80 import java.net.InetAddress; 81 import java.util.ArrayList; 82 import java.util.Collections; 83 import java.util.HashMap; 84 import java.util.List; 85 import java.util.Map; 86 import java.util.Objects; 87 import java.util.Set; 88 import java.util.StringTokenizer; 89 import java.util.concurrent.Executor; 90 91 /** 92 * This class provides the primary API for managing all aspects of Wi-Fi 93 * connectivity. 94 * <p> 95 * On releases before {@link android.os.Build.VERSION_CODES#N}, this object 96 * should only be obtained from an {@linkplain Context#getApplicationContext() 97 * application context}, and not from any other derived context to avoid memory 98 * leaks within the calling process. 99 * <p> 100 * It deals with several categories of items: 101 * </p> 102 * <ul> 103 * <li>The list of configured networks. The list can be viewed and updated, and 104 * attributes of individual entries can be modified.</li> 105 * <li>The currently active Wi-Fi network, if any. Connectivity can be 106 * established or torn down, and dynamic information about the state of the 107 * network can be queried.</li> 108 * <li>Results of access point scans, containing enough information to make 109 * decisions about what access point to connect to.</li> 110 * <li>It defines the names of various Intent actions that are broadcast upon 111 * any sort of change in Wi-Fi state. 112 * </ul> 113 * <p> 114 * This is the API to use when performing Wi-Fi specific operations. To perform 115 * operations that pertain to network connectivity at an abstract level, use 116 * {@link android.net.ConnectivityManager}. 117 * </p> 118 */ 119 @SystemService(Context.WIFI_SERVICE) 120 public class WifiManager { 121 122 private static final String TAG = "WifiManager"; 123 // Supplicant error codes: 124 /** 125 * The error code if there was a problem authenticating. 126 * @deprecated This is no longer supported. 127 */ 128 @Deprecated 129 public static final int ERROR_AUTHENTICATING = 1; 130 131 /** 132 * The reason code if there is no error during authentication. 133 * It could also imply that there no authentication in progress, 134 * this reason code also serves as a reset value. 135 * @deprecated This is no longer supported. 136 * @hide 137 */ 138 @Deprecated 139 public static final int ERROR_AUTH_FAILURE_NONE = 0; 140 141 /** 142 * The reason code if there was a timeout authenticating. 143 * @deprecated This is no longer supported. 144 * @hide 145 */ 146 @Deprecated 147 public static final int ERROR_AUTH_FAILURE_TIMEOUT = 1; 148 149 /** 150 * The reason code if there was a wrong password while 151 * authenticating. 152 * @deprecated This is no longer supported. 153 * @hide 154 */ 155 @Deprecated 156 public static final int ERROR_AUTH_FAILURE_WRONG_PSWD = 2; 157 158 /** 159 * The reason code if there was EAP failure while 160 * authenticating. 161 * @deprecated This is no longer supported. 162 * @hide 163 */ 164 @Deprecated 165 public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3; 166 167 /** @hide */ 168 public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM = 256; 169 170 /** @hide */ 171 public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM = 1024; 172 173 /** 174 * Reason code if all of the network suggestions were successfully added or removed. 175 */ 176 public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; 177 178 /** 179 * Reason code if there was an internal error in the platform while processing the addition or 180 * removal of suggestions. 181 */ 182 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1; 183 184 /** 185 * Reason code if the user has disallowed "android:change_wifi_state" app-ops from the app. 186 * @see android.app.AppOpsManager#unsafeCheckOp(String, int, String). 187 */ 188 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED = 2; 189 190 /** 191 * Reason code if one or more of the network suggestions added already exists in platform's 192 * database. 193 * Note: this code will not be returned with Android 11 as in-place modification is allowed, 194 * please check {@link #addNetworkSuggestions(List)}. 195 * @see WifiNetworkSuggestion#equals(Object) 196 */ 197 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 3; 198 199 /** 200 * Reason code if the number of network suggestions provided by the app crosses the max 201 * threshold set per app. 202 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} if 203 * the total size exceeds the limit. 204 * @see #getMaxNumberOfNetworkSuggestionsPerApp() 205 */ 206 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 4; 207 208 /** 209 * Reason code if one or more of the network suggestions removed does not exist in platform's 210 * database. 211 * The framework won't remove any suggestions if one or more of suggestions provided 212 * by {@link #removeNetworkSuggestions(List)} does not exist in database. 213 * @see WifiNetworkSuggestion#equals(Object) 214 */ 215 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5; 216 217 /** 218 * Reason code if one or more of the network suggestions added is not allowed. 219 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} 220 * if one or more of them is not allowed. 221 * This error may be caused by suggestion is using SIM-based encryption method, but calling app 222 * is not carrier privileged. 223 */ 224 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED = 6; 225 226 /** 227 * Reason code if one or more of the network suggestions added is invalid. Framework will reject 228 * all the suggestions in the list. 229 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} 230 * if one or more of them is invalid. 231 * Please use {@link WifiNetworkSuggestion.Builder} to create network suggestions. 232 */ 233 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID = 7; 234 235 /** @hide */ 236 @IntDef(prefix = { "STATUS_NETWORK_SUGGESTIONS_" }, value = { 237 STATUS_NETWORK_SUGGESTIONS_SUCCESS, 238 STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, 239 STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED, 240 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE, 241 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP, 242 STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, 243 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED, 244 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, 245 }) 246 @Retention(RetentionPolicy.SOURCE) 247 public @interface NetworkSuggestionsStatusCode {} 248 249 /** 250 * Reason code if suggested network connection attempt failed with an unknown failure. 251 */ 252 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN = 0; 253 /** 254 * Reason code if suggested network connection attempt failed with association failure. 255 */ 256 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION = 1; 257 /** 258 * Reason code if suggested network connection attempt failed with an authentication failure. 259 */ 260 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION = 2; 261 /** 262 * Reason code if suggested network connection attempt failed with an IP provision failure. 263 */ 264 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING = 3; 265 266 /** @hide */ 267 @IntDef(prefix = {"STATUS_SUGGESTION_CONNECTION_FAILURE_"}, 268 value = {STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN, 269 STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION, 270 STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION, 271 STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING 272 }) 273 @Retention(RetentionPolicy.SOURCE) 274 public @interface SuggestionConnectionStatusCode {} 275 276 /** 277 * Status code if suggestion approval status is unknown, an App which hasn't made any 278 * suggestions will get this code. 279 */ 280 public static final int STATUS_SUGGESTION_APPROVAL_UNKNOWN = 0; 281 282 /** 283 * Status code if the calling app is still pending user approval for suggestions. 284 */ 285 public static final int STATUS_SUGGESTION_APPROVAL_PENDING = 1; 286 287 /** 288 * Status code if the calling app got the user approval for suggestions. 289 */ 290 public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER = 2; 291 292 /** 293 * Status code if the calling app suggestions were rejected by the user. 294 */ 295 public static final int STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER = 3; 296 297 /** 298 * Status code if the calling app was approved by virtue of being a carrier privileged app. 299 * @see TelephonyManager#hasCarrierPrivileges(). 300 */ 301 public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE = 4; 302 303 /** @hide */ 304 @IntDef(prefix = {"STATUS_SUGGESTION_APPROVAL_"}, 305 value = {STATUS_SUGGESTION_APPROVAL_UNKNOWN, 306 STATUS_SUGGESTION_APPROVAL_PENDING, 307 STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER, 308 STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER, 309 STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE 310 }) 311 @Retention(RetentionPolicy.SOURCE) 312 public @interface SuggestionUserApprovalStatus {} 313 314 /** 315 * Broadcast intent action indicating whether Wi-Fi scanning is currently available. 316 * Available extras: 317 * - {@link #EXTRA_SCAN_AVAILABLE} 318 */ 319 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 320 public static final String ACTION_WIFI_SCAN_AVAILABILITY_CHANGED = 321 "android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED"; 322 323 /** 324 * A boolean extra indicating whether scanning is currently available. 325 * Sent in the broadcast {@link #ACTION_WIFI_SCAN_AVAILABILITY_CHANGED}. 326 * Its value is true if scanning is currently available, false otherwise. 327 */ 328 public static final String EXTRA_SCAN_AVAILABLE = "android.net.wifi.extra.SCAN_AVAILABLE"; 329 330 /** 331 * Broadcast intent action indicating that the credential of a Wi-Fi network 332 * has been changed. One extra provides the ssid of the network. Another 333 * extra provides the event type, whether the credential is saved or forgot. 334 * @hide 335 */ 336 @SystemApi 337 public static final String WIFI_CREDENTIAL_CHANGED_ACTION = 338 "android.net.wifi.WIFI_CREDENTIAL_CHANGED"; 339 /** @hide */ 340 @SystemApi 341 public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et"; 342 /** @hide */ 343 @SystemApi 344 public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid"; 345 /** @hide */ 346 @SystemApi 347 public static final int WIFI_CREDENTIAL_SAVED = 0; 348 /** @hide */ 349 @SystemApi 350 public static final int WIFI_CREDENTIAL_FORGOT = 1; 351 352 /** @hide */ 353 @SystemApi 354 public static final int PASSPOINT_HOME_NETWORK = 0; 355 356 /** @hide */ 357 @SystemApi 358 public static final int PASSPOINT_ROAMING_NETWORK = 1; 359 360 /** 361 * Broadcast intent action indicating that a Passpoint provider icon has been received. 362 * 363 * Included extras: 364 * {@link #EXTRA_BSSID_LONG} 365 * {@link #EXTRA_FILENAME} 366 * {@link #EXTRA_ICON} 367 * 368 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 369 * 370 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 371 * components will be launched. 372 * 373 * @hide 374 */ 375 public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; 376 /** 377 * BSSID of an AP in long representation. The {@link #EXTRA_BSSID} contains BSSID in 378 * String representation. 379 * 380 * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}. 381 * 382 * @hide 383 */ 384 public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; 385 /** 386 * Icon data. 387 * 388 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into 389 * {@link android.graphics.drawable.Icon}. 390 * 391 * @hide 392 */ 393 public static final String EXTRA_ICON = "android.net.wifi.extra.ICON"; 394 /** 395 * Name of a file. 396 * 397 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 398 * 399 * @hide 400 */ 401 public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; 402 403 /** 404 * Broadcast intent action indicating a Passpoint OSU Providers List element has been received. 405 * 406 * Included extras: 407 * {@link #EXTRA_BSSID_LONG} 408 * {@link #EXTRA_ANQP_ELEMENT_DATA} 409 * 410 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 411 * 412 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 413 * components will be launched. 414 * 415 * @hide 416 */ 417 public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = 418 "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; 419 /** 420 * Raw binary data of an ANQP (Access Network Query Protocol) element. 421 * 422 * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}. 423 * 424 * @hide 425 */ 426 public static final String EXTRA_ANQP_ELEMENT_DATA = 427 "android.net.wifi.extra.ANQP_ELEMENT_DATA"; 428 429 /** 430 * Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received. 431 * 432 * Included extras: 433 * {@link #EXTRA_BSSID_LONG} 434 * {@link #EXTRA_ESS} 435 * {@link #EXTRA_DELAY} 436 * {@link #EXTRA_URL} 437 * 438 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 439 * 440 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 441 * components will be launched. 442 * 443 * @hide 444 */ 445 public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT = 446 "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; 447 /** 448 * Flag indicating BSS (Basic Service Set) or ESS (Extended Service Set). This will be set to 449 * {@code true} for ESS. 450 * 451 * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}. 452 * 453 * @hide 454 */ 455 public static final String EXTRA_ESS = "android.net.wifi.extra.ESS"; 456 /** 457 * Delay in seconds. 458 * 459 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 460 * 461 * @hide 462 */ 463 public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; 464 465 /** 466 * Broadcast intent action indicating a Passpoint subscription remediation frame has been 467 * received. 468 * 469 * Included extras: 470 * {@link #EXTRA_BSSID_LONG} 471 * {@link #EXTRA_SUBSCRIPTION_REMEDIATION_METHOD} 472 * {@link #EXTRA_URL} 473 * 474 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 475 * 476 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 477 * components will be launched. 478 * 479 * @hide 480 */ 481 public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = 482 "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; 483 /** 484 * The protocol supported by the subscription remediation server. The possible values are: 485 * 0 - OMA DM 486 * 1 - SOAP XML SPP 487 * 488 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 489 * 490 * @hide 491 */ 492 public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = 493 "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; 494 495 /** 496 * Activity Action: Receiver should launch Passpoint OSU (Online Sign Up) view. 497 * Included extras: 498 * 499 * {@link #EXTRA_OSU_NETWORK}: {@link Network} instance associated with OSU AP. 500 * {@link #EXTRA_URL}: String representation of a server URL used for OSU process. 501 * 502 * @hide 503 */ 504 @SystemApi 505 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 506 public static final String ACTION_PASSPOINT_LAUNCH_OSU_VIEW = 507 "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW"; 508 509 /** 510 * The lookup key for a {@link android.net.Network} associated with a Passpoint OSU server. 511 * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast. 512 * 513 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 514 * 515 * @hide 516 */ 517 @SystemApi 518 public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK"; 519 520 /** 521 * String representation of an URL for Passpoint OSU. 522 * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast. 523 * 524 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 525 * 526 * @hide 527 */ 528 @SystemApi 529 public static final String EXTRA_URL = "android.net.wifi.extra.URL"; 530 531 /** 532 * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, 533 * enabling, disabling, or unknown. One extra provides this state as an int. 534 * Another extra provides the previous state, if available. No network-related 535 * permissions are required to subscribe to this broadcast. 536 * 537 * <p class="note">This broadcast is not delivered to manifest receivers in 538 * applications that target API version 26 or later. 539 * 540 * @see #EXTRA_WIFI_STATE 541 * @see #EXTRA_PREVIOUS_WIFI_STATE 542 */ 543 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 544 public static final String WIFI_STATE_CHANGED_ACTION = 545 "android.net.wifi.WIFI_STATE_CHANGED"; 546 /** 547 * The lookup key for an int that indicates whether Wi-Fi is enabled, 548 * disabled, enabling, disabling, or unknown. Retrieve it with 549 * {@link android.content.Intent#getIntExtra(String,int)}. 550 * 551 * @see #WIFI_STATE_DISABLED 552 * @see #WIFI_STATE_DISABLING 553 * @see #WIFI_STATE_ENABLED 554 * @see #WIFI_STATE_ENABLING 555 * @see #WIFI_STATE_UNKNOWN 556 */ 557 public static final String EXTRA_WIFI_STATE = "wifi_state"; 558 /** 559 * The previous Wi-Fi state. 560 * 561 * @see #EXTRA_WIFI_STATE 562 */ 563 public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; 564 565 /** 566 * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if 567 * it finishes successfully. 568 * 569 * @see #WIFI_STATE_CHANGED_ACTION 570 * @see #getWifiState() 571 */ 572 public static final int WIFI_STATE_DISABLING = 0; 573 /** 574 * Wi-Fi is disabled. 575 * 576 * @see #WIFI_STATE_CHANGED_ACTION 577 * @see #getWifiState() 578 */ 579 public static final int WIFI_STATE_DISABLED = 1; 580 /** 581 * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if 582 * it finishes successfully. 583 * 584 * @see #WIFI_STATE_CHANGED_ACTION 585 * @see #getWifiState() 586 */ 587 public static final int WIFI_STATE_ENABLING = 2; 588 /** 589 * Wi-Fi is enabled. 590 * 591 * @see #WIFI_STATE_CHANGED_ACTION 592 * @see #getWifiState() 593 */ 594 public static final int WIFI_STATE_ENABLED = 3; 595 /** 596 * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling 597 * or disabling. 598 * 599 * @see #WIFI_STATE_CHANGED_ACTION 600 * @see #getWifiState() 601 */ 602 public static final int WIFI_STATE_UNKNOWN = 4; 603 604 /** 605 * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled, 606 * enabling, disabling, or failed. 607 * 608 * @hide 609 */ 610 @SystemApi 611 public static final String WIFI_AP_STATE_CHANGED_ACTION = 612 "android.net.wifi.WIFI_AP_STATE_CHANGED"; 613 614 /** 615 * The lookup key for an int that indicates whether Wi-Fi AP is enabled, 616 * disabled, enabling, disabling, or failed. Retrieve it with 617 * {@link android.content.Intent#getIntExtra(String,int)}. 618 * 619 * @see #WIFI_AP_STATE_DISABLED 620 * @see #WIFI_AP_STATE_DISABLING 621 * @see #WIFI_AP_STATE_ENABLED 622 * @see #WIFI_AP_STATE_ENABLING 623 * @see #WIFI_AP_STATE_FAILED 624 * 625 * @hide 626 */ 627 @SystemApi 628 public static final String EXTRA_WIFI_AP_STATE = "wifi_state"; 629 630 /** 631 * An extra containing the int error code for Soft AP start failure. 632 * Can be obtained from the {@link #WIFI_AP_STATE_CHANGED_ACTION} using 633 * {@link android.content.Intent#getIntExtra}. 634 * This extra will only be attached if {@link #EXTRA_WIFI_AP_STATE} is 635 * attached and is equal to {@link #WIFI_AP_STATE_FAILED}. 636 * 637 * The error code will be one of: 638 * {@link #SAP_START_FAILURE_GENERAL}, 639 * {@link #SAP_START_FAILURE_NO_CHANNEL}, 640 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION} 641 * 642 * @hide 643 */ 644 @SystemApi 645 public static final String EXTRA_WIFI_AP_FAILURE_REASON = 646 "android.net.wifi.extra.WIFI_AP_FAILURE_REASON"; 647 /** 648 * The previous Wi-Fi state. 649 * 650 * @see #EXTRA_WIFI_AP_STATE 651 * 652 * @hide 653 */ 654 @SystemApi 655 public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; 656 /** 657 * The lookup key for a String extra that stores the interface name used for the Soft AP. 658 * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. 659 * Retrieve its value with {@link android.content.Intent#getStringExtra(String)}. 660 * 661 * @hide 662 */ 663 @SystemApi 664 public static final String EXTRA_WIFI_AP_INTERFACE_NAME = 665 "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME"; 666 /** 667 * The lookup key for an int extra that stores the intended IP mode for this Soft AP. 668 * One of {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}. 669 * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. 670 * Retrieve its value with {@link android.content.Intent#getIntExtra(String, int)}. 671 * 672 * @hide 673 */ 674 @SystemApi 675 public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE"; 676 677 /** @hide */ 678 @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = { 679 WIFI_AP_STATE_DISABLING, 680 WIFI_AP_STATE_DISABLED, 681 WIFI_AP_STATE_ENABLING, 682 WIFI_AP_STATE_ENABLED, 683 WIFI_AP_STATE_FAILED, 684 }) 685 @Retention(RetentionPolicy.SOURCE) 686 public @interface WifiApState {} 687 688 /** 689 * Wi-Fi AP is currently being disabled. The state will change to 690 * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully. 691 * 692 * @see #WIFI_AP_STATE_CHANGED_ACTION 693 * @see #getWifiApState() 694 * 695 * @hide 696 */ 697 @SystemApi 698 public static final int WIFI_AP_STATE_DISABLING = 10; 699 /** 700 * Wi-Fi AP is disabled. 701 * 702 * @see #WIFI_AP_STATE_CHANGED_ACTION 703 * @see #getWifiState() 704 * 705 * @hide 706 */ 707 @SystemApi 708 public static final int WIFI_AP_STATE_DISABLED = 11; 709 /** 710 * Wi-Fi AP is currently being enabled. The state will change to 711 * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully. 712 * 713 * @see #WIFI_AP_STATE_CHANGED_ACTION 714 * @see #getWifiApState() 715 * 716 * @hide 717 */ 718 @SystemApi 719 public static final int WIFI_AP_STATE_ENABLING = 12; 720 /** 721 * Wi-Fi AP is enabled. 722 * 723 * @see #WIFI_AP_STATE_CHANGED_ACTION 724 * @see #getWifiApState() 725 * 726 * @hide 727 */ 728 @SystemApi 729 public static final int WIFI_AP_STATE_ENABLED = 13; 730 /** 731 * Wi-Fi AP is in a failed state. This state will occur when an error occurs during 732 * enabling or disabling 733 * 734 * @see #WIFI_AP_STATE_CHANGED_ACTION 735 * @see #getWifiApState() 736 * 737 * @hide 738 */ 739 @SystemApi 740 public static final int WIFI_AP_STATE_FAILED = 14; 741 742 /** @hide */ 743 @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = { 744 SAP_START_FAILURE_GENERAL, 745 SAP_START_FAILURE_NO_CHANNEL, 746 SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION, 747 }) 748 @Retention(RetentionPolicy.SOURCE) 749 public @interface SapStartFailure {} 750 751 /** 752 * All other reasons for AP start failure besides {@link #SAP_START_FAILURE_NO_CHANNEL} and 753 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}. 754 * 755 * @hide 756 */ 757 @SystemApi 758 public static final int SAP_START_FAILURE_GENERAL= 0; 759 760 /** 761 * If Wi-Fi AP start failed, this reason code means that no legal channel exists on user 762 * selected band due to regulatory constraints. 763 * 764 * @hide 765 */ 766 @SystemApi 767 public static final int SAP_START_FAILURE_NO_CHANNEL = 1; 768 769 /** 770 * If Wi-Fi AP start failed, this reason code means that the specified configuration 771 * is not supported by the current HAL version. 772 * 773 * @hide 774 */ 775 @SystemApi 776 public static final int SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION = 2; 777 778 779 /** @hide */ 780 @IntDef(flag = false, prefix = { "SAP_CLIENT_BLOCKED_REASON_" }, value = { 781 SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER, 782 SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS, 783 }) 784 @Retention(RetentionPolicy.SOURCE) 785 public @interface SapClientBlockedReason {} 786 787 /** 788 * If Soft Ap client is blocked, this reason code means that client doesn't exist in the 789 * specified configuration {@link SoftApConfiguration.Builder#setBlockedClientList(List)} 790 * and {@link SoftApConfiguration.Builder#setAllowedClientList(List)} 791 * and the {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)} 792 * is configured as well. 793 * @hide 794 */ 795 @SystemApi 796 public static final int SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER = 0; 797 798 /** 799 * If Soft Ap client is blocked, this reason code means that no more clients can be 800 * associated to this AP since it reached maximum capacity. The maximum capacity is 801 * the minimum of {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} and 802 * {@link SoftApCapability#getMaxSupportedClients} which get from 803 * {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)}. 804 * 805 * @hide 806 */ 807 @SystemApi 808 public static final int SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS = 1; 809 810 /** 811 * Client disconnected for unspecified reason. This could for example be because the AP is being 812 * shut down. 813 * @hide 814 */ 815 public static final int SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED = 2; 816 817 /** @hide */ 818 @Retention(RetentionPolicy.SOURCE) 819 @IntDef(prefix = {"IFACE_IP_MODE_"}, value = { 820 IFACE_IP_MODE_UNSPECIFIED, 821 IFACE_IP_MODE_CONFIGURATION_ERROR, 822 IFACE_IP_MODE_TETHERED, 823 IFACE_IP_MODE_LOCAL_ONLY}) 824 public @interface IfaceIpMode {} 825 826 /** 827 * Interface IP mode unspecified. 828 * 829 * @see #updateInterfaceIpState(String, int) 830 * 831 * @hide 832 */ 833 @SystemApi 834 public static final int IFACE_IP_MODE_UNSPECIFIED = -1; 835 836 /** 837 * Interface IP mode for configuration error. 838 * 839 * @see #updateInterfaceIpState(String, int) 840 * 841 * @hide 842 */ 843 @SystemApi 844 public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; 845 846 /** 847 * Interface IP mode for tethering. 848 * 849 * @see #updateInterfaceIpState(String, int) 850 * 851 * @hide 852 */ 853 @SystemApi 854 public static final int IFACE_IP_MODE_TETHERED = 1; 855 856 /** 857 * Interface IP mode for Local Only Hotspot. 858 * 859 * @see #updateInterfaceIpState(String, int) 860 * 861 * @hide 862 */ 863 @SystemApi 864 public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; 865 866 /** 867 * Broadcast intent action indicating that the wifi network settings 868 * had been reset. 869 * 870 * Note: This intent is sent as a directed broadcast to each manifest registered receiver. 871 * Intent will not be received by dynamically registered receivers. 872 * @hide 873 */ 874 @SystemApi 875 @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) 876 public static final String ACTION_NETWORK_SETTINGS_RESET = 877 "android.net.wifi.action.NETWORK_SETTINGS_RESET"; 878 879 /** 880 * Broadcast intent action indicating that the wifi network profiles provisioned 881 * may need refresh. 882 * 883 * Note: This intent is sent as a directed broadcast to each manifest registered receiver; 884 * And restricted to those apps which have the NETWORK_CARRIER_PROVISIONING permission. 885 * Intent will not be received by dynamically registered receivers. 886 * @hide 887 */ 888 @SystemApi 889 @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) 890 public static final String ACTION_REFRESH_USER_PROVISIONING = 891 "android.net.wifi.action.REFRESH_USER_PROVISIONING"; 892 893 /** 894 * Broadcast intent action indicating that a connection to the supplicant has 895 * been established (and it is now possible 896 * to perform Wi-Fi operations) or the connection to the supplicant has been 897 * lost. One extra provides the connection state as a boolean, where {@code true} 898 * means CONNECTED. 899 * @deprecated This is no longer supported. 900 * @see #EXTRA_SUPPLICANT_CONNECTED 901 */ 902 @Deprecated 903 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 904 public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = 905 "android.net.wifi.supplicant.CONNECTION_CHANGE"; 906 /** 907 * The lookup key for a boolean that indicates whether a connection to 908 * the supplicant daemon has been gained or lost. {@code true} means 909 * a connection now exists. 910 * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. 911 * @deprecated This is no longer supported. 912 */ 913 @Deprecated 914 public static final String EXTRA_SUPPLICANT_CONNECTED = "connected"; 915 /** 916 * Broadcast intent action indicating that the state of Wi-Fi connectivity 917 * has changed. An extra provides the new state 918 * in the form of a {@link android.net.NetworkInfo} object. No network-related 919 * permissions are required to subscribe to this broadcast. 920 * 921 * <p class="note">This broadcast is not delivered to manifest receivers in 922 * applications that target API version 26 or later. 923 * @see #EXTRA_NETWORK_INFO 924 */ 925 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 926 public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"; 927 /** 928 * The lookup key for a {@link android.net.NetworkInfo} object associated with the 929 * Wi-Fi network. Retrieve with 930 * {@link android.content.Intent#getParcelableExtra(String)}. 931 */ 932 public static final String EXTRA_NETWORK_INFO = "networkInfo"; 933 /** 934 * The lookup key for a String giving the BSSID of the access point to which 935 * we are connected. No longer used. 936 */ 937 @Deprecated 938 public static final String EXTRA_BSSID = "bssid"; 939 /** 940 * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the 941 * information about the access point to which we are connected. 942 * No longer used. 943 */ 944 @Deprecated 945 public static final String EXTRA_WIFI_INFO = "wifiInfo"; 946 /** 947 * Broadcast intent action indicating that the state of establishing a connection to 948 * an access point has changed.One extra provides the new 949 * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and 950 * is not generally the most useful thing to look at if you are just interested in 951 * the overall state of connectivity. 952 * @see #EXTRA_NEW_STATE 953 * @see #EXTRA_SUPPLICANT_ERROR 954 * @deprecated This is no longer supported. 955 */ 956 @Deprecated 957 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 958 public static final String SUPPLICANT_STATE_CHANGED_ACTION = 959 "android.net.wifi.supplicant.STATE_CHANGE"; 960 /** 961 * The lookup key for a {@link SupplicantState} describing the new state 962 * Retrieve with 963 * {@link android.content.Intent#getParcelableExtra(String)}. 964 * @deprecated This is no longer supported. 965 */ 966 @Deprecated 967 public static final String EXTRA_NEW_STATE = "newState"; 968 969 /** 970 * The lookup key for a {@link SupplicantState} describing the supplicant 971 * error code if any 972 * Retrieve with 973 * {@link android.content.Intent#getIntExtra(String, int)}. 974 * @see #ERROR_AUTHENTICATING 975 * @deprecated This is no longer supported. 976 */ 977 @Deprecated 978 public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; 979 980 /** 981 * The lookup key for a {@link SupplicantState} describing the supplicant 982 * error reason if any 983 * Retrieve with 984 * {@link android.content.Intent#getIntExtra(String, int)}. 985 * @see #ERROR_AUTH_FAILURE_#REASON_CODE 986 * @deprecated This is no longer supported. 987 * @hide 988 */ 989 @Deprecated 990 public static final String EXTRA_SUPPLICANT_ERROR_REASON = "supplicantErrorReason"; 991 992 /** 993 * Broadcast intent action indicating that the configured networks changed. 994 * This can be as a result of adding/updating/deleting a network. 995 * <br /> 996 * {@link #EXTRA_CHANGE_REASON} contains whether the configuration was added/changed/removed. 997 * {@link #EXTRA_WIFI_CONFIGURATION} is never set beginning in 998 * {@link android.os.Build.VERSION_CODES#R}. 999 * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set for backwards compatibility reasons, but 1000 * its value is always true beginning in {@link android.os.Build.VERSION_CODES#R}, even if only 1001 * a single network changed. 1002 * <br /> 1003 * The {@link android.Manifest.permission#ACCESS_WIFI_STATE ACCESS_WIFI_STATE} permission is 1004 * required to receive this broadcast. 1005 * 1006 * @hide 1007 */ 1008 @SystemApi 1009 public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = 1010 "android.net.wifi.CONFIGURED_NETWORKS_CHANGE"; 1011 /** 1012 * The lookup key for a {@link android.net.wifi.WifiConfiguration} object representing 1013 * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION} 1014 * broadcast is sent. 1015 * @deprecated This extra is never set beginning in {@link android.os.Build.VERSION_CODES#R}, 1016 * regardless of the target SDK version. Use {@link #getConfiguredNetworks} to get the full list 1017 * of configured networks. 1018 * @hide 1019 */ 1020 @Deprecated 1021 @SystemApi 1022 public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; 1023 /** 1024 * Multiple network configurations have changed. 1025 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 1026 * @deprecated This extra's value is always true beginning in 1027 * {@link android.os.Build.VERSION_CODES#R}, regardless of the target SDK version. 1028 * @hide 1029 */ 1030 @Deprecated 1031 @SystemApi 1032 public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges"; 1033 /** 1034 * The lookup key for an integer indicating the reason a Wi-Fi network configuration 1035 * has changed. One of {@link #CHANGE_REASON_ADDED}, {@link #CHANGE_REASON_REMOVED}, 1036 * {@link #CHANGE_REASON_CONFIG_CHANGE}. 1037 * 1038 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 1039 * @hide 1040 */ 1041 @SystemApi 1042 public static final String EXTRA_CHANGE_REASON = "changeReason"; 1043 /** 1044 * The configuration is new and was added. 1045 * @hide 1046 */ 1047 @SystemApi 1048 public static final int CHANGE_REASON_ADDED = 0; 1049 /** 1050 * The configuration was removed and is no longer present in the system's list of 1051 * configured networks. 1052 * @hide 1053 */ 1054 @SystemApi 1055 public static final int CHANGE_REASON_REMOVED = 1; 1056 /** 1057 * The configuration has changed as a result of explicit action or because the system 1058 * took an automated action such as disabling a malfunctioning configuration. 1059 * @hide 1060 */ 1061 @SystemApi 1062 public static final int CHANGE_REASON_CONFIG_CHANGE = 2; 1063 /** 1064 * An access point scan has completed, and results are available. 1065 * Call {@link #getScanResults()} to obtain the results. 1066 * The broadcast intent may contain an extra field with the key {@link #EXTRA_RESULTS_UPDATED} 1067 * and a {@code boolean} value indicating if the scan was successful. 1068 */ 1069 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1070 public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; 1071 1072 /** 1073 * Lookup key for a {@code boolean} extra in intent {@link #SCAN_RESULTS_AVAILABLE_ACTION} 1074 * representing if the scan was successful or not. 1075 * Scans may fail for multiple reasons, these may include: 1076 * <ol> 1077 * <li>An app requested too many scans in a certain period of time. 1078 * This may lead to additional scan request rejections via "scan throttling" for both 1079 * foreground and background apps. 1080 * Note: Apps holding android.Manifest.permission.NETWORK_SETTINGS permission are 1081 * exempted from scan throttling. 1082 * </li> 1083 * <li>The device is idle and scanning is disabled.</li> 1084 * <li>Wifi hardware reported a scan failure.</li> 1085 * </ol> 1086 * @return true scan was successful, results are updated 1087 * @return false scan was not successful, results haven't been updated since previous scan 1088 */ 1089 public static final String EXTRA_RESULTS_UPDATED = "resultsUpdated"; 1090 1091 /** 1092 * A batch of access point scans has been completed and the results areavailable. 1093 * Call {@link #getBatchedScanResults()} to obtain the results. 1094 * @deprecated This API is nolonger supported. 1095 * Use {@link WifiScanner} API 1096 * @hide 1097 */ 1098 @Deprecated 1099 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1100 public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION = 1101 "android.net.wifi.BATCHED_RESULTS"; 1102 1103 /** 1104 * The RSSI (signal strength) has changed. 1105 * 1106 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 1107 * @see #EXTRA_NEW_RSSI 1108 */ 1109 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1110 public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; 1111 /** 1112 * The lookup key for an {@code int} giving the new RSSI in dBm. 1113 */ 1114 public static final String EXTRA_NEW_RSSI = "newRssi"; 1115 1116 /** 1117 * @see #ACTION_LINK_CONFIGURATION_CHANGED 1118 * @hide 1119 */ 1120 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1121 public static final String LINK_CONFIGURATION_CHANGED_ACTION = 1122 "android.net.wifi.LINK_CONFIGURATION_CHANGED"; 1123 1124 /** 1125 * Broadcast intent action indicating that the link configuration changed on wifi. 1126 * <br /> No permissions are required to listen to this broadcast. 1127 * @hide 1128 */ 1129 @SystemApi 1130 public static final String ACTION_LINK_CONFIGURATION_CHANGED = 1131 // should be android.net.wifi.action.LINK_CONFIGURATION_CHANGED, but due to 1132 // @UnsupportedAppUsage leaving it as android.net.wifi.LINK_CONFIGURATION_CHANGED. 1133 LINK_CONFIGURATION_CHANGED_ACTION; 1134 1135 /** 1136 * The lookup key for a {@link android.net.LinkProperties} object associated with the 1137 * Wi-Fi network. 1138 * Included in the {@link #ACTION_LINK_CONFIGURATION_CHANGED} broadcast. 1139 * 1140 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 1141 * 1142 * @deprecated this extra is no longer populated. 1143 * 1144 * @hide 1145 */ 1146 @Deprecated 1147 @SystemApi 1148 public static final String EXTRA_LINK_PROPERTIES = "android.net.wifi.extra.LINK_PROPERTIES"; 1149 1150 /** 1151 * The lookup key for a {@link android.net.NetworkCapabilities} object associated with the 1152 * Wi-Fi network. Retrieve with 1153 * {@link android.content.Intent#getParcelableExtra(String)}. 1154 * @hide 1155 */ 1156 public static final String EXTRA_NETWORK_CAPABILITIES = "networkCapabilities"; 1157 1158 /** 1159 * The network IDs of the configured networks could have changed. 1160 */ 1161 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1162 public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; 1163 1164 /** 1165 * Activity Action: Show a system activity that allows the user to enable 1166 * scans to be available even with Wi-Fi turned off. 1167 * 1168 * <p>Notification of the result of this activity is posted using the 1169 * {@link android.app.Activity#onActivityResult} callback. The 1170 * <code>resultCode</code> 1171 * will be {@link android.app.Activity#RESULT_OK} if scan always mode has 1172 * been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user 1173 * has rejected the request or an error has occurred. 1174 */ 1175 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1176 public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = 1177 "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; 1178 1179 /** 1180 * Activity Action: Pick a Wi-Fi network to connect to. 1181 * <p>Input: Nothing. 1182 * <p>Output: Nothing. 1183 */ 1184 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1185 public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; 1186 1187 /** 1188 * Activity Action: Receiver should show UI to get user approval to enable WiFi. 1189 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 1190 * the name of the app requesting the action. 1191 * <p>Output: Nothing. 1192 * <p>No permissions are required to send this action. 1193 * @hide 1194 */ 1195 @SystemApi 1196 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1197 public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE"; 1198 1199 /** 1200 * Activity Action: Receiver should show UI to get user approval to disable WiFi. 1201 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 1202 * the name of the app requesting the action. 1203 * <p>Output: Nothing. 1204 * <p>No permissions are required to send this action. 1205 * @hide 1206 */ 1207 @SystemApi 1208 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1209 public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; 1210 1211 /** 1212 * Directed broadcast intent action indicating that the device has connected to one of the 1213 * network suggestions provided by the app. This will be sent post connection to a network 1214 * which was created with {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired( 1215 * boolean)} 1216 * flag set. 1217 * <p> 1218 * Note: The broadcast is sent to the app only if it holds 1219 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission. 1220 * 1221 * @see #EXTRA_NETWORK_SUGGESTION 1222 */ 1223 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1224 public static final String ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION = 1225 "android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION"; 1226 /** 1227 * Sent as as a part of {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} that holds 1228 * an instance of {@link WifiNetworkSuggestion} corresponding to the connected network. 1229 */ 1230 public static final String EXTRA_NETWORK_SUGGESTION = 1231 "android.net.wifi.extra.NETWORK_SUGGESTION"; 1232 1233 /** 1234 * Internally used Wi-Fi lock mode representing the case were no locks are held. 1235 * @hide 1236 */ 1237 public static final int WIFI_MODE_NO_LOCKS_HELD = 0; 1238 1239 /** 1240 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 1241 * and will behave normally, i.e., it will attempt to automatically 1242 * establish a connection to a remembered access point that is 1243 * within range, and will do periodic scans if there are remembered 1244 * access points but none are in range. 1245 * 1246 * @deprecated This API is non-functional and will have no impact. 1247 */ 1248 @Deprecated 1249 public static final int WIFI_MODE_FULL = 1; 1250 1251 /** 1252 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 1253 * but the only operation that will be supported is initiation of 1254 * scans, and the subsequent reporting of scan results. No attempts 1255 * will be made to automatically connect to remembered access points, 1256 * nor will periodic scans be automatically performed looking for 1257 * remembered access points. Scans must be explicitly requested by 1258 * an application in this mode. 1259 * 1260 * @deprecated This API is non-functional and will have no impact. 1261 */ 1262 @Deprecated 1263 public static final int WIFI_MODE_SCAN_ONLY = 2; 1264 1265 /** 1266 * In this Wi-Fi lock mode, Wi-Fi will not go to power save. 1267 * This results in operating with low packet latency. 1268 * The lock is only active when the device is connected to an access point. 1269 * The lock is active even when the device screen is off or the acquiring application is 1270 * running in the background. 1271 * This mode will consume more power and hence should be used only 1272 * when there is a need for this tradeoff. 1273 * <p> 1274 * An example use case is when a voice connection needs to be 1275 * kept active even after the device screen goes off. 1276 * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the 1277 * duration of the voice call may improve the call quality. 1278 * <p> 1279 * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_HIGH_PERF} 1280 * lock will have no impact. 1281 */ 1282 public static final int WIFI_MODE_FULL_HIGH_PERF = 3; 1283 1284 /** 1285 * In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency. 1286 * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock has the following limitations: 1287 * <ol> 1288 * <li>The lock is only active when the device is connected to an access point.</li> 1289 * <li>The lock is only active when the screen is on.</li> 1290 * <li>The lock is only active when the acquiring app is running in the foreground.</li> 1291 * </ol> 1292 * Low latency mode optimizes for reduced packet latency, 1293 * and as a result other performance measures may suffer when there are trade-offs to make: 1294 * <ol> 1295 * <li>Battery life may be reduced.</li> 1296 * <li>Throughput may be reduced.</li> 1297 * <li>Frequency of Wi-Fi scanning may be reduced. This may result in: </li> 1298 * <ul> 1299 * <li>The device may not roam or switch to the AP with highest signal quality.</li> 1300 * <li>Location accuracy may be reduced.</li> 1301 * </ul> 1302 * </ol> 1303 * <p> 1304 * Example use cases are real time gaming or virtual reality applications where 1305 * low latency is a key factor for user experience. 1306 * <p> 1307 * Note: For an app which acquires both {@link #WIFI_MODE_FULL_LOW_LATENCY} and 1308 * {@link #WIFI_MODE_FULL_HIGH_PERF} locks, {@link #WIFI_MODE_FULL_LOW_LATENCY} 1309 * lock will be effective when app is running in foreground and screen is on, 1310 * while the {@link #WIFI_MODE_FULL_HIGH_PERF} lock will take effect otherwise. 1311 */ 1312 public static final int WIFI_MODE_FULL_LOW_LATENCY = 4; 1313 1314 1315 /** Anything worse than or equal to this will show 0 bars. */ 1316 @UnsupportedAppUsage 1317 private static final int MIN_RSSI = -100; 1318 1319 /** Anything better than or equal to this will show the max bars. */ 1320 @UnsupportedAppUsage 1321 private static final int MAX_RSSI = -55; 1322 1323 /** 1324 * Number of RSSI levels used in the framework to initiate {@link #RSSI_CHANGED_ACTION} 1325 * broadcast, where each level corresponds to a range of RSSI values. 1326 * The {@link #RSSI_CHANGED_ACTION} broadcast will only fire if the RSSI 1327 * change is significant enough to change the RSSI signal level. 1328 * @hide 1329 */ 1330 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1331 public static final int RSSI_LEVELS = 5; 1332 1333 //TODO (b/146346676): This needs to be removed, not used in the code. 1334 /** 1335 * Auto settings in the driver. The driver could choose to operate on both 1336 * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band. 1337 * @hide 1338 */ 1339 @UnsupportedAppUsage 1340 public static final int WIFI_FREQUENCY_BAND_AUTO = 0; 1341 1342 /** 1343 * Operation on 5 GHz alone 1344 * @hide 1345 */ 1346 @UnsupportedAppUsage 1347 public static final int WIFI_FREQUENCY_BAND_5GHZ = 1; 1348 1349 /** 1350 * Operation on 2.4 GHz alone 1351 * @hide 1352 */ 1353 @UnsupportedAppUsage 1354 public static final int WIFI_FREQUENCY_BAND_2GHZ = 2; 1355 1356 /** @hide */ 1357 public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false; 1358 1359 /** 1360 * Maximum number of active locks we allow. 1361 * This limit was added to prevent apps from creating a ridiculous number 1362 * of locks and crashing the system by overflowing the global ref table. 1363 */ 1364 private static final int MAX_ACTIVE_LOCKS = 50; 1365 1366 /** Indicates an invalid SSID. */ 1367 public static final String UNKNOWN_SSID = "<unknown ssid>"; 1368 1369 /** @hide */ 1370 public static final MacAddress ALL_ZEROS_MAC_ADDRESS = 1371 MacAddress.fromString("00:00:00:00:00:00"); 1372 1373 /* Number of currently active WifiLocks and MulticastLocks */ 1374 @UnsupportedAppUsage 1375 private int mActiveLockCount; 1376 1377 private Context mContext; 1378 @UnsupportedAppUsage 1379 IWifiManager mService; 1380 private final int mTargetSdkVersion; 1381 1382 private Looper mLooper; 1383 private boolean mVerboseLoggingEnabled = false; 1384 1385 private final Object mLock = new Object(); // lock guarding access to the following vars 1386 @GuardedBy("mLock") 1387 private LocalOnlyHotspotCallbackProxy mLOHSCallbackProxy; 1388 @GuardedBy("mLock") 1389 private LocalOnlyHotspotObserverProxy mLOHSObserverProxy; 1390 1391 private static final SparseArray<IOnWifiUsabilityStatsListener> 1392 sOnWifiUsabilityStatsListenerMap = new SparseArray(); 1393 private static final SparseArray<ISuggestionConnectionStatusListener> 1394 sSuggestionConnectionStatusListenerMap = new SparseArray(); 1395 private static final SparseArray<ISuggestionUserApprovalStatusListener> 1396 sSuggestionUserApprovalStatusListenerMap = new SparseArray(); 1397 private static final SparseArray<IWifiVerboseLoggingStatusChangedListener> 1398 sWifiVerboseLoggingStatusChangedListenerMap = new SparseArray(); 1399 private static final SparseArray<INetworkRequestMatchCallback> 1400 sNetworkRequestMatchCallbackMap = new SparseArray(); 1401 private static final SparseArray<ITrafficStateCallback> 1402 sTrafficStateCallbackMap = new SparseArray(); 1403 private static final SparseArray<ISoftApCallback> sSoftApCallbackMap = new SparseArray(); 1404 1405 /** 1406 * Create a new WifiManager instance. 1407 * Applications will almost always want to use 1408 * {@link android.content.Context#getSystemService Context.getSystemService} to retrieve 1409 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. 1410 * 1411 * @param context the application context 1412 * @param service the Binder interface 1413 * @param looper the Looper used to deliver callbacks 1414 * @hide - hide this because it takes in a parameter of type IWifiManager, which 1415 * is a system private class. 1416 */ WifiManager(@onNull Context context, @NonNull IWifiManager service, @NonNull Looper looper)1417 public WifiManager(@NonNull Context context, @NonNull IWifiManager service, 1418 @NonNull Looper looper) { 1419 mContext = context; 1420 mService = service; 1421 mLooper = looper; 1422 mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; 1423 updateVerboseLoggingEnabledFromService(); 1424 } 1425 1426 /** 1427 * Return a list of all the networks configured for the current foreground 1428 * user. 1429 * 1430 * Not all fields of WifiConfiguration are returned. Only the following 1431 * fields are filled in: 1432 * <ul> 1433 * <li>networkId</li> 1434 * <li>SSID</li> 1435 * <li>BSSID</li> 1436 * <li>priority</li> 1437 * <li>allowedProtocols</li> 1438 * <li>allowedKeyManagement</li> 1439 * <li>allowedAuthAlgorithms</li> 1440 * <li>allowedPairwiseCiphers</li> 1441 * <li>allowedGroupCiphers</li> 1442 * <li>status</li> 1443 * </ul> 1444 * @return a list of network configurations in the form of a list 1445 * of {@link WifiConfiguration} objects. 1446 * 1447 * @deprecated 1448 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 1449 * mechanism to trigger connection to a Wi-Fi network. 1450 * b) See {@link #addNetworkSuggestions(List)}, 1451 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 1452 * when auto-connecting to wifi. 1453 * <b>Compatibility Note:</b> For applications targeting 1454 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return an 1455 * empty list. 1456 * <p> 1457 * Deprecation Exemptions: 1458 * <ul> 1459 * <li>Device Owner (DO), Profile Owner (PO) and system apps will have access to the full list. 1460 * <li>Callers with Carrier privilege will receive a restricted list only containing 1461 * configurations which they created. 1462 * </ul> 1463 */ 1464 @Deprecated 1465 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) getConfiguredNetworks()1466 public List<WifiConfiguration> getConfiguredNetworks() { 1467 try { 1468 ParceledListSlice<WifiConfiguration> parceledList = 1469 mService.getConfiguredNetworks(mContext.getOpPackageName(), 1470 mContext.getAttributionTag(), false); 1471 if (parceledList == null) { 1472 return Collections.emptyList(); 1473 } 1474 return parceledList.getList(); 1475 } catch (RemoteException e) { 1476 throw e.rethrowFromSystemServer(); 1477 } 1478 } 1479 1480 /** 1481 * Return a list of all the networks previously configured by the calling app. Can 1482 * be called by Device Owner (DO), Profile Owner (PO), Callers with Carrier privilege and 1483 * system apps. 1484 * 1485 * @return a list of network configurations in the form of a list 1486 * of {@link WifiConfiguration} objects. 1487 * @throws {@link java.lang.SecurityException} if the caller is allowed to call this API 1488 */ 1489 @RequiresPermission(ACCESS_WIFI_STATE) 1490 @NonNull getCallerConfiguredNetworks()1491 public List<WifiConfiguration> getCallerConfiguredNetworks() { 1492 try { 1493 ParceledListSlice<WifiConfiguration> parceledList = 1494 mService.getConfiguredNetworks(mContext.getOpPackageName(), 1495 mContext.getAttributionTag(), true); 1496 if (parceledList == null) { 1497 return Collections.emptyList(); 1498 } 1499 return parceledList.getList(); 1500 } catch (RemoteException e) { 1501 throw e.rethrowFromSystemServer(); 1502 } 1503 } 1504 1505 1506 /** @hide */ 1507 @SystemApi 1508 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE, READ_WIFI_CREDENTIAL}) getPrivilegedConfiguredNetworks()1509 public List<WifiConfiguration> getPrivilegedConfiguredNetworks() { 1510 try { 1511 ParceledListSlice<WifiConfiguration> parceledList = 1512 mService.getPrivilegedConfiguredNetworks(mContext.getOpPackageName(), 1513 mContext.getAttributionTag()); 1514 if (parceledList == null) { 1515 return Collections.emptyList(); 1516 } 1517 return parceledList.getList(); 1518 } catch (RemoteException e) { 1519 throw e.rethrowFromSystemServer(); 1520 } 1521 } 1522 1523 /** 1524 * Returns a list of all matching WifiConfigurations of PasspointConfiguration for a given list 1525 * of ScanResult. 1526 * 1527 * An empty list will be returned when no PasspointConfiguration are installed or if no 1528 * PasspointConfiguration match the ScanResult. 1529 * 1530 * @param scanResults a list of scanResult that represents the BSSID 1531 * @return List that consists of {@link WifiConfiguration} and corresponding scanResults per 1532 * network type({@link #PASSPOINT_HOME_NETWORK} and {@link #PASSPOINT_ROAMING_NETWORK}). 1533 * @hide 1534 */ 1535 @SystemApi 1536 @RequiresPermission(anyOf = { 1537 android.Manifest.permission.NETWORK_SETTINGS, 1538 android.Manifest.permission.NETWORK_SETUP_WIZARD 1539 }) 1540 @NonNull getAllMatchingWifiConfigs( @onNull List<ScanResult> scanResults)1541 public List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> getAllMatchingWifiConfigs( 1542 @NonNull List<ScanResult> scanResults) { 1543 List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>(); 1544 try { 1545 Map<String, Map<Integer, List<ScanResult>>> results = 1546 mService.getAllMatchingPasspointProfilesForScanResults(scanResults); 1547 if (results.isEmpty()) { 1548 return configs; 1549 } 1550 List<WifiConfiguration> wifiConfigurations = 1551 mService.getWifiConfigsForPasspointProfiles( 1552 new ArrayList<>(results.keySet())); 1553 for (WifiConfiguration configuration : wifiConfigurations) { 1554 Map<Integer, List<ScanResult>> scanResultsPerNetworkType = 1555 results.get(configuration.getProfileKey()); 1556 if (scanResultsPerNetworkType != null) { 1557 configs.add(Pair.create(configuration, scanResultsPerNetworkType)); 1558 } 1559 } 1560 } catch (RemoteException e) { 1561 throw e.rethrowFromSystemServer(); 1562 } 1563 1564 return configs; 1565 } 1566 1567 /** 1568 * Retrieve a list of {@link WifiConfiguration} for available {@link WifiNetworkSuggestion} 1569 * matching the given list of {@link ScanResult}. 1570 * 1571 * An available {@link WifiNetworkSuggestion} must satisfy: 1572 * <ul> 1573 * <li> Matching one of the {@link ScanResult} from the given list. 1574 * <li> and {@link WifiNetworkSuggestion.Builder#setIsUserAllowedToManuallyConnect(boolean)} set 1575 * to true. 1576 * </ul> 1577 * 1578 * @param scanResults a list of scanResult. 1579 * @return a list of @link WifiConfiguration} for available {@link WifiNetworkSuggestion} 1580 * @hide 1581 */ 1582 @SystemApi 1583 @RequiresPermission(anyOf = { 1584 android.Manifest.permission.NETWORK_SETTINGS, 1585 android.Manifest.permission.NETWORK_SETUP_WIZARD 1586 }) 1587 @NonNull getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( @onNull List<ScanResult> scanResults)1588 public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( 1589 @NonNull List<ScanResult> scanResults) { 1590 try { 1591 return mService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults); 1592 } catch (RemoteException e) { 1593 throw e.rethrowAsRuntimeException(); 1594 } 1595 } 1596 1597 /** 1598 * Returns a list of unique Hotspot 2.0 OSU (Online Sign-Up) providers associated with a given 1599 * list of ScanResult. 1600 * 1601 * An empty list will be returned if no match is found. 1602 * 1603 * @param scanResults a list of ScanResult 1604 * @return Map that consists {@link OsuProvider} and a list of matching {@link ScanResult} 1605 * @hide 1606 */ 1607 @SystemApi 1608 @RequiresPermission(anyOf = { 1609 android.Manifest.permission.NETWORK_SETTINGS, 1610 android.Manifest.permission.NETWORK_SETUP_WIZARD 1611 }) 1612 @NonNull getMatchingOsuProviders( @ullable List<ScanResult> scanResults)1613 public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( 1614 @Nullable List<ScanResult> scanResults) { 1615 if (scanResults == null) { 1616 return new HashMap<>(); 1617 } 1618 try { 1619 return mService.getMatchingOsuProviders(scanResults); 1620 } catch (RemoteException e) { 1621 throw e.rethrowFromSystemServer(); 1622 } 1623 } 1624 1625 /** 1626 * Returns the matching Passpoint R2 configurations for given OSU (Online Sign-Up) providers. 1627 * 1628 * Given a list of OSU providers, this only returns OSU providers that already have Passpoint R2 1629 * configurations in the device. 1630 * An empty map will be returned when there is no matching Passpoint R2 configuration for the 1631 * given OsuProviders. 1632 * 1633 * @param osuProviders a set of {@link OsuProvider} 1634 * @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}. 1635 * @hide 1636 */ 1637 @SystemApi 1638 @RequiresPermission(anyOf = { 1639 android.Manifest.permission.NETWORK_SETTINGS, 1640 android.Manifest.permission.NETWORK_SETUP_WIZARD 1641 }) 1642 @NonNull getMatchingPasspointConfigsForOsuProviders( @onNull Set<OsuProvider> osuProviders)1643 public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( 1644 @NonNull Set<OsuProvider> osuProviders) { 1645 try { 1646 return mService.getMatchingPasspointConfigsForOsuProviders( 1647 new ArrayList<>(osuProviders)); 1648 } catch (RemoteException e) { 1649 throw e.rethrowFromSystemServer(); 1650 } 1651 } 1652 1653 /** 1654 * Add a new network description to the set of configured networks. 1655 * The {@code networkId} field of the supplied configuration object 1656 * is ignored. 1657 * <p/> 1658 * The new network will be marked DISABLED by default. To enable it, 1659 * called {@link #enableNetwork}. 1660 * 1661 * @param config the set of variables that describe the configuration, 1662 * contained in a {@link WifiConfiguration} object. 1663 * If the {@link WifiConfiguration} has an Http Proxy set 1664 * the calling app must be System, or be provisioned as the Profile or Device Owner. 1665 * @return the ID of the newly created network description. This is used in 1666 * other operations to specified the network to be acted upon. 1667 * Returns {@code -1} on failure. 1668 * 1669 * @deprecated 1670 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 1671 * mechanism to trigger connection to a Wi-Fi network. 1672 * b) See {@link #addNetworkSuggestions(List)}, 1673 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 1674 * when auto-connecting to wifi. 1675 * <b>Compatibility Note:</b> For applications targeting 1676 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 1677 * {@code -1}. 1678 * <p> 1679 * Deprecation Exemptions: 1680 * <ul> 1681 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 1682 * </ul> 1683 */ 1684 @Deprecated addNetwork(WifiConfiguration config)1685 public int addNetwork(WifiConfiguration config) { 1686 if (config == null) { 1687 return -1; 1688 } 1689 config.networkId = -1; 1690 return addOrUpdateNetwork(config); 1691 } 1692 1693 /** 1694 * This is a new version of {@link #addNetwork(WifiConfiguration)} which returns more detailed 1695 * failure codes. The usage of this API is limited to Device Owner (DO), Profile Owner (PO), 1696 * system app, and privileged apps. 1697 * <p> 1698 * Add a new network description to the set of configured networks. The {@code networkId} 1699 * field of the supplied configuration object is ignored. The new network will be marked 1700 * DISABLED by default. To enable it, call {@link #enableNetwork}. 1701 * <p> 1702 * @param config the set of variables that describe the configuration, 1703 * contained in a {@link WifiConfiguration} object. 1704 * If the {@link WifiConfiguration} has an Http Proxy set 1705 * the calling app must be System, or be provisioned as the Profile or Device Owner. 1706 * @return A {@link AddNetworkResult} Object. 1707 * @throws {@link SecurityException} if the calling app is not a Device Owner (DO), 1708 * Profile Owner (PO), system app, or a privileged app that has one of 1709 * the permissions required by this API. 1710 * @throws {@link IllegalArgumentException} if the input configuration is null. 1711 */ 1712 @RequiresPermission(anyOf = { 1713 android.Manifest.permission.NETWORK_SETTINGS, 1714 android.Manifest.permission.NETWORK_STACK, 1715 android.Manifest.permission.NETWORK_SETUP_WIZARD, 1716 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING 1717 }) 1718 @NonNull addNetworkPrivileged(@onNull WifiConfiguration config)1719 public AddNetworkResult addNetworkPrivileged(@NonNull WifiConfiguration config) { 1720 if (config == null) throw new IllegalArgumentException("config cannot be null"); 1721 config.networkId = -1; 1722 try { 1723 return mService.addOrUpdateNetworkPrivileged(config, mContext.getOpPackageName()); 1724 } catch (RemoteException e) { 1725 throw e.rethrowFromSystemServer(); 1726 } 1727 } 1728 1729 /** 1730 * Provides the results of a call to {@link #addNetworkPrivileged(WifiConfiguration)} 1731 */ 1732 public static final class AddNetworkResult implements Parcelable { 1733 /** 1734 * The operation has completed successfully. 1735 */ 1736 public static final int STATUS_SUCCESS = 0; 1737 /** 1738 * The operation has failed due to an unknown reason. 1739 */ 1740 public static final int STATUS_FAILURE_UNKNOWN = 1; 1741 /** 1742 * The calling app does not have permission to call this API. 1743 */ 1744 public static final int STATUS_NO_PERMISSION = 2; 1745 /** 1746 * Generic failure code for adding a passpoint network. 1747 */ 1748 public static final int STATUS_ADD_PASSPOINT_FAILURE = 3; 1749 /** 1750 * Generic failure code for adding a non-passpoint network. 1751 */ 1752 public static final int STATUS_ADD_WIFI_CONFIG_FAILURE = 4; 1753 /** 1754 * The network configuration is invalid. 1755 */ 1756 public static final int STATUS_INVALID_CONFIGURATION = 5; 1757 /** 1758 * The calling app has no permission to modify the configuration. 1759 */ 1760 public static final int STATUS_NO_PERMISSION_MODIFY_CONFIG = 6; 1761 /** 1762 * The calling app has no permission to modify the proxy setting. 1763 */ 1764 public static final int STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING = 7; 1765 /** 1766 * The calling app has no permission to modify the MAC randomization setting. 1767 */ 1768 public static final int STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION = 8; 1769 /** 1770 * Internal failure in updating network keys.. 1771 */ 1772 public static final int STATUS_FAILURE_UPDATE_NETWORK_KEYS = 9; 1773 /** 1774 * The enterprise network is missing either the root CA or domain name. 1775 */ 1776 public static final int STATUS_INVALID_CONFIGURATION_ENTERPRISE = 10; 1777 1778 /** @hide */ 1779 @IntDef(prefix = { "STATUS_" }, value = { 1780 STATUS_SUCCESS, 1781 STATUS_FAILURE_UNKNOWN, 1782 STATUS_NO_PERMISSION, 1783 STATUS_ADD_PASSPOINT_FAILURE, 1784 STATUS_ADD_WIFI_CONFIG_FAILURE, 1785 STATUS_INVALID_CONFIGURATION, 1786 STATUS_NO_PERMISSION_MODIFY_CONFIG, 1787 STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING, 1788 STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION, 1789 STATUS_FAILURE_UPDATE_NETWORK_KEYS, 1790 STATUS_INVALID_CONFIGURATION_ENTERPRISE, 1791 }) 1792 @Retention(RetentionPolicy.SOURCE) 1793 public @interface AddNetworkStatusCode {} 1794 1795 @Override describeContents()1796 public int describeContents() { 1797 return 0; 1798 } 1799 1800 @Override writeToParcel(@onNull Parcel dest, int flags)1801 public void writeToParcel(@NonNull Parcel dest, int flags) { 1802 dest.writeInt(statusCode); 1803 dest.writeInt(networkId); 1804 } 1805 1806 /** Implement the Parcelable interface */ 1807 public static final @android.annotation.NonNull Creator<AddNetworkResult> CREATOR = 1808 new Creator<AddNetworkResult>() { 1809 public AddNetworkResult createFromParcel(Parcel in) { 1810 return new AddNetworkResult(in.readInt(), in.readInt()); 1811 } 1812 1813 public AddNetworkResult[] newArray(int size) { 1814 return new AddNetworkResult[size]; 1815 } 1816 }; 1817 1818 /** 1819 * One of the {@code STATUS_} values. If the operation is successful this field 1820 * will be set to {@code STATUS_SUCCESS}. 1821 */ 1822 public final @AddNetworkStatusCode int statusCode; 1823 /** 1824 * The identifier of the added network, which could be used in other operations. This field 1825 * will be set to {@code -1} if the operation failed. 1826 */ 1827 public final int networkId; 1828 AddNetworkResult(@ddNetworkStatusCode int statusCode, int networkId)1829 public AddNetworkResult(@AddNetworkStatusCode int statusCode, int networkId) { 1830 this.statusCode = statusCode; 1831 this.networkId = networkId; 1832 } 1833 } 1834 1835 /** 1836 * Update the network description of an existing configured network. 1837 * 1838 * @param config the set of variables that describe the configuration, 1839 * contained in a {@link WifiConfiguration} object. It may 1840 * be sparse, so that only the items that are being changed 1841 * are non-<code>null</code>. The {@code networkId} field 1842 * must be set to the ID of the existing network being updated. 1843 * If the {@link WifiConfiguration} has an Http Proxy set 1844 * the calling app must be System, or be provisioned as the Profile or Device Owner. 1845 * @return Returns the {@code networkId} of the supplied 1846 * {@code WifiConfiguration} on success. 1847 * <br/> 1848 * Returns {@code -1} on failure, including when the {@code networkId} 1849 * field of the {@code WifiConfiguration} does not refer to an 1850 * existing network. 1851 * 1852 * @deprecated 1853 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 1854 * mechanism to trigger connection to a Wi-Fi network. 1855 * b) See {@link #addNetworkSuggestions(List)}, 1856 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 1857 * when auto-connecting to wifi. 1858 * <b>Compatibility Note:</b> For applications targeting 1859 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 1860 * {@code -1}. 1861 * <p> 1862 * Deprecation Exemptions: 1863 * <ul> 1864 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 1865 * </ul> 1866 */ 1867 @Deprecated updateNetwork(WifiConfiguration config)1868 public int updateNetwork(WifiConfiguration config) { 1869 if (config == null || config.networkId < 0) { 1870 return -1; 1871 } 1872 return addOrUpdateNetwork(config); 1873 } 1874 1875 /** 1876 * Internal method for doing the RPC that creates a new network description 1877 * or updates an existing one. 1878 * 1879 * @param config The possibly sparse object containing the variables that 1880 * are to set or updated in the network description. 1881 * @return the ID of the network on success, {@code -1} on failure. 1882 */ addOrUpdateNetwork(WifiConfiguration config)1883 private int addOrUpdateNetwork(WifiConfiguration config) { 1884 try { 1885 return mService.addOrUpdateNetwork(config, mContext.getOpPackageName()); 1886 } catch (RemoteException e) { 1887 throw e.rethrowFromSystemServer(); 1888 } 1889 } 1890 1891 /** 1892 * Interface for indicating user selection from the list of networks presented in the 1893 * {@link NetworkRequestMatchCallback#onMatch(List)}. 1894 * 1895 * The platform will implement this callback and pass it along with the 1896 * {@link NetworkRequestMatchCallback#onUserSelectionCallbackRegistration( 1897 * NetworkRequestUserSelectionCallback)}. The UI component handling 1898 * {@link NetworkRequestMatchCallback} will invoke {@link #select(WifiConfiguration)} or 1899 * {@link #reject()} to return the user's selection back to the platform via this callback. 1900 * @hide 1901 */ 1902 @SystemApi 1903 public interface NetworkRequestUserSelectionCallback { 1904 /** 1905 * User selected this network to connect to. 1906 * @param wifiConfiguration WifiConfiguration object corresponding to the network 1907 * user selected. 1908 */ 1909 @SuppressLint("CallbackMethodName") select(@onNull WifiConfiguration wifiConfiguration)1910 default void select(@NonNull WifiConfiguration wifiConfiguration) {} 1911 1912 /** 1913 * User rejected the app's request. 1914 */ 1915 @SuppressLint("CallbackMethodName") reject()1916 default void reject() {} 1917 } 1918 1919 /** 1920 * Interface for network request callback. Should be implemented by applications and passed when 1921 * calling {@link #registerNetworkRequestMatchCallback(Executor, 1922 * WifiManager.NetworkRequestMatchCallback)}. 1923 * 1924 * This is meant to be implemented by a UI component to present the user with a list of networks 1925 * matching the app's request. The user is allowed to pick one of these networks to connect to 1926 * or reject the request by the app. 1927 * @hide 1928 */ 1929 @SystemApi 1930 public interface NetworkRequestMatchCallback { 1931 /** 1932 * Invoked to register a callback to be invoked to convey user selection. The callback 1933 * object passed in this method is to be invoked by the UI component after the service sends 1934 * a list of matching scan networks using {@link #onMatch(List)} and user picks a network 1935 * from that list. 1936 * 1937 * @param userSelectionCallback Callback object to send back the user selection. 1938 */ onUserSelectionCallbackRegistration( @onNull NetworkRequestUserSelectionCallback userSelectionCallback)1939 default void onUserSelectionCallbackRegistration( 1940 @NonNull NetworkRequestUserSelectionCallback userSelectionCallback) {} 1941 1942 /** 1943 * Invoked when the active network request is aborted, either because 1944 * <li> The app released the request, OR</li> 1945 * <li> Request was overridden by a new request</li> 1946 * This signals the end of processing for the current request and should stop the UI 1947 * component. No subsequent calls from the UI component will be handled by the platform. 1948 */ onAbort()1949 default void onAbort() {} 1950 1951 /** 1952 * Invoked when a network request initiated by an app matches some networks in scan results. 1953 * This may be invoked multiple times for a single network request as the platform finds new 1954 * matching networks in scan results. 1955 * 1956 * @param scanResults List of {@link ScanResult} objects corresponding to the networks 1957 * matching the request. 1958 */ onMatch(@onNull List<ScanResult> scanResults)1959 default void onMatch(@NonNull List<ScanResult> scanResults) {} 1960 1961 /** 1962 * Invoked on a successful connection with the network that the user selected 1963 * via {@link NetworkRequestUserSelectionCallback}. 1964 * 1965 * @param wifiConfiguration WifiConfiguration object corresponding to the network that the 1966 * user selected. 1967 */ onUserSelectionConnectSuccess(@onNull WifiConfiguration wifiConfiguration)1968 default void onUserSelectionConnectSuccess(@NonNull WifiConfiguration wifiConfiguration) {} 1969 1970 /** 1971 * Invoked on failure to establish connection with the network that the user selected 1972 * via {@link NetworkRequestUserSelectionCallback}. 1973 * 1974 * @param wifiConfiguration WifiConfiguration object corresponding to the network 1975 * user selected. 1976 */ onUserSelectionConnectFailure(@onNull WifiConfiguration wifiConfiguration)1977 default void onUserSelectionConnectFailure(@NonNull WifiConfiguration wifiConfiguration) {} 1978 } 1979 1980 /** 1981 * Callback proxy for NetworkRequestUserSelectionCallback objects. 1982 * @hide 1983 */ 1984 private class NetworkRequestUserSelectionCallbackProxy implements 1985 NetworkRequestUserSelectionCallback { 1986 private final INetworkRequestUserSelectionCallback mCallback; 1987 NetworkRequestUserSelectionCallbackProxy( INetworkRequestUserSelectionCallback callback)1988 NetworkRequestUserSelectionCallbackProxy( 1989 INetworkRequestUserSelectionCallback callback) { 1990 mCallback = callback; 1991 } 1992 1993 @Override select(@onNull WifiConfiguration wifiConfiguration)1994 public void select(@NonNull WifiConfiguration wifiConfiguration) { 1995 if (mVerboseLoggingEnabled) { 1996 Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: select " 1997 + "wificonfiguration: " + wifiConfiguration); 1998 } 1999 try { 2000 mCallback.select(wifiConfiguration); 2001 } catch (RemoteException e) { 2002 Log.e(TAG, "Failed to invoke onSelected", e); 2003 throw e.rethrowFromSystemServer(); 2004 } 2005 } 2006 2007 @Override reject()2008 public void reject() { 2009 if (mVerboseLoggingEnabled) { 2010 Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: reject"); 2011 } 2012 try { 2013 mCallback.reject(); 2014 } catch (RemoteException e) { 2015 Log.e(TAG, "Failed to invoke onRejected", e); 2016 throw e.rethrowFromSystemServer(); 2017 } 2018 } 2019 } 2020 2021 /** 2022 * Callback proxy for NetworkRequestMatchCallback objects. 2023 * @hide 2024 */ 2025 private class NetworkRequestMatchCallbackProxy extends INetworkRequestMatchCallback.Stub { 2026 private final Executor mExecutor; 2027 private final NetworkRequestMatchCallback mCallback; 2028 NetworkRequestMatchCallbackProxy(Executor executor, NetworkRequestMatchCallback callback)2029 NetworkRequestMatchCallbackProxy(Executor executor, NetworkRequestMatchCallback callback) { 2030 mExecutor = executor; 2031 mCallback = callback; 2032 } 2033 2034 @Override onUserSelectionCallbackRegistration( INetworkRequestUserSelectionCallback userSelectionCallback)2035 public void onUserSelectionCallbackRegistration( 2036 INetworkRequestUserSelectionCallback userSelectionCallback) { 2037 if (mVerboseLoggingEnabled) { 2038 Log.v(TAG, "NetworkRequestMatchCallbackProxy: " 2039 + "onUserSelectionCallbackRegistration callback: " + userSelectionCallback); 2040 } 2041 Binder.clearCallingIdentity(); 2042 mExecutor.execute(() -> { 2043 mCallback.onUserSelectionCallbackRegistration( 2044 new NetworkRequestUserSelectionCallbackProxy(userSelectionCallback)); 2045 }); 2046 } 2047 2048 @Override onAbort()2049 public void onAbort() { 2050 if (mVerboseLoggingEnabled) { 2051 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onAbort"); 2052 } 2053 Binder.clearCallingIdentity(); 2054 mExecutor.execute(() -> { 2055 mCallback.onAbort(); 2056 }); 2057 } 2058 2059 @Override onMatch(List<ScanResult> scanResults)2060 public void onMatch(List<ScanResult> scanResults) { 2061 if (mVerboseLoggingEnabled) { 2062 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onMatch scanResults: " 2063 + scanResults); 2064 } 2065 Binder.clearCallingIdentity(); 2066 mExecutor.execute(() -> { 2067 mCallback.onMatch(scanResults); 2068 }); 2069 } 2070 2071 @Override onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration)2072 public void onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration) { 2073 if (mVerboseLoggingEnabled) { 2074 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectSuccess " 2075 + " wificonfiguration: " + wifiConfiguration); 2076 } 2077 Binder.clearCallingIdentity(); 2078 mExecutor.execute(() -> { 2079 mCallback.onUserSelectionConnectSuccess(wifiConfiguration); 2080 }); 2081 } 2082 2083 @Override onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration)2084 public void onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration) { 2085 if (mVerboseLoggingEnabled) { 2086 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectFailure" 2087 + " wificonfiguration: " + wifiConfiguration); 2088 } 2089 Binder.clearCallingIdentity(); 2090 mExecutor.execute(() -> { 2091 mCallback.onUserSelectionConnectFailure(wifiConfiguration); 2092 }); 2093 } 2094 } 2095 2096 /** 2097 * Registers a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. 2098 * Caller can unregister a previously registered callback using 2099 * {@link #unregisterNetworkRequestMatchCallback(NetworkRequestMatchCallback)} 2100 * <p> 2101 * Applications should have the 2102 * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers 2103 * without the permission will trigger a {@link java.lang.SecurityException}. 2104 * <p> 2105 * 2106 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 2107 * object. 2108 * @param callback Callback for network match events to register. 2109 * @hide 2110 */ 2111 @SystemApi 2112 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) registerNetworkRequestMatchCallback(@onNull @allbackExecutor Executor executor, @NonNull NetworkRequestMatchCallback callback)2113 public void registerNetworkRequestMatchCallback(@NonNull @CallbackExecutor Executor executor, 2114 @NonNull NetworkRequestMatchCallback callback) { 2115 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 2116 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 2117 Log.v(TAG, "registerNetworkRequestMatchCallback: callback=" + callback 2118 + ", executor=" + executor); 2119 2120 try { 2121 synchronized (sNetworkRequestMatchCallbackMap) { 2122 INetworkRequestMatchCallback.Stub binderCallback = 2123 new NetworkRequestMatchCallbackProxy(executor, callback); 2124 sNetworkRequestMatchCallbackMap.put(System.identityHashCode(callback), 2125 binderCallback); 2126 mService.registerNetworkRequestMatchCallback(binderCallback); 2127 } 2128 } catch (RemoteException e) { 2129 throw e.rethrowFromSystemServer(); 2130 } 2131 } 2132 2133 /** 2134 * Unregisters a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. 2135 * <p> 2136 * Applications should have the 2137 * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers 2138 * without the permission will trigger a {@link java.lang.SecurityException}. 2139 * <p> 2140 * 2141 * @param callback Callback for network match events to unregister. 2142 * @hide 2143 */ 2144 @SystemApi 2145 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) unregisterNetworkRequestMatchCallback( @onNull NetworkRequestMatchCallback callback)2146 public void unregisterNetworkRequestMatchCallback( 2147 @NonNull NetworkRequestMatchCallback callback) { 2148 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 2149 Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback); 2150 2151 try { 2152 synchronized (sNetworkRequestMatchCallbackMap) { 2153 int callbackIdentifier = System.identityHashCode(callback); 2154 if (!sNetworkRequestMatchCallbackMap.contains(callbackIdentifier)) { 2155 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 2156 return; 2157 } 2158 mService.unregisterNetworkRequestMatchCallback( 2159 sNetworkRequestMatchCallbackMap.get(callbackIdentifier)); 2160 sNetworkRequestMatchCallbackMap.remove(callbackIdentifier); 2161 } 2162 } catch (RemoteException e) { 2163 throw e.rethrowFromSystemServer(); 2164 } 2165 } 2166 2167 /** 2168 * Privileged API to revoke all app state from wifi stack (equivalent to operations that the 2169 * wifi stack performs to clear state for an app that was uninstalled. 2170 * This removes: 2171 * <li> All saved networks or passpoint profiles added by the app </li> 2172 * <li> All previously approved peer to peer connection to access points initiated by the app 2173 * using {@link WifiNetworkSpecifier}</li> 2174 * <li> All network suggestions and approvals provided using {@link WifiNetworkSuggestion}</li> 2175 * <p> 2176 * @param targetAppUid UID of the app. 2177 * @param targetAppPackageName Package name of the app. 2178 * @hide 2179 */ 2180 @SystemApi 2181 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) removeAppState(int targetAppUid, @NonNull String targetAppPackageName)2182 public void removeAppState(int targetAppUid, @NonNull String targetAppPackageName) { 2183 try { 2184 mService.removeAppState(targetAppUid, targetAppPackageName); 2185 } catch (RemoteException e) { 2186 throw e.rethrowAsRuntimeException(); 2187 } 2188 } 2189 2190 /** 2191 * Provide a list of network suggestions to the device. See {@link WifiNetworkSuggestion} 2192 * for a detailed explanation of the parameters. 2193 * When the device decides to connect to one of the provided network suggestions, platform sends 2194 * a directed broadcast {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} to the app if 2195 * the network was created with 2196 * {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired(boolean)} flag set and the 2197 * app holds {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} 2198 * permission. 2199 *<p> 2200 * NOTE: 2201 * <li> These networks are just a suggestion to the platform. The platform will ultimately 2202 * decide on which network the device connects to. </li> 2203 * <li> When an app is uninstalled or disabled, all its suggested networks are discarded. 2204 * If the device is currently connected to a suggested network which is being removed then the 2205 * device will disconnect from that network.</li> 2206 * <li> If user reset network settings, all added suggestions will be discarded. Apps can use 2207 * {@link #getNetworkSuggestions()} to check if their suggestions are in the device.</li> 2208 * <li> In-place modification of existing suggestions are allowed. 2209 * <li> If the provided suggestions include any previously provided suggestions by the app, 2210 * previous suggestions will be updated.</li> 2211 * <li>If one of the provided suggestions marks a previously unmetered suggestion as metered and 2212 * the device is currently connected to that suggested network, then the device will disconnect 2213 * from that network. The system will immediately re-evaluate all the network candidates 2214 * and possibly reconnect back to the same suggestion. This disconnect is to make sure that any 2215 * traffic flowing over unmetered networks isn't accidentally continued over a metered network. 2216 * </li> 2217 * </li> 2218 * 2219 * @param networkSuggestions List of network suggestions provided by the app. 2220 * @return Status code for the operation. One of the STATUS_NETWORK_SUGGESTIONS_ values. 2221 * @throws {@link SecurityException} if the caller is missing required permissions. 2222 * @see WifiNetworkSuggestion#equals(Object) 2223 */ 2224 @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) addNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions)2225 public @NetworkSuggestionsStatusCode int addNetworkSuggestions( 2226 @NonNull List<WifiNetworkSuggestion> networkSuggestions) { 2227 try { 2228 return mService.addNetworkSuggestions( 2229 networkSuggestions, mContext.getOpPackageName(), mContext.getAttributionTag()); 2230 } catch (RemoteException e) { 2231 throw e.rethrowFromSystemServer(); 2232 } 2233 } 2234 2235 /** 2236 * Remove some or all of the network suggestions that were previously provided by the app. 2237 * If one of the suggestions being removed was used to establish connection to the current 2238 * network, then the device will immediately disconnect from that network. 2239 * 2240 * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters. 2241 * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used. 2242 * 2243 * @param networkSuggestions List of network suggestions to be removed. Pass an empty list 2244 * to remove all the previous suggestions provided by the app. 2245 * @return Status code for the operation. One of the STATUS_NETWORK_SUGGESTIONS_ values. 2246 * Any matching suggestions are removed from the device and will not be considered for any 2247 * further connection attempts. 2248 */ 2249 @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) removeNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions)2250 public @NetworkSuggestionsStatusCode int removeNetworkSuggestions( 2251 @NonNull List<WifiNetworkSuggestion> networkSuggestions) { 2252 try { 2253 return mService.removeNetworkSuggestions( 2254 networkSuggestions, mContext.getOpPackageName()); 2255 } catch (RemoteException e) { 2256 throw e.rethrowFromSystemServer(); 2257 } 2258 } 2259 2260 /** 2261 * Get all network suggestions provided by the calling app. 2262 * See {@link #addNetworkSuggestions(List)} 2263 * See {@link #removeNetworkSuggestions(List)} 2264 * @return a list of {@link WifiNetworkSuggestion} 2265 */ 2266 @RequiresPermission(ACCESS_WIFI_STATE) getNetworkSuggestions()2267 public @NonNull List<WifiNetworkSuggestion> getNetworkSuggestions() { 2268 try { 2269 return mService.getNetworkSuggestions(mContext.getOpPackageName()); 2270 } catch (RemoteException e) { 2271 throw e.rethrowAsRuntimeException(); 2272 } 2273 } 2274 2275 /** 2276 * Returns the max number of network suggestions that are allowed per app on the device. 2277 * @see #addNetworkSuggestions(List) 2278 * @see #removeNetworkSuggestions(List) 2279 */ getMaxNumberOfNetworkSuggestionsPerApp()2280 public int getMaxNumberOfNetworkSuggestionsPerApp() { 2281 return getMaxNumberOfNetworkSuggestionsPerApp( 2282 mContext.getSystemService(ActivityManager.class).isLowRamDevice()); 2283 } 2284 2285 /** @hide */ getMaxNumberOfNetworkSuggestionsPerApp(boolean isLowRamDevice)2286 public static int getMaxNumberOfNetworkSuggestionsPerApp(boolean isLowRamDevice) { 2287 return isLowRamDevice 2288 ? NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM 2289 : NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM; 2290 } 2291 2292 /** 2293 * Add or update a Passpoint configuration. The configuration provides a credential 2294 * for connecting to Passpoint networks that are operated by the Passpoint 2295 * service provider specified in the configuration. 2296 * 2297 * Each configuration is uniquely identified by a unique key which depends on the contents of 2298 * the configuration. This allows the caller to install multiple profiles with the same FQDN 2299 * (Fully qualified domain name). Therefore, in order to update an existing profile, it is 2300 * first required to remove it using {@link WifiManager#removePasspointConfiguration(String)}. 2301 * Otherwise, a new profile will be added with both configuration. 2302 * 2303 * Deprecated for general app usage - except DO/PO apps. 2304 * See {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} to 2305 * create a passpoint suggestion. 2306 * See {@link #addNetworkSuggestions(List)}, {@link #removeNetworkSuggestions(List)} for new 2307 * API to add Wi-Fi networks for consideration when auto-connecting to wifi. 2308 * <b>Compatibility Note:</b> For applications targeting 2309 * {@link android.os.Build.VERSION_CODES#R} or above, this API will always fail and throw 2310 * {@link IllegalArgumentException}. 2311 * <p> 2312 * Deprecation Exemptions: 2313 * <ul> 2314 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2315 * </ul> 2316 * 2317 * @param config The Passpoint configuration to be added 2318 * @throws IllegalArgumentException if configuration is invalid or Passpoint is not enabled on 2319 * the device. 2320 */ addOrUpdatePasspointConfiguration(PasspointConfiguration config)2321 public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) { 2322 try { 2323 if (!mService.addOrUpdatePasspointConfiguration(config, mContext.getOpPackageName())) { 2324 throw new IllegalArgumentException(); 2325 } 2326 } catch (RemoteException e) { 2327 throw e.rethrowFromSystemServer(); 2328 } 2329 } 2330 2331 /** 2332 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name) added 2333 * by the caller. 2334 * 2335 * @param fqdn The FQDN of the Passpoint configuration added by the caller to be removed 2336 * @throws IllegalArgumentException if no configuration is associated with the given FQDN or 2337 * Passpoint is not enabled on the device. 2338 * @deprecated This will be non-functional in a future release. 2339 */ 2340 @Deprecated 2341 @RequiresPermission(anyOf = { 2342 android.Manifest.permission.NETWORK_SETTINGS, 2343 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING 2344 }) removePasspointConfiguration(String fqdn)2345 public void removePasspointConfiguration(String fqdn) { 2346 try { 2347 if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) { 2348 throw new IllegalArgumentException(); 2349 } 2350 } catch (RemoteException e) { 2351 throw e.rethrowFromSystemServer(); 2352 } 2353 } 2354 2355 /** 2356 * Return the list of installed Passpoint configurations added by the caller. 2357 * 2358 * An empty list will be returned when no configurations are installed. 2359 * 2360 * @return A list of {@link PasspointConfiguration} added by the caller 2361 * @deprecated This will be non-functional in a future release. 2362 */ 2363 @Deprecated 2364 @RequiresPermission(anyOf = { 2365 android.Manifest.permission.NETWORK_SETTINGS, 2366 android.Manifest.permission.NETWORK_SETUP_WIZARD 2367 }) getPasspointConfigurations()2368 public List<PasspointConfiguration> getPasspointConfigurations() { 2369 try { 2370 return mService.getPasspointConfigurations(mContext.getOpPackageName()); 2371 } catch (RemoteException e) { 2372 throw e.rethrowFromSystemServer(); 2373 } 2374 } 2375 2376 /** 2377 * Query for a Hotspot 2.0 release 2 OSU icon file. An {@link #ACTION_PASSPOINT_ICON} intent 2378 * will be broadcasted once the request is completed. The presence of the intent extra 2379 * {@link #EXTRA_ICON} will indicate the result of the request. 2380 * A missing intent extra {@link #EXTRA_ICON} will indicate a failure. 2381 * 2382 * @param bssid The BSSID of the AP 2383 * @param fileName Name of the icon file (remote file) to query from the AP 2384 * 2385 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 2386 * @hide 2387 */ queryPasspointIcon(long bssid, String fileName)2388 public void queryPasspointIcon(long bssid, String fileName) { 2389 try { 2390 mService.queryPasspointIcon(bssid, fileName); 2391 } catch (RemoteException e) { 2392 throw e.rethrowFromSystemServer(); 2393 } 2394 } 2395 2396 /** 2397 * Match the currently associated network against the SP matching the given FQDN 2398 * @param fqdn FQDN of the SP 2399 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 2400 * @hide 2401 */ matchProviderWithCurrentNetwork(String fqdn)2402 public int matchProviderWithCurrentNetwork(String fqdn) { 2403 try { 2404 return mService.matchProviderWithCurrentNetwork(fqdn); 2405 } catch (RemoteException e) { 2406 throw e.rethrowFromSystemServer(); 2407 } 2408 } 2409 2410 /** 2411 * Remove the specified network from the list of configured networks. 2412 * This may result in the asynchronous delivery of state change 2413 * events. 2414 * 2415 * Applications are not allowed to remove networks created by other 2416 * applications. 2417 * 2418 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 2419 * #getConfiguredNetworks}. 2420 * @return {@code true} if the operation succeeded 2421 * 2422 * @deprecated 2423 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2424 * mechanism to trigger connection to a Wi-Fi network. 2425 * b) See {@link #addNetworkSuggestions(List)}, 2426 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2427 * when auto-connecting to wifi. 2428 * <b>Compatibility Note:</b> For applications targeting 2429 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 2430 * {@code false}. 2431 * <p> 2432 * Deprecation Exemptions: 2433 * <ul> 2434 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2435 * </ul> 2436 */ 2437 @Deprecated removeNetwork(int netId)2438 public boolean removeNetwork(int netId) { 2439 try { 2440 return mService.removeNetwork(netId, mContext.getOpPackageName()); 2441 } catch (RemoteException e) { 2442 throw e.rethrowFromSystemServer(); 2443 } 2444 } 2445 2446 /** 2447 * Remove all configured networks that were not created by the calling app. Can only 2448 * be called by a Device Owner (DO) app. 2449 * 2450 * @return {@code true} if at least one network is removed, {@code false} otherwise 2451 * @throws {@link java.lang.SecurityException} if the caller is not a Device Owner app 2452 */ 2453 @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) removeNonCallerConfiguredNetworks()2454 public boolean removeNonCallerConfiguredNetworks() { 2455 try { 2456 return mService.removeNonCallerConfiguredNetworks(mContext.getOpPackageName()); 2457 } catch (RemoteException e) { 2458 throw e.rethrowFromSystemServer(); 2459 } 2460 } 2461 /** 2462 * Allow a previously configured network to be associated with. If 2463 * <code>attemptConnect</code> is true, an attempt to connect to the selected 2464 * network is initiated. This may result in the asynchronous delivery 2465 * of state change events. 2466 * <p> 2467 * <b>Note:</b> Network communication may not use Wi-Fi even if Wi-Fi is connected; 2468 * traffic may instead be sent through another network, such as cellular data, 2469 * Bluetooth tethering, or Ethernet. For example, traffic will never use a 2470 * Wi-Fi network that does not provide Internet access (e.g. a wireless 2471 * printer), if another network that does offer Internet access (e.g. 2472 * cellular data) is available. Applications that need to ensure that their 2473 * network traffic uses Wi-Fi should use APIs such as 2474 * {@link Network#bindSocket(java.net.Socket)}, 2475 * {@link Network#openConnection(java.net.URL)}, or 2476 * {@link ConnectivityManager#bindProcessToNetwork} to do so. 2477 * 2478 * Applications are not allowed to enable networks created by other 2479 * applications. 2480 * 2481 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 2482 * #getConfiguredNetworks}. 2483 * @param attemptConnect The way to select a particular network to connect to is specify 2484 * {@code true} for this parameter. 2485 * @return {@code true} if the operation succeeded 2486 * 2487 * @deprecated 2488 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2489 * mechanism to trigger connection to a Wi-Fi network. 2490 * b) See {@link #addNetworkSuggestions(List)}, 2491 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2492 * when auto-connecting to wifi. 2493 * <b>Compatibility Note:</b> For applications targeting 2494 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 2495 * {@code false}. 2496 * Deprecation Exemptions: 2497 * <ul> 2498 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2499 * </ul> 2500 */ 2501 @Deprecated enableNetwork(int netId, boolean attemptConnect)2502 public boolean enableNetwork(int netId, boolean attemptConnect) { 2503 try { 2504 return mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName()); 2505 } catch (RemoteException e) { 2506 throw e.rethrowFromSystemServer(); 2507 } 2508 } 2509 2510 /** 2511 * Disable a configured network. The specified network will not be 2512 * a candidate for associating. This may result in the asynchronous 2513 * delivery of state change events. 2514 * 2515 * Applications are not allowed to disable networks created by other 2516 * applications. 2517 * 2518 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 2519 * #getConfiguredNetworks}. 2520 * @return {@code true} if the operation succeeded 2521 * 2522 * @deprecated 2523 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2524 * mechanism to trigger connection to a Wi-Fi network. 2525 * b) See {@link #addNetworkSuggestions(List)}, 2526 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2527 * when auto-connecting to wifi. 2528 * <b>Compatibility Note:</b> For applications targeting 2529 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 2530 * {@code false}. 2531 * <p> 2532 * Deprecation Exemptions: 2533 * <ul> 2534 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2535 * </ul> 2536 */ 2537 @Deprecated disableNetwork(int netId)2538 public boolean disableNetwork(int netId) { 2539 try { 2540 return mService.disableNetwork(netId, mContext.getOpPackageName()); 2541 } catch (RemoteException e) { 2542 throw e.rethrowFromSystemServer(); 2543 } 2544 } 2545 2546 /** 2547 * Disassociate from the currently active access point. This may result 2548 * in the asynchronous delivery of state change events. 2549 * @return {@code true} if the operation succeeded 2550 * 2551 * @deprecated 2552 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2553 * mechanism to trigger connection to a Wi-Fi network. 2554 * b) See {@link #addNetworkSuggestions(List)}, 2555 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2556 * when auto-connecting to wifi. 2557 * <b>Compatibility Note:</b> For applications targeting 2558 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 2559 * {@code false}. 2560 * <p> 2561 * Deprecation Exemptions: 2562 * <ul> 2563 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2564 * </ul> 2565 */ 2566 @Deprecated disconnect()2567 public boolean disconnect() { 2568 try { 2569 return mService.disconnect(mContext.getOpPackageName()); 2570 } catch (RemoteException e) { 2571 throw e.rethrowFromSystemServer(); 2572 } 2573 } 2574 2575 /** 2576 * Reconnect to the currently active access point, if we are currently 2577 * disconnected. This may result in the asynchronous delivery of state 2578 * change events. 2579 * @return {@code true} if the operation succeeded 2580 * 2581 * @deprecated 2582 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2583 * mechanism to trigger connection to a Wi-Fi network. 2584 * b) See {@link #addNetworkSuggestions(List)}, 2585 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2586 * when auto-connecting to wifi. 2587 * <b>Compatibility Note:</b> For applications targeting 2588 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 2589 * {@code false}. 2590 * <p> 2591 * Deprecation Exemptions: 2592 * <ul> 2593 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2594 * </ul> 2595 */ 2596 @Deprecated reconnect()2597 public boolean reconnect() { 2598 try { 2599 return mService.reconnect(mContext.getOpPackageName()); 2600 } catch (RemoteException e) { 2601 throw e.rethrowFromSystemServer(); 2602 } 2603 } 2604 2605 /** 2606 * Reconnect to the currently active access point, even if we are already 2607 * connected. This may result in the asynchronous delivery of state 2608 * change events. 2609 * @return {@code true} if the operation succeeded 2610 * 2611 * @deprecated 2612 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2613 * mechanism to trigger connection to a Wi-Fi network. 2614 * b) See {@link #addNetworkSuggestions(List)}, 2615 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2616 * when auto-connecting to wifi. 2617 * <b>Compatibility Note:</b> For applications targeting 2618 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. 2619 */ 2620 @Deprecated reassociate()2621 public boolean reassociate() { 2622 try { 2623 return mService.reassociate(mContext.getOpPackageName()); 2624 } catch (RemoteException e) { 2625 throw e.rethrowFromSystemServer(); 2626 } 2627 } 2628 2629 /** 2630 * Check that the supplicant daemon is responding to requests. 2631 * @return {@code true} if we were able to communicate with the supplicant and 2632 * it returned the expected response to the PING message. 2633 * @deprecated Will return the output of {@link #isWifiEnabled()} instead. 2634 */ 2635 @Deprecated pingSupplicant()2636 public boolean pingSupplicant() { 2637 return isWifiEnabled(); 2638 } 2639 2640 /** TODO(b/181364583): Convert all of these to 1 << X form. */ 2641 /** @hide */ 2642 public static final long WIFI_FEATURE_INFRA = 0x0001L; // Basic infrastructure mode 2643 /** @hide */ 2644 public static final long WIFI_FEATURE_PASSPOINT = 0x0004L; // Support for GAS/ANQP 2645 /** @hide */ 2646 public static final long WIFI_FEATURE_P2P = 0x0008L; // Wifi-Direct 2647 /** @hide */ 2648 public static final long WIFI_FEATURE_MOBILE_HOTSPOT = 0x0010L; // Soft AP 2649 /** @hide */ 2650 public static final long WIFI_FEATURE_SCANNER = 0x0020L; // WifiScanner APIs 2651 /** @hide */ 2652 public static final long WIFI_FEATURE_AWARE = 0x0040L; // Wi-Fi AWare networking 2653 /** @hide */ 2654 public static final long WIFI_FEATURE_D2D_RTT = 0x0080L; // Device-to-device RTT 2655 /** @hide */ 2656 public static final long WIFI_FEATURE_D2AP_RTT = 0x0100L; // Device-to-AP RTT 2657 /** @hide */ 2658 public static final long WIFI_FEATURE_BATCH_SCAN = 0x0200L; // Batched Scan (deprecated) 2659 /** @hide */ 2660 public static final long WIFI_FEATURE_PNO = 0x0400L; // Preferred network offload 2661 /** @hide */ 2662 public static final long WIFI_FEATURE_ADDITIONAL_STA = 0x0800L; // (unused) 2663 /** @hide */ 2664 public static final long WIFI_FEATURE_TDLS = 0x1000L; // Tunnel directed link setup 2665 /** @hide */ 2666 public static final long WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000L; // TDLS off channel 2667 /** @hide */ 2668 public static final long WIFI_FEATURE_EPR = 0x4000L; // Enhanced power reporting 2669 /** @hide */ 2670 public static final long WIFI_FEATURE_AP_STA = 0x8000L; // AP STA Concurrency 2671 /** @hide */ 2672 public static final long WIFI_FEATURE_LINK_LAYER_STATS = 0x10000L; // Link layer stats 2673 /** @hide */ 2674 public static final long WIFI_FEATURE_LOGGER = 0x20000L; // WiFi Logger 2675 /** @hide */ 2676 public static final long WIFI_FEATURE_HAL_EPNO = 0x40000L; // Enhanced PNO 2677 /** @hide */ 2678 public static final long WIFI_FEATURE_RSSI_MONITOR = 0x80000L; // RSSI Monitor 2679 /** @hide */ 2680 public static final long WIFI_FEATURE_MKEEP_ALIVE = 0x100000L; // mkeep_alive 2681 /** @hide */ 2682 public static final long WIFI_FEATURE_CONFIG_NDO = 0x200000L; // ND offload 2683 /** @hide */ 2684 public static final long WIFI_FEATURE_TRANSMIT_POWER = 0x400000L; // Capture transmit power 2685 /** @hide */ 2686 public static final long WIFI_FEATURE_CONTROL_ROAMING = 0x800000L; // Control firmware roaming 2687 /** @hide */ 2688 public static final long WIFI_FEATURE_IE_WHITELIST = 0x1000000L; // Probe IE white listing 2689 /** @hide */ 2690 public static final long WIFI_FEATURE_SCAN_RAND = 0x2000000L; // Random MAC & Probe seq 2691 /** @hide */ 2692 public static final long WIFI_FEATURE_TX_POWER_LIMIT = 0x4000000L; // Set Tx power limit 2693 /** @hide */ 2694 public static final long WIFI_FEATURE_WPA3_SAE = 0x8000000L; // WPA3-Personal SAE 2695 /** @hide */ 2696 public static final long WIFI_FEATURE_WPA3_SUITE_B = 0x10000000L; // WPA3-Enterprise Suite-B 2697 /** @hide */ 2698 public static final long WIFI_FEATURE_OWE = 0x20000000L; // Enhanced Open 2699 /** @hide */ 2700 public static final long WIFI_FEATURE_LOW_LATENCY = 0x40000000L; // Low Latency modes 2701 /** @hide */ 2702 public static final long WIFI_FEATURE_DPP = 0x80000000L; // DPP (Easy-Connect) 2703 /** @hide */ 2704 public static final long WIFI_FEATURE_P2P_RAND_MAC = 0x100000000L; // Random P2P MAC 2705 /** @hide */ 2706 public static final long WIFI_FEATURE_CONNECTED_RAND_MAC = 0x200000000L; // Random STA MAC 2707 /** @hide */ 2708 public static final long WIFI_FEATURE_AP_RAND_MAC = 0x400000000L; // Random AP MAC 2709 /** @hide */ 2710 public static final long WIFI_FEATURE_MBO = 0x800000000L; // MBO Support 2711 /** @hide */ 2712 public static final long WIFI_FEATURE_OCE = 0x1000000000L; // OCE Support 2713 /** @hide */ 2714 public static final long WIFI_FEATURE_WAPI = 0x2000000000L; // WAPI 2715 2716 /** @hide */ 2717 public static final long WIFI_FEATURE_FILS_SHA256 = 0x4000000000L; // FILS-SHA256 2718 2719 /** @hide */ 2720 public static final long WIFI_FEATURE_FILS_SHA384 = 0x8000000000L; // FILS-SHA384 2721 2722 /** @hide */ 2723 public static final long WIFI_FEATURE_SAE_PK = 0x10000000000L; // SAE-PK 2724 2725 /** @hide */ 2726 public static final long WIFI_FEATURE_STA_BRIDGED_AP = 0x20000000000L; // STA + Bridged AP 2727 2728 /** @hide */ 2729 public static final long WIFI_FEATURE_BRIDGED_AP = 0x40000000000L; // Bridged AP 2730 2731 /** @hide */ 2732 public static final long WIFI_FEATURE_INFRA_60G = 0x80000000000L; // 60 GHz Band Support 2733 2734 /** 2735 * Support for 2 STA's for the local-only (peer to peer) connection + internet connection 2736 * concurrency. 2737 * @hide 2738 */ 2739 public static final long WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 0x100000000000L; 2740 2741 /** 2742 * Support for 2 STA's for the make before break concurrency. 2743 * @hide 2744 */ 2745 public static final long WIFI_FEATURE_ADDITIONAL_STA_MBB = 0x200000000000L; 2746 2747 /** 2748 * Support for 2 STA's for the restricted connection + internet connection concurrency. 2749 * @hide 2750 */ 2751 public static final long WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 0x400000000000L; 2752 2753 /** 2754 * DPP (Easy-Connect) Enrollee Responder mode support 2755 * @hide 2756 */ 2757 public static final long WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 0x800000000000L; 2758 2759 /** 2760 * Passpoint Terms and Conditions feature support 2761 * @hide 2762 */ 2763 public static final long WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 0x1000000000000L; 2764 2765 /** @hide */ 2766 public static final long WIFI_FEATURE_SAE_H2E = 0x2000000000000L; // Hash-to-Element 2767 2768 /** @hide */ 2769 public static final long WIFI_FEATURE_WFD_R2 = 0x4000000000000L; // Wi-Fi Display R2 2770 2771 /** 2772 * RFC 7542 decorated identity support 2773 * @hide */ 2774 public static final long WIFI_FEATURE_DECORATED_IDENTITY = 0x8000000000000L; 2775 getSupportedFeatures()2776 private long getSupportedFeatures() { 2777 try { 2778 return mService.getSupportedFeatures(); 2779 } catch (RemoteException e) { 2780 throw e.rethrowFromSystemServer(); 2781 } 2782 } 2783 isFeatureSupported(long feature)2784 private boolean isFeatureSupported(long feature) { 2785 return (getSupportedFeatures() & feature) == feature; 2786 } 2787 2788 /** 2789 * @return true if this adapter supports Passpoint 2790 * @hide 2791 */ isPasspointSupported()2792 public boolean isPasspointSupported() { 2793 return isFeatureSupported(WIFI_FEATURE_PASSPOINT); 2794 } 2795 2796 /** 2797 * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct) 2798 */ isP2pSupported()2799 public boolean isP2pSupported() { 2800 return isFeatureSupported(WIFI_FEATURE_P2P); 2801 } 2802 2803 /** 2804 * @return true if this adapter supports portable Wi-Fi hotspot 2805 * @hide 2806 */ 2807 @SystemApi isPortableHotspotSupported()2808 public boolean isPortableHotspotSupported() { 2809 return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT); 2810 } 2811 2812 /** 2813 * @return true if this adapter supports WifiScanner APIs 2814 * @hide 2815 */ 2816 @SystemApi isWifiScannerSupported()2817 public boolean isWifiScannerSupported() { 2818 return isFeatureSupported(WIFI_FEATURE_SCANNER); 2819 } 2820 2821 /** 2822 * @return true if this adapter supports Neighbour Awareness Network APIs 2823 * @hide 2824 */ isWifiAwareSupported()2825 public boolean isWifiAwareSupported() { 2826 return isFeatureSupported(WIFI_FEATURE_AWARE); 2827 } 2828 2829 /** 2830 * Query whether or not the device supports Station (STA) + Access point (AP) concurrency. 2831 * 2832 * @return true if this device supports STA + AP concurrency, false otherwise. 2833 */ isStaApConcurrencySupported()2834 public boolean isStaApConcurrencySupported() { 2835 return isFeatureSupported(WIFI_FEATURE_AP_STA); 2836 } 2837 2838 /** 2839 * Query whether or not the device supports concurrent station (STA) connections for local-only 2840 * connections using {@link WifiNetworkSpecifier}. 2841 * 2842 * @return true if this device supports multiple STA concurrency for this use-case, false 2843 * otherwise. 2844 */ isStaConcurrencyForLocalOnlyConnectionsSupported()2845 public boolean isStaConcurrencyForLocalOnlyConnectionsSupported() { 2846 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY); 2847 } 2848 2849 /** 2850 * Query whether or not the device supports concurrent station (STA) connections for 2851 * make-before-break wifi to wifi switching. 2852 * 2853 * Note: This is an internal feature which is not available to apps. 2854 * 2855 * @return true if this device supports multiple STA concurrency for this use-case, false 2856 * otherwise. 2857 */ isMakeBeforeBreakWifiSwitchingSupported()2858 public boolean isMakeBeforeBreakWifiSwitchingSupported() { 2859 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_MBB); 2860 } 2861 2862 /** 2863 * Query whether or not the device supports concurrent station (STA) connections for restricted 2864 * connections using {@link WifiNetworkSuggestion.Builder#setOemPaid(boolean)} / 2865 * {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)}. 2866 * 2867 * @return true if this device supports multiple STA concurrency for this use-case, false 2868 * otherwise. 2869 * @hide 2870 */ 2871 @SystemApi isStaConcurrencyForRestrictedConnectionsSupported()2872 public boolean isStaConcurrencyForRestrictedConnectionsSupported() { 2873 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED); 2874 } 2875 2876 /** 2877 * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)} 2878 * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT} and 2879 * {@link android.content.pm.PackageManager#FEATURE_WIFI_AWARE}. 2880 * 2881 * @return true if this adapter supports Device-to-device RTT 2882 * @hide 2883 */ 2884 @Deprecated 2885 @SystemApi isDeviceToDeviceRttSupported()2886 public boolean isDeviceToDeviceRttSupported() { 2887 return isFeatureSupported(WIFI_FEATURE_D2D_RTT); 2888 } 2889 2890 /** 2891 * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)} 2892 * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT}. 2893 * 2894 * @return true if this adapter supports Device-to-AP RTT 2895 */ 2896 @Deprecated isDeviceToApRttSupported()2897 public boolean isDeviceToApRttSupported() { 2898 return isFeatureSupported(WIFI_FEATURE_D2AP_RTT); 2899 } 2900 2901 /** 2902 * @return true if this adapter supports offloaded connectivity scan 2903 */ isPreferredNetworkOffloadSupported()2904 public boolean isPreferredNetworkOffloadSupported() { 2905 return isFeatureSupported(WIFI_FEATURE_PNO); 2906 } 2907 2908 /** 2909 * @return true if this adapter supports Tunnel Directed Link Setup 2910 */ isTdlsSupported()2911 public boolean isTdlsSupported() { 2912 return isFeatureSupported(WIFI_FEATURE_TDLS); 2913 } 2914 2915 /** 2916 * @return true if this adapter supports Off Channel Tunnel Directed Link Setup 2917 * @hide 2918 */ isOffChannelTdlsSupported()2919 public boolean isOffChannelTdlsSupported() { 2920 return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL); 2921 } 2922 2923 /** 2924 * @return true if this adapter supports advanced power/performance counters 2925 */ isEnhancedPowerReportingSupported()2926 public boolean isEnhancedPowerReportingSupported() { 2927 return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS); 2928 } 2929 2930 /** 2931 * @return true if this device supports connected MAC randomization. 2932 * @hide 2933 */ 2934 @SystemApi isConnectedMacRandomizationSupported()2935 public boolean isConnectedMacRandomizationSupported() { 2936 return isFeatureSupported(WIFI_FEATURE_CONNECTED_RAND_MAC); 2937 } 2938 2939 /** 2940 * @return true if this device supports AP MAC randomization. 2941 * @hide 2942 */ 2943 @SystemApi isApMacRandomizationSupported()2944 public boolean isApMacRandomizationSupported() { 2945 return isFeatureSupported(WIFI_FEATURE_AP_RAND_MAC); 2946 } 2947 2948 /** 2949 * Check if the chipset supports 2.4GHz band. 2950 * @return {@code true} if supported, {@code false} otherwise. 2951 */ is24GHzBandSupported()2952 public boolean is24GHzBandSupported() { 2953 try { 2954 return mService.is24GHzBandSupported(); 2955 } catch (RemoteException e) { 2956 throw e.rethrowFromSystemServer(); 2957 } 2958 } 2959 2960 /** 2961 * Check if the chipset supports 5GHz band. 2962 * @return {@code true} if supported, {@code false} otherwise. 2963 */ is5GHzBandSupported()2964 public boolean is5GHzBandSupported() { 2965 try { 2966 return mService.is5GHzBandSupported(); 2967 } catch (RemoteException e) { 2968 throw e.rethrowFromSystemServer(); 2969 } 2970 } 2971 2972 /** 2973 * Check if the chipset supports the 60GHz frequency band. 2974 * 2975 * @return {@code true} if supported, {@code false} otherwise. 2976 */ 2977 @RequiresApi(Build.VERSION_CODES.S) is60GHzBandSupported()2978 public boolean is60GHzBandSupported() { 2979 try { 2980 return mService.is60GHzBandSupported(); 2981 } catch (RemoteException e) { 2982 throw e.rethrowFromSystemServer(); 2983 } 2984 } 2985 2986 /** 2987 * Check if the chipset supports 6GHz band. 2988 * @return {@code true} if supported, {@code false} otherwise. 2989 */ is6GHzBandSupported()2990 public boolean is6GHzBandSupported() { 2991 try { 2992 return mService.is6GHzBandSupported(); 2993 } catch (RemoteException e) { 2994 throw e.rethrowFromSystemServer(); 2995 } 2996 } 2997 2998 /** 2999 * Check if the chipset supports a certain Wi-Fi standard. 3000 * @param standard the IEEE 802.11 standard to check on. 3001 * valid values from {@link ScanResult}'s {@code WIFI_STANDARD_} 3002 * @return {@code true} if supported, {@code false} otherwise. 3003 */ isWifiStandardSupported(@ifiAnnotations.WifiStandard int standard)3004 public boolean isWifiStandardSupported(@WifiAnnotations.WifiStandard int standard) { 3005 try { 3006 return mService.isWifiStandardSupported(standard); 3007 } catch (RemoteException e) { 3008 throw e.rethrowFromSystemServer(); 3009 } 3010 } 3011 3012 /** 3013 * Query whether or not the device supports concurrency of Station (STA) + multiple access 3014 * points (AP) (where the APs bridged together). 3015 * 3016 * See {@link SoftApConfiguration.Builder#setBands(int[])} 3017 * or {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)} to configure 3018 * bridged AP when the bridged AP supported. 3019 * 3020 * @return true if this device supports concurrency of STA + multiple APs which are bridged 3021 * together, false otherwise. 3022 */ isStaBridgedApConcurrencySupported()3023 public boolean isStaBridgedApConcurrencySupported() { 3024 return isFeatureSupported(WIFI_FEATURE_STA_BRIDGED_AP); 3025 } 3026 3027 /** 3028 * Query whether or not the device supports multiple Access point (AP) which are bridged 3029 * together. 3030 * 3031 * See {@link SoftApConfiguration.Builder#setBands(int[])} 3032 * or {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)} to configure 3033 * bridged AP when the bridged AP supported. 3034 * 3035 * @return true if this device supports concurrency of multiple AP which bridged together, 3036 * false otherwise. 3037 */ isBridgedApConcurrencySupported()3038 public boolean isBridgedApConcurrencySupported() { 3039 return isFeatureSupported(WIFI_FEATURE_BRIDGED_AP); 3040 } 3041 3042 /** 3043 * Interface for Wi-Fi activity energy info listener. Should be implemented by applications and 3044 * set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}. 3045 * 3046 * @hide 3047 */ 3048 @SystemApi 3049 public interface OnWifiActivityEnergyInfoListener { 3050 /** 3051 * Called when Wi-Fi activity energy info is available. 3052 * Note: this listener is triggered at most once for each call to 3053 * {@link #getWifiActivityEnergyInfoAsync}. 3054 * 3055 * @param info the latest {@link WifiActivityEnergyInfo}, or null if unavailable. 3056 */ onWifiActivityEnergyInfo(@ullable WifiActivityEnergyInfo info)3057 void onWifiActivityEnergyInfo(@Nullable WifiActivityEnergyInfo info); 3058 } 3059 3060 private static class OnWifiActivityEnergyInfoProxy 3061 extends IOnWifiActivityEnergyInfoListener.Stub { 3062 private final Object mLock = new Object(); 3063 @Nullable @GuardedBy("mLock") private Executor mExecutor; 3064 @Nullable @GuardedBy("mLock") private OnWifiActivityEnergyInfoListener mListener; 3065 OnWifiActivityEnergyInfoProxy(Executor executor, OnWifiActivityEnergyInfoListener listener)3066 OnWifiActivityEnergyInfoProxy(Executor executor, 3067 OnWifiActivityEnergyInfoListener listener) { 3068 mExecutor = executor; 3069 mListener = listener; 3070 } 3071 3072 @Override onWifiActivityEnergyInfo(WifiActivityEnergyInfo info)3073 public void onWifiActivityEnergyInfo(WifiActivityEnergyInfo info) { 3074 Executor executor; 3075 OnWifiActivityEnergyInfoListener listener; 3076 synchronized (mLock) { 3077 if (mExecutor == null || mListener == null) { 3078 return; 3079 } 3080 executor = mExecutor; 3081 listener = mListener; 3082 // null out to allow garbage collection, prevent triggering listener more than once 3083 mExecutor = null; 3084 mListener = null; 3085 } 3086 Binder.clearCallingIdentity(); 3087 executor.execute(() -> listener.onWifiActivityEnergyInfo(info)); 3088 } 3089 } 3090 3091 /** 3092 * Request to get the current {@link WifiActivityEnergyInfo} asynchronously. 3093 * Note: This method will return null if {@link #isEnhancedPowerReportingSupported()} returns 3094 * false. 3095 * 3096 * @param executor the executor that the listener will be invoked on 3097 * @param listener the listener that will receive the {@link WifiActivityEnergyInfo} object 3098 * when it becomes available. The listener will be triggered at most once for 3099 * each call to this method. 3100 * 3101 * @hide 3102 */ 3103 @SystemApi 3104 @RequiresPermission(ACCESS_WIFI_STATE) getWifiActivityEnergyInfoAsync( @onNull @allbackExecutor Executor executor, @NonNull OnWifiActivityEnergyInfoListener listener)3105 public void getWifiActivityEnergyInfoAsync( 3106 @NonNull @CallbackExecutor Executor executor, 3107 @NonNull OnWifiActivityEnergyInfoListener listener) { 3108 Objects.requireNonNull(executor, "executor cannot be null"); 3109 Objects.requireNonNull(listener, "listener cannot be null"); 3110 try { 3111 mService.getWifiActivityEnergyInfoAsync( 3112 new OnWifiActivityEnergyInfoProxy(executor, listener)); 3113 } catch (RemoteException e) { 3114 throw e.rethrowFromSystemServer(); 3115 } 3116 } 3117 3118 /** 3119 * Request a scan for access points. Returns immediately. The availability 3120 * of the results is made known later by means of an asynchronous event sent 3121 * on completion of the scan. 3122 * <p> 3123 * To initiate a Wi-Fi scan, declare the 3124 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} 3125 * permission in the manifest, and perform these steps: 3126 * </p> 3127 * <ol style="1"> 3128 * <li>Invoke the following method: 3129 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).startScan()}</li> 3130 * <li> 3131 * Register a BroadcastReceiver to listen to 3132 * {@code SCAN_RESULTS_AVAILABLE_ACTION}.</li> 3133 * <li>When a broadcast is received, call: 3134 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).getScanResults()}</li> 3135 * </ol> 3136 * @return {@code true} if the operation succeeded, i.e., the scan was initiated. 3137 * @deprecated The ability for apps to trigger scan requests will be removed in a future 3138 * release. 3139 */ 3140 @Deprecated startScan()3141 public boolean startScan() { 3142 return startScan(null); 3143 } 3144 3145 /** @hide */ 3146 @SystemApi 3147 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) startScan(WorkSource workSource)3148 public boolean startScan(WorkSource workSource) { 3149 try { 3150 String packageName = mContext.getOpPackageName(); 3151 String attributionTag = mContext.getAttributionTag(); 3152 return mService.startScan(packageName, attributionTag); 3153 } catch (RemoteException e) { 3154 throw e.rethrowFromSystemServer(); 3155 } 3156 } 3157 3158 /** 3159 * WPS has been deprecated from Client mode operation. 3160 * 3161 * @return null 3162 * @hide 3163 * @deprecated This API is deprecated 3164 */ getCurrentNetworkWpsNfcConfigurationToken()3165 public String getCurrentNetworkWpsNfcConfigurationToken() { 3166 return null; 3167 } 3168 3169 /** 3170 * Return dynamic information about the current Wi-Fi connection, if any is active. 3171 * <p> 3172 * 3173 * @return the Wi-Fi information, contained in {@link WifiInfo}. 3174 * 3175 * @deprecated Starting with {@link Build.VERSION_CODES#S}, WifiInfo retrieval is moved to 3176 * {@link ConnectivityManager} API surface. WifiInfo is attached in 3177 * {@link NetworkCapabilities#getTransportInfo()} which is available via callback in 3178 * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} or on-demand from 3179 * {@link ConnectivityManager#getNetworkCapabilities(Network)}. 3180 * 3181 *</p> 3182 * Usage example: 3183 * <pre>{@code 3184 * final NetworkRequest request = 3185 * new NetworkRequest.Builder() 3186 * .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 3187 * .build(); 3188 * final ConnectivityManager connectivityManager = 3189 * context.getSystemService(ConnectivityManager.class); 3190 * final NetworkCallback networkCallback = new NetworkCallback() { 3191 * ... 3192 * {@literal @}Override 3193 * void onAvailable(Network network) {} 3194 * 3195 * {@literal @}Override 3196 * void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { 3197 * WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo(); 3198 * } 3199 * // etc. 3200 * }; 3201 * connectivityManager.requestNetwork(request, networkCallback); // For request 3202 * connectivityManager.registerNetworkCallback(request, networkCallback); // For listen 3203 * }</pre> 3204 * <p> 3205 * <b>Compatibility Notes:</b> 3206 * <li>Apps can continue using this API, however newer features 3207 * such as ability to mask out location sensitive data in WifiInfo will not be supported 3208 * via this API. </li> 3209 * <li>On devices supporting concurrent connections (indicated via 3210 * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc) this API will return 3211 * the details of the internet providing connection (if any) to all apps, except for the apps 3212 * that triggered the creation of the concurrent connection. For such apps, this API will return 3213 * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will 3214 * trigger a concurrent connection on supported devices and hence this API will provide 3215 * details of their peer to peer connection (not the internet providing connection). This 3216 * is to maintain backwards compatibility with behavior on single STA devices.</li> 3217 * </p> 3218 */ 3219 @Deprecated getConnectionInfo()3220 public WifiInfo getConnectionInfo() { 3221 try { 3222 return mService.getConnectionInfo(mContext.getOpPackageName(), 3223 mContext.getAttributionTag()); 3224 } catch (RemoteException e) { 3225 throw e.rethrowFromSystemServer(); 3226 } 3227 } 3228 3229 /** 3230 * Return the results of the latest access point scan. 3231 * @return the list of access points found in the most recent scan. An app must hold 3232 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission 3233 * in order to get valid results. 3234 */ getScanResults()3235 public List<ScanResult> getScanResults() { 3236 try { 3237 return mService.getScanResults(mContext.getOpPackageName(), 3238 mContext.getAttributionTag()); 3239 } catch (RemoteException e) { 3240 throw e.rethrowFromSystemServer(); 3241 } 3242 } 3243 3244 /** 3245 * Get the filtered ScanResults which match the network configurations specified by the 3246 * {@code networkSuggestionsToMatch}. Suggestions which use {@link WifiConfiguration} use 3247 * SSID and the security type to match. Suggestions which use {@link PasspointConfigration} 3248 * use the matching rules of Hotspot 2.0. 3249 * @param networkSuggestionsToMatch The list of {@link WifiNetworkSuggestion} to match against. 3250 * These may or may not be suggestions which are installed on the device. 3251 * @param scanResults The scan results to be filtered. Optional - if not provided(empty list), 3252 * the Wi-Fi service will use the most recent scan results which the system has. 3253 * @return The map of {@link WifiNetworkSuggestion} to the list of {@link ScanResult} 3254 * corresponding to networks which match them. 3255 * @hide 3256 */ 3257 @SystemApi 3258 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) 3259 @NonNull getMatchingScanResults( @onNull List<WifiNetworkSuggestion> networkSuggestionsToMatch, @Nullable List<ScanResult> scanResults)3260 public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( 3261 @NonNull List<WifiNetworkSuggestion> networkSuggestionsToMatch, 3262 @Nullable List<ScanResult> scanResults) { 3263 if (networkSuggestionsToMatch == null) { 3264 throw new IllegalArgumentException("networkSuggestions must not be null."); 3265 } 3266 try { 3267 return mService.getMatchingScanResults( 3268 networkSuggestionsToMatch, scanResults, 3269 mContext.getOpPackageName(), mContext.getAttributionTag()); 3270 } catch (RemoteException e) { 3271 throw e.rethrowFromSystemServer(); 3272 } 3273 } 3274 3275 /** 3276 * Set if scanning is always available. 3277 * 3278 * If set to {@code true}, apps can issue {@link #startScan} and fetch scan results 3279 * even when Wi-Fi is turned off. 3280 * 3281 * @param isAvailable true to enable, false to disable. 3282 * @hide 3283 * @see #isScanAlwaysAvailable() 3284 */ 3285 @SystemApi 3286 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setScanAlwaysAvailable(boolean isAvailable)3287 public void setScanAlwaysAvailable(boolean isAvailable) { 3288 try { 3289 mService.setScanAlwaysAvailable(isAvailable, mContext.getOpPackageName()); 3290 } catch (RemoteException e) { 3291 throw e.rethrowFromSystemServer(); 3292 } 3293 } 3294 3295 /** 3296 * Check if scanning is always available. 3297 * 3298 * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results 3299 * even when Wi-Fi is turned off. 3300 * 3301 * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}. 3302 * @deprecated The ability for apps to trigger scan requests will be removed in a future 3303 * release. 3304 */ 3305 @Deprecated isScanAlwaysAvailable()3306 public boolean isScanAlwaysAvailable() { 3307 try { 3308 return mService.isScanAlwaysAvailable(); 3309 } catch (RemoteException e) { 3310 throw e.rethrowFromSystemServer(); 3311 } 3312 } 3313 3314 /** 3315 * Tell the device to persist the current list of configured networks. 3316 * <p> 3317 * Note: It is possible for this method to change the network IDs of 3318 * existing networks. You should assume the network IDs can be different 3319 * after calling this method. 3320 * 3321 * @return {@code false}. 3322 * @deprecated There is no need to call this method - 3323 * {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)} 3324 * and {@link #removeNetwork(int)} already persist the configurations automatically. 3325 */ 3326 @Deprecated saveConfiguration()3327 public boolean saveConfiguration() { 3328 return false; 3329 } 3330 3331 /** 3332 * Get the country code as resolved by the Wi-Fi framework. 3333 * The Wi-Fi framework uses multiple sources to resolve a country code 3334 * - in order of priority (high to low): 3335 * 1. Override country code set by {@link WifiManager#setOverrideCountryCode(String)} 3336 * and cleared by {@link WifiManager#clearOverrideCountryCode()}. Typically only used 3337 * for testing. 3338 * 2. Country code supplied by the telephony module. Typically provided from the 3339 * current network or from emergency cell information. 3340 * 3. Default country code set either via {@code ro.boot.wificountrycode} 3341 * or the {@link WifiManager#setDefaultCountryCode(String)}. 3342 * 3343 * @return the country code in ISO 3166 alpha-2 (2-letter) upper format, 3344 * or null if there is no country code configured. 3345 * 3346 * @hide 3347 */ 3348 @Nullable 3349 @SystemApi 3350 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) getCountryCode()3351 public String getCountryCode() { 3352 try { 3353 return mService.getCountryCode(); 3354 } catch (RemoteException e) { 3355 throw e.rethrowFromSystemServer(); 3356 } 3357 } 3358 3359 /** 3360 * Set the override country code - may be used for testing. See the country code resolution 3361 * order and format in {@link #getCountryCode()}. 3362 * @param country A 2-Character alphanumeric country code. 3363 * @see #getCountryCode(). 3364 * 3365 * @hide 3366 */ 3367 @RequiresApi(Build.VERSION_CODES.S) 3368 @SystemApi 3369 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) setOverrideCountryCode(@onNull String country)3370 public void setOverrideCountryCode(@NonNull String country) { 3371 try { 3372 mService.setOverrideCountryCode(country); 3373 } catch (RemoteException e) { 3374 throw e.rethrowFromSystemServer(); 3375 } 3376 } 3377 3378 /** 3379 * This clears the override country code which was previously set by 3380 * {@link WifiManager#setOverrideCountryCode(String)} method. 3381 * @see #getCountryCode(). 3382 * 3383 * @hide 3384 */ 3385 @RequiresApi(Build.VERSION_CODES.S) 3386 @SystemApi 3387 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) clearOverrideCountryCode()3388 public void clearOverrideCountryCode() { 3389 try { 3390 mService.clearOverrideCountryCode(); 3391 } catch (RemoteException e) { 3392 throw e.rethrowFromSystemServer(); 3393 } 3394 } 3395 /** 3396 * Used to configure the default country code. See {@link #getCountryCode()} for resolution 3397 * method of the country code. 3398 * @param country A 2-character alphanumeric country code. 3399 * @see #getCountryCode(). 3400 * 3401 * @hide 3402 */ 3403 @RequiresApi(Build.VERSION_CODES.S) 3404 @SystemApi 3405 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) setDefaultCountryCode(@onNull String country)3406 public void setDefaultCountryCode(@NonNull String country) { 3407 try { 3408 mService.setDefaultCountryCode(country); 3409 } catch (RemoteException e) { 3410 throw e.rethrowFromSystemServer(); 3411 } 3412 } 3413 3414 /** 3415 * Return the DHCP-assigned addresses from the last successful DHCP request, 3416 * if any. 3417 * 3418 * @return the DHCP information 3419 * 3420 * @deprecated Use the methods on {@link android.net.LinkProperties} which can be obtained 3421 * either via {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)} or 3422 * {@link ConnectivityManager#getLinkProperties(Network)}. 3423 * 3424 * <p> 3425 * <b>Compatibility Notes:</b> 3426 * <li>On devices supporting concurrent connections (indicated via 3427 * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc), this API will return 3428 * the details of the internet providing connection (if any) to all apps, except for the apps 3429 * that triggered the creation of the concurrent connection. For such apps, this API will return 3430 * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will 3431 * trigger a concurrent connection on supported devices and hence this API will provide 3432 * details of their peer to peer connection (not the internet providing connection). This 3433 * is to maintain backwards compatibility with behavior on single STA devices.</li> 3434 * </p> 3435 */ 3436 @Deprecated getDhcpInfo()3437 public DhcpInfo getDhcpInfo() { 3438 try { 3439 return mService.getDhcpInfo(mContext.getOpPackageName()); 3440 } catch (RemoteException e) { 3441 throw e.rethrowFromSystemServer(); 3442 } 3443 } 3444 3445 /** 3446 * Enable or disable Wi-Fi. 3447 * <p> 3448 * Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE} 3449 * permission to toggle wifi. 3450 * 3451 * @param enabled {@code true} to enable, {@code false} to disable. 3452 * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is 3453 * either already in the requested state, or in progress toward the requested state. 3454 * @throws {@link java.lang.SecurityException} if the caller is missing required permissions. 3455 * 3456 * @deprecated Starting with Build.VERSION_CODES#Q, applications are not allowed to 3457 * enable/disable Wi-Fi. 3458 * <b>Compatibility Note:</b> For applications targeting 3459 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3460 * {@code false}. If apps are targeting an older SDK ({@link android.os.Build.VERSION_CODES#P} 3461 * or below), they can continue to use this API. 3462 * <p> 3463 * Deprecation Exemptions: 3464 * <ul> 3465 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3466 * </ul> 3467 */ 3468 @Deprecated setWifiEnabled(boolean enabled)3469 public boolean setWifiEnabled(boolean enabled) { 3470 try { 3471 return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); 3472 } catch (RemoteException e) { 3473 throw e.rethrowFromSystemServer(); 3474 } 3475 } 3476 3477 /** 3478 * Abstract callback class for applications to receive updates about the Wi-Fi subsystem 3479 * restarting. The Wi-Fi subsystem can restart due to internal recovery mechanisms or via user 3480 * action. 3481 */ 3482 @RequiresApi(Build.VERSION_CODES.S) 3483 public abstract static class SubsystemRestartTrackingCallback { 3484 private final SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy mProxy; 3485 SubsystemRestartTrackingCallback()3486 public SubsystemRestartTrackingCallback() { 3487 mProxy = new SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy(); 3488 } 3489 3490 /*package*/ @NonNull getProxy()3491 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy getProxy() { 3492 return mProxy; 3493 } 3494 3495 /** 3496 * Indicates that the Wi-Fi subsystem is about to restart. 3497 */ onSubsystemRestarting()3498 public abstract void onSubsystemRestarting(); 3499 3500 /** 3501 * Indicates that the Wi-Fi subsystem has restarted. 3502 */ onSubsystemRestarted()3503 public abstract void onSubsystemRestarted(); 3504 3505 private static class SubsystemRestartCallbackProxy extends ISubsystemRestartCallback.Stub { 3506 private final Object mLock = new Object(); 3507 @Nullable 3508 @GuardedBy("mLock") 3509 private Executor mExecutor; 3510 @Nullable 3511 @GuardedBy("mLock") 3512 private SubsystemRestartTrackingCallback mCallback; 3513 SubsystemRestartCallbackProxy()3514 SubsystemRestartCallbackProxy() { 3515 mExecutor = null; 3516 mCallback = null; 3517 } 3518 initProxy(@onNull Executor executor, @NonNull SubsystemRestartTrackingCallback callback)3519 /*package*/ void initProxy(@NonNull Executor executor, 3520 @NonNull SubsystemRestartTrackingCallback callback) { 3521 synchronized (mLock) { 3522 mExecutor = executor; 3523 mCallback = callback; 3524 } 3525 } 3526 cleanUpProxy()3527 /*package*/ void cleanUpProxy() { 3528 synchronized (mLock) { 3529 mExecutor = null; 3530 mCallback = null; 3531 } 3532 } 3533 3534 @Override onSubsystemRestarting()3535 public void onSubsystemRestarting() { 3536 Executor executor; 3537 SubsystemRestartTrackingCallback callback; 3538 synchronized (mLock) { 3539 executor = mExecutor; 3540 callback = mCallback; 3541 } 3542 if (executor == null || callback == null) { 3543 return; 3544 } 3545 Binder.clearCallingIdentity(); 3546 executor.execute(callback::onSubsystemRestarting); 3547 } 3548 3549 @Override onSubsystemRestarted()3550 public void onSubsystemRestarted() { 3551 Executor executor; 3552 SubsystemRestartTrackingCallback callback; 3553 synchronized (mLock) { 3554 executor = mExecutor; 3555 callback = mCallback; 3556 } 3557 if (executor == null || callback == null) { 3558 return; 3559 } 3560 Binder.clearCallingIdentity(); 3561 executor.execute(callback::onSubsystemRestarted); 3562 } 3563 } 3564 } 3565 3566 /** 3567 * Registers a {@link SubsystemRestartTrackingCallback} to listen to Wi-Fi subsystem restarts. 3568 * The subsystem may restart due to internal recovery mechanisms or via user action. 3569 * 3570 * @see #unregisterSubsystemRestartTrackingCallback(SubsystemRestartTrackingCallback) 3571 * 3572 * @param executor Executor to execute callback on 3573 * @param callback {@link SubsystemRestartTrackingCallback} to register 3574 */ 3575 @RequiresApi(Build.VERSION_CODES.S) 3576 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) registerSubsystemRestartTrackingCallback( @onNull @allbackExecutor Executor executor, @NonNull SubsystemRestartTrackingCallback callback)3577 public void registerSubsystemRestartTrackingCallback( 3578 @NonNull @CallbackExecutor Executor executor, 3579 @NonNull SubsystemRestartTrackingCallback callback) { 3580 if (executor == null) throw new IllegalArgumentException("executor must not be null"); 3581 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 3582 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy(); 3583 proxy.initProxy(executor, callback); 3584 try { 3585 mService.registerSubsystemRestartCallback(proxy); 3586 } catch (RemoteException e) { 3587 proxy.cleanUpProxy(); 3588 throw e.rethrowFromSystemServer(); 3589 } 3590 } 3591 3592 /** 3593 * Unregisters a {@link SubsystemRestartTrackingCallback} registered with 3594 * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)} 3595 * 3596 * @param callback {@link SubsystemRestartTrackingCallback} to unregister 3597 */ 3598 @RequiresApi(Build.VERSION_CODES.S) 3599 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) unregisterSubsystemRestartTrackingCallback( @onNull SubsystemRestartTrackingCallback callback)3600 public void unregisterSubsystemRestartTrackingCallback( 3601 @NonNull SubsystemRestartTrackingCallback callback) { 3602 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 3603 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy(); 3604 try { 3605 mService.unregisterSubsystemRestartCallback(proxy); 3606 } catch (RemoteException e) { 3607 throw e.rethrowFromSystemServer(); 3608 } finally { 3609 proxy.cleanUpProxy(); 3610 } 3611 } 3612 3613 /** 3614 * Restart the Wi-Fi subsystem. 3615 * 3616 * Restarts the Wi-Fi subsystem - effectively disabling it and re-enabling it. All existing 3617 * Access Point (AP) associations are torn down, all Soft APs are disabled, Wi-Fi Direct and 3618 * Wi-Fi Aware are disabled. 3619 * 3620 * The state of the system after restart is not guaranteed to match its state before the API is 3621 * called - for instance the device may associate to a different Access Point (AP), and tethered 3622 * hotspots may or may not be restored. 3623 * 3624 * Use the 3625 * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)} 3626 * to track the operation. 3627 * 3628 * @hide 3629 */ 3630 @RequiresApi(Build.VERSION_CODES.S) 3631 @SystemApi 3632 @RequiresPermission(android.Manifest.permission.RESTART_WIFI_SUBSYSTEM) restartWifiSubsystem()3633 public void restartWifiSubsystem() { 3634 try { 3635 mService.restartWifiSubsystem(); 3636 } catch (RemoteException e) { 3637 throw e.rethrowFromSystemServer(); 3638 } 3639 } 3640 3641 /** 3642 * Gets the Wi-Fi enabled state. 3643 * @return One of {@link #WIFI_STATE_DISABLED}, 3644 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 3645 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 3646 * @see #isWifiEnabled() 3647 */ getWifiState()3648 public int getWifiState() { 3649 try { 3650 return mService.getWifiEnabledState(); 3651 } catch (RemoteException e) { 3652 throw e.rethrowFromSystemServer(); 3653 } 3654 } 3655 3656 /** 3657 * Return whether Wi-Fi is enabled or disabled. 3658 * @return {@code true} if Wi-Fi is enabled 3659 * @see #getWifiState() 3660 */ isWifiEnabled()3661 public boolean isWifiEnabled() { 3662 return getWifiState() == WIFI_STATE_ENABLED; 3663 } 3664 3665 /** 3666 * Calculates the level of the signal. This should be used any time a signal 3667 * is being shown. 3668 * 3669 * @param rssi The power of the signal measured in RSSI. 3670 * @param numLevels The number of levels to consider in the calculated level. 3671 * @return A level of the signal, given in the range of 0 to numLevels-1 (both inclusive). 3672 * @deprecated Callers should use {@link #calculateSignalLevel(int)} instead to get the 3673 * signal level using the system default RSSI thresholds, or otherwise compute the RSSI level 3674 * themselves using their own formula. 3675 */ 3676 @Deprecated calculateSignalLevel(int rssi, int numLevels)3677 public static int calculateSignalLevel(int rssi, int numLevels) { 3678 if (rssi <= MIN_RSSI) { 3679 return 0; 3680 } else if (rssi >= MAX_RSSI) { 3681 return numLevels - 1; 3682 } else { 3683 float inputRange = (MAX_RSSI - MIN_RSSI); 3684 float outputRange = (numLevels - 1); 3685 return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange); 3686 } 3687 } 3688 3689 /** 3690 * Given a raw RSSI, return the RSSI signal quality rating using the system default RSSI 3691 * quality rating thresholds. 3692 * @param rssi a raw RSSI value, in dBm, usually between -55 and -90 3693 * @return the RSSI signal quality rating, in the range 3694 * [0, {@link #getMaxSignalLevel()}], where 0 is the lowest (worst signal) RSSI 3695 * rating and {@link #getMaxSignalLevel()} is the highest (best signal) RSSI rating. 3696 */ 3697 @IntRange(from = 0) calculateSignalLevel(int rssi)3698 public int calculateSignalLevel(int rssi) { 3699 try { 3700 return mService.calculateSignalLevel(rssi); 3701 } catch (RemoteException e) { 3702 throw e.rethrowFromSystemServer(); 3703 } 3704 } 3705 3706 /** 3707 * Get the system default maximum signal level. 3708 * This is the maximum RSSI level returned by {@link #calculateSignalLevel(int)}. 3709 */ 3710 @IntRange(from = 0) getMaxSignalLevel()3711 public int getMaxSignalLevel() { 3712 return calculateSignalLevel(Integer.MAX_VALUE); 3713 } 3714 3715 /** 3716 * Compares two signal strengths. 3717 * 3718 * @param rssiA The power of the first signal measured in RSSI. 3719 * @param rssiB The power of the second signal measured in RSSI. 3720 * @return Returns <0 if the first signal is weaker than the second signal, 3721 * 0 if the two signals have the same strength, and >0 if the first 3722 * signal is stronger than the second signal. 3723 */ compareSignalLevel(int rssiA, int rssiB)3724 public static int compareSignalLevel(int rssiA, int rssiB) { 3725 return rssiA - rssiB; 3726 } 3727 3728 /** 3729 * Call allowing ConnectivityService to update WifiService with interface mode changes. 3730 * 3731 * @param ifaceName String name of the updated interface, or null to represent all interfaces 3732 * @param mode int representing the new mode, one of: 3733 * {@link #IFACE_IP_MODE_TETHERED}, 3734 * {@link #IFACE_IP_MODE_LOCAL_ONLY}, 3735 * {@link #IFACE_IP_MODE_CONFIGURATION_ERROR}, 3736 * {@link #IFACE_IP_MODE_UNSPECIFIED} 3737 * 3738 * @hide 3739 */ 3740 @SystemApi 3741 @RequiresPermission(anyOf = { 3742 android.Manifest.permission.NETWORK_STACK, 3743 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 3744 }) updateInterfaceIpState(@ullable String ifaceName, @IfaceIpMode int mode)3745 public void updateInterfaceIpState(@Nullable String ifaceName, @IfaceIpMode int mode) { 3746 try { 3747 mService.updateInterfaceIpState(ifaceName, mode); 3748 } catch (RemoteException e) { 3749 throw e.rethrowFromSystemServer(); 3750 } 3751 } 3752 3753 /* Wi-Fi/Cellular Coex */ 3754 3755 /** 3756 * Mandatory coex restriction flag for Wi-Fi Direct. 3757 * 3758 * @see #setCoexUnsafeChannels(List, int) 3759 * 3760 * @hide 3761 */ 3762 @SystemApi 3763 @RequiresApi(Build.VERSION_CODES.S) 3764 public static final int COEX_RESTRICTION_WIFI_DIRECT = 0x1 << 0; 3765 3766 /** 3767 * Mandatory coex restriction flag for SoftAP 3768 * 3769 * @see #setCoexUnsafeChannels(List, int) 3770 * 3771 * @hide 3772 */ 3773 @SystemApi 3774 @RequiresApi(Build.VERSION_CODES.S) 3775 public static final int COEX_RESTRICTION_SOFTAP = 0x1 << 1; 3776 3777 /** 3778 * Mandatory coex restriction flag for Wi-Fi Aware. 3779 * 3780 * @see #setCoexUnsafeChannels(List, int) 3781 * 3782 * @hide 3783 */ 3784 @SystemApi 3785 @RequiresApi(Build.VERSION_CODES.S) 3786 public static final int COEX_RESTRICTION_WIFI_AWARE = 0x1 << 2; 3787 3788 /** @hide */ 3789 @RequiresApi(Build.VERSION_CODES.S) 3790 @Retention(RetentionPolicy.SOURCE) 3791 @IntDef(flag = true, prefix = {"COEX_RESTRICTION_"}, value = { 3792 COEX_RESTRICTION_WIFI_DIRECT, 3793 COEX_RESTRICTION_SOFTAP, 3794 COEX_RESTRICTION_WIFI_AWARE 3795 }) 3796 public @interface CoexRestriction {} 3797 3798 /** 3799 * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise. 3800 * 3801 * @hide 3802 */ isDefaultCoexAlgorithmEnabled()3803 public boolean isDefaultCoexAlgorithmEnabled() { 3804 try { 3805 return mService.isDefaultCoexAlgorithmEnabled(); 3806 } catch (RemoteException e) { 3807 throw e.rethrowFromSystemServer(); 3808 } 3809 } 3810 3811 /** 3812 * Specify the list of {@link CoexUnsafeChannel} to propagate through the framework for 3813 * Wi-Fi/Cellular coex channel avoidance if the default algorithm is disabled via overlay 3814 * (i.e. config_wifiCoexDefaultAlgorithmEnabled = false). Otherwise do nothing. 3815 * 3816 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 3817 * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode 3818 * restrictions on the specified channels. If any restrictions are set, 3819 * then the supplied CoexUnsafeChannels should be completely avoided for 3820 * the specified modes, rather than be avoided with best effort. 3821 * 3822 * @hide 3823 */ 3824 @SystemApi 3825 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS) 3826 @RequiresApi(Build.VERSION_CODES.S) setCoexUnsafeChannels( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)3827 public void setCoexUnsafeChannels( 3828 @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions) { 3829 if (unsafeChannels == null) { 3830 throw new IllegalArgumentException("unsafeChannels must not be null"); 3831 } 3832 try { 3833 mService.setCoexUnsafeChannels(unsafeChannels, restrictions); 3834 } catch (RemoteException e) { 3835 throw e.rethrowFromSystemServer(); 3836 } 3837 } 3838 3839 /** 3840 * Registers a CoexCallback to listen on the current CoexUnsafeChannels and restrictions being 3841 * used for Wi-Fi/cellular coex channel avoidance. The callback method 3842 * {@link CoexCallback#onCoexUnsafeChannelsChanged(List, int)} will be called immediately after 3843 * registration to return the current values. 3844 * 3845 * @param executor Executor to execute listener callback on 3846 * @param callback CoexCallback to register 3847 * 3848 * @hide 3849 */ 3850 @SystemApi 3851 @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) 3852 @RequiresApi(Build.VERSION_CODES.S) registerCoexCallback( @onNull @allbackExecutor Executor executor, @NonNull CoexCallback callback)3853 public void registerCoexCallback( 3854 @NonNull @CallbackExecutor Executor executor, @NonNull CoexCallback callback) { 3855 if (executor == null) throw new IllegalArgumentException("executor must not be null"); 3856 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 3857 CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); 3858 proxy.initProxy(executor, callback); 3859 try { 3860 mService.registerCoexCallback(proxy); 3861 } catch (RemoteException e) { 3862 throw e.rethrowFromSystemServer(); 3863 } 3864 } 3865 3866 /** 3867 * Unregisters a CoexCallback from listening on the current CoexUnsafeChannels and restrictions 3868 * being used for Wi-Fi/cellular coex channel avoidance. 3869 * @param callback CoexCallback to unregister 3870 * 3871 * @hide 3872 */ 3873 @SystemApi 3874 @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) 3875 @RequiresApi(Build.VERSION_CODES.S) unregisterCoexCallback(@onNull CoexCallback callback)3876 public void unregisterCoexCallback(@NonNull CoexCallback callback) { 3877 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 3878 CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); 3879 try { 3880 mService.unregisterCoexCallback(proxy); 3881 } catch (RemoteException e) { 3882 throw e.rethrowFromSystemServer(); 3883 } finally { 3884 proxy.cleanUpProxy(); 3885 } 3886 } 3887 3888 /** 3889 * Abstract callback class for applications to receive updates about current CoexUnsafeChannels 3890 * for Wi-Fi/Cellular coex channel avoidance. 3891 * 3892 * @hide 3893 */ 3894 @SystemApi 3895 @RequiresApi(Build.VERSION_CODES.S) 3896 public abstract static class CoexCallback { 3897 private final CoexCallbackProxy mCoexCallbackProxy; 3898 CoexCallback()3899 public CoexCallback() { 3900 if (!SdkLevel.isAtLeastS()) { 3901 throw new UnsupportedOperationException(); 3902 } 3903 mCoexCallbackProxy = new CoexCallbackProxy(); 3904 } 3905 3906 /*package*/ @NonNull getProxy()3907 CoexCallbackProxy getProxy() { 3908 return mCoexCallbackProxy; 3909 } 3910 3911 /** 3912 * This indicates the current CoexUnsafeChannels and restrictions calculated by the default 3913 * coex algorithm if config_wifiCoexDefaultAlgorithmEnabled is {@code true}. Otherwise, the 3914 * values will match the ones supplied to {@link #setCoexUnsafeChannels(List, int)}. 3915 * 3916 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 3917 * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode 3918 * restrictions on the specified channels. If any restrictions are set, 3919 * then the supplied CoexUnsafeChannels should be completely avoided for 3920 * the specified modes, rather than be avoided with best effort. 3921 */ onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)3922 public abstract void onCoexUnsafeChannelsChanged( 3923 @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions); 3924 3925 /** 3926 * Callback proxy for CoexCallback objects. 3927 */ 3928 private static class CoexCallbackProxy extends ICoexCallback.Stub { 3929 private final Object mLock = new Object(); 3930 @Nullable @GuardedBy("mLock") private Executor mExecutor; 3931 @Nullable @GuardedBy("mLock") private CoexCallback mCallback; 3932 CoexCallbackProxy()3933 CoexCallbackProxy() { 3934 mExecutor = null; 3935 mCallback = null; 3936 } 3937 initProxy(@onNull Executor executor, @NonNull CoexCallback callback)3938 /*package*/ void initProxy(@NonNull Executor executor, 3939 @NonNull CoexCallback callback) { 3940 synchronized (mLock) { 3941 mExecutor = executor; 3942 mCallback = callback; 3943 } 3944 } 3945 cleanUpProxy()3946 /*package*/ void cleanUpProxy() { 3947 synchronized (mLock) { 3948 mExecutor = null; 3949 mCallback = null; 3950 } 3951 } 3952 3953 @Override onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)3954 public void onCoexUnsafeChannelsChanged( 3955 @NonNull List<CoexUnsafeChannel> unsafeChannels, 3956 @CoexRestriction int restrictions) { 3957 Executor executor; 3958 CoexCallback callback; 3959 synchronized (mLock) { 3960 executor = mExecutor; 3961 callback = mCallback; 3962 } 3963 if (executor == null || callback == null) { 3964 return; 3965 } 3966 Binder.clearCallingIdentity(); 3967 executor.execute(() -> 3968 callback.onCoexUnsafeChannelsChanged(unsafeChannels, restrictions)); 3969 } 3970 } 3971 } 3972 3973 /** 3974 * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. 3975 * Note that starting Soft AP mode may disable station mode operation if the device does not 3976 * support concurrency. 3977 * @param wifiConfig SSID, security and channel details as part of WifiConfiguration, or null to 3978 * use the persisted Soft AP configuration that was previously set using 3979 * {@link #setWifiApConfiguration(WifiConfiguration)}. 3980 * @return {@code true} if the operation succeeded, {@code false} otherwise 3981 * 3982 * @hide 3983 */ 3984 @RequiresPermission(anyOf = { 3985 android.Manifest.permission.NETWORK_STACK, 3986 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 3987 }) startSoftAp(@ullable WifiConfiguration wifiConfig)3988 public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) { 3989 try { 3990 return mService.startSoftAp(wifiConfig, mContext.getOpPackageName()); 3991 } catch (RemoteException e) { 3992 throw e.rethrowFromSystemServer(); 3993 } 3994 } 3995 3996 /** 3997 * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. 3998 * Note that starting Soft AP mode may disable station mode operation if the device does not 3999 * support concurrency. 4000 * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP, 4001 * or null to use the persisted Soft AP configuration that was previously 4002 * set using {@link #setSoftApConfiguration(softApConfiguration)}. 4003 * @return {@code true} if the operation succeeded, {@code false} otherwise 4004 * 4005 * @hide 4006 */ 4007 @SystemApi 4008 @RequiresPermission(anyOf = { 4009 android.Manifest.permission.NETWORK_STACK, 4010 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 4011 }) startTetheredHotspot(@ullable SoftApConfiguration softApConfig)4012 public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) { 4013 try { 4014 return mService.startTetheredHotspot(softApConfig, mContext.getOpPackageName()); 4015 } catch (RemoteException e) { 4016 throw e.rethrowFromSystemServer(); 4017 } 4018 } 4019 4020 4021 /** 4022 * Stop SoftAp mode. 4023 * Note that stopping softap mode will restore the previous wifi mode. 4024 * @return {@code true} if the operation succeeds, {@code false} otherwise 4025 * 4026 * @hide 4027 */ 4028 @SystemApi 4029 @RequiresPermission(anyOf = { 4030 android.Manifest.permission.NETWORK_STACK, 4031 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 4032 }) stopSoftAp()4033 public boolean stopSoftAp() { 4034 try { 4035 return mService.stopSoftAp(); 4036 } catch (RemoteException e) { 4037 throw e.rethrowFromSystemServer(); 4038 } 4039 } 4040 4041 /** 4042 * Request a local only hotspot that an application can use to communicate between co-located 4043 * devices connected to the created WiFi hotspot. The network created by this method will not 4044 * have Internet access. Each application can make a single request for the hotspot, but 4045 * multiple applications could be requesting the hotspot at the same time. When multiple 4046 * applications have successfully registered concurrently, they will be sharing the underlying 4047 * hotspot. {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} is called 4048 * when the hotspot is ready for use by the application. 4049 * <p> 4050 * Each application can make a single active call to this method. The {@link 4051 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} callback supplies the 4052 * requestor with a {@link LocalOnlyHotspotReservation} that contains a 4053 * {@link SoftApConfiguration} with the SSID, security type and credentials needed to connect 4054 * to the hotspot. Communicating this information is up to the application. 4055 * <p> 4056 * If the LocalOnlyHotspot cannot be created, the {@link LocalOnlyHotspotCallback#onFailed(int)} 4057 * method will be called. Example failures include errors bringing up the network or if 4058 * there is an incompatible operating mode. For example, if the user is currently using Wifi 4059 * Tethering to provide an upstream to another device, LocalOnlyHotspot will not start due to 4060 * an incompatible mode. The possible error codes include: 4061 * {@link LocalOnlyHotspotCallback#ERROR_NO_CHANNEL}, 4062 * {@link LocalOnlyHotspotCallback#ERROR_GENERIC}, 4063 * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE} and 4064 * {@link LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED}. 4065 * <p> 4066 * Internally, requests will be tracked to prevent the hotspot from being torn down while apps 4067 * are still using it. The {@link LocalOnlyHotspotReservation} object passed in the {@link 4068 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call should be closed when 4069 * the LocalOnlyHotspot is no longer needed using {@link LocalOnlyHotspotReservation#close()}. 4070 * Since the hotspot may be shared among multiple applications, removing the final registered 4071 * application request will trigger the hotspot teardown. This means that applications should 4072 * not listen to broadcasts containing wifi state to determine if the hotspot was stopped after 4073 * they are done using it. Additionally, once {@link LocalOnlyHotspotReservation#close()} is 4074 * called, applications will not receive callbacks of any kind. 4075 * <p> 4076 * Applications should be aware that the user may also stop the LocalOnlyHotspot through the 4077 * Settings UI; it is not guaranteed to stay up as long as there is a requesting application. 4078 * The requestors will be notified of this case via 4079 * {@link LocalOnlyHotspotCallback#onStopped()}. Other cases may arise where the hotspot is 4080 * torn down (Emergency mode, etc). Application developers should be aware that it can stop 4081 * unexpectedly, but they will receive a notification if they have properly registered. 4082 * <p> 4083 * Applications should also be aware that this network will be shared with other applications. 4084 * Applications are responsible for protecting their data on this network (e.g. TLS). 4085 * <p> 4086 * Applications need to have the following permissions to start LocalOnlyHotspot: {@link 4087 * android.Manifest.permission#CHANGE_WIFI_STATE} and {@link 4088 * android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}. Callers without 4089 * the permissions will trigger a {@link java.lang.SecurityException}. 4090 * <p> 4091 * @param callback LocalOnlyHotspotCallback for the application to receive updates about 4092 * operating status. 4093 * @param handler Handler to be used for callbacks. If the caller passes a null Handler, the 4094 * main thread will be used. 4095 */ 4096 @RequiresPermission(allOf = { 4097 android.Manifest.permission.CHANGE_WIFI_STATE, 4098 android.Manifest.permission.ACCESS_FINE_LOCATION}) startLocalOnlyHotspot(LocalOnlyHotspotCallback callback, @Nullable Handler handler)4099 public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback, 4100 @Nullable Handler handler) { 4101 Executor executor = handler == null ? null : new HandlerExecutor(handler); 4102 startLocalOnlyHotspotInternal(null, executor, callback); 4103 } 4104 4105 /** 4106 * Starts a local-only hotspot with a specific configuration applied. See 4107 * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}. 4108 * 4109 * Applications need either {@link android.Manifest.permission#NETWORK_SETUP_WIZARD} or 4110 * {@link android.Manifest.permission#NETWORK_SETTINGS} to call this method. 4111 * 4112 * Since custom configuration settings may be incompatible with each other, the hotspot started 4113 * through this method cannot coexist with another hotspot created through 4114 * startLocalOnlyHotspot. If this is attempted, the first hotspot request wins and others 4115 * receive {@link LocalOnlyHotspotCallback#ERROR_GENERIC} through 4116 * {@link LocalOnlyHotspotCallback#onFailed}. 4117 * 4118 * @param config Custom configuration for the hotspot. See {@link SoftApConfiguration}. 4119 * @param executor Executor to run callback methods on, or null to use the main thread. 4120 * @param callback Callback object for updates about hotspot status, or null for no updates. 4121 * @hide 4122 */ 4123 @SystemApi 4124 @RequiresPermission(anyOf = { 4125 android.Manifest.permission.NETWORK_SETTINGS, 4126 android.Manifest.permission.NETWORK_SETUP_WIZARD}) startLocalOnlyHotspot(@onNull SoftApConfiguration config, @Nullable Executor executor, @Nullable LocalOnlyHotspotCallback callback)4127 public void startLocalOnlyHotspot(@NonNull SoftApConfiguration config, 4128 @Nullable Executor executor, 4129 @Nullable LocalOnlyHotspotCallback callback) { 4130 Objects.requireNonNull(config); 4131 startLocalOnlyHotspotInternal(config, executor, callback); 4132 } 4133 4134 /** 4135 * Common implementation of both configurable and non-configurable LOHS. 4136 * 4137 * @param config App-specified configuration, or null. When present, additional privileges are 4138 * required, and the hotspot cannot be shared with other clients. 4139 * @param executor Executor to run callback methods on, or null to use the main thread. 4140 * @param callback Callback object for updates about hotspot status, or null for no updates. 4141 */ startLocalOnlyHotspotInternal( @ullable SoftApConfiguration config, @Nullable Executor executor, @Nullable LocalOnlyHotspotCallback callback)4142 private void startLocalOnlyHotspotInternal( 4143 @Nullable SoftApConfiguration config, 4144 @Nullable Executor executor, 4145 @Nullable LocalOnlyHotspotCallback callback) { 4146 if (executor == null) { 4147 executor = mContext.getMainExecutor(); 4148 } 4149 synchronized (mLock) { 4150 LocalOnlyHotspotCallbackProxy proxy = 4151 new LocalOnlyHotspotCallbackProxy(this, executor, callback); 4152 try { 4153 String packageName = mContext.getOpPackageName(); 4154 String featureId = mContext.getAttributionTag(); 4155 int returnCode = mService.startLocalOnlyHotspot(proxy, packageName, featureId, 4156 config); 4157 if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) { 4158 // Send message to the proxy to make sure we call back on the correct thread 4159 proxy.onHotspotFailed(returnCode); 4160 return; 4161 } 4162 mLOHSCallbackProxy = proxy; 4163 } catch (RemoteException e) { 4164 throw e.rethrowFromSystemServer(); 4165 } 4166 } 4167 } 4168 4169 /** 4170 * Cancels a pending local only hotspot request. This can be used by the calling application to 4171 * cancel the existing request if the provided callback has not been triggered. Calling this 4172 * method will be equivalent to closing the returned LocalOnlyHotspotReservation, but it is not 4173 * explicitly required. 4174 * <p> 4175 * When cancelling this request, application developers should be aware that there may still be 4176 * outstanding local only hotspot requests and the hotspot may still start, or continue running. 4177 * Additionally, if a callback was registered, it will no longer be triggered after calling 4178 * cancel. 4179 * 4180 * @hide 4181 */ 4182 @UnsupportedAppUsage cancelLocalOnlyHotspotRequest()4183 public void cancelLocalOnlyHotspotRequest() { 4184 synchronized (mLock) { 4185 stopLocalOnlyHotspot(); 4186 } 4187 } 4188 4189 /** 4190 * Method used to inform WifiService that the LocalOnlyHotspot is no longer needed. This 4191 * method is used by WifiManager to release LocalOnlyHotspotReservations held by calling 4192 * applications and removes the internal tracking for the hotspot request. When all requesting 4193 * applications are finished using the hotspot, it will be stopped and WiFi will return to the 4194 * previous operational mode. 4195 * 4196 * This method should not be called by applications. Instead, they should call the close() 4197 * method on their LocalOnlyHotspotReservation. 4198 */ stopLocalOnlyHotspot()4199 private void stopLocalOnlyHotspot() { 4200 synchronized (mLock) { 4201 if (mLOHSCallbackProxy == null) { 4202 // nothing to do, the callback was already cleaned up. 4203 return; 4204 } 4205 mLOHSCallbackProxy = null; 4206 try { 4207 mService.stopLocalOnlyHotspot(); 4208 } catch (RemoteException e) { 4209 throw e.rethrowFromSystemServer(); 4210 } 4211 } 4212 } 4213 4214 /** 4215 * Allow callers (Settings UI) to watch LocalOnlyHotspot state changes. Callers will 4216 * receive a {@link LocalOnlyHotspotSubscription} object as a parameter of the 4217 * {@link LocalOnlyHotspotObserver#onRegistered(LocalOnlyHotspotSubscription)}. The registered 4218 * callers will receive the {@link LocalOnlyHotspotObserver#onStarted(SoftApConfiguration)} and 4219 * {@link LocalOnlyHotspotObserver#onStopped()} callbacks. 4220 * <p> 4221 * Applications should have the 4222 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} 4223 * permission. Callers without the permission will trigger a 4224 * {@link java.lang.SecurityException}. 4225 * <p> 4226 * @param observer LocalOnlyHotspotObserver callback. 4227 * @param handler Handler to use for callbacks 4228 * 4229 * @hide 4230 */ watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer, @Nullable Handler handler)4231 public void watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer, 4232 @Nullable Handler handler) { 4233 Executor executor = handler == null ? mContext.getMainExecutor() 4234 : new HandlerExecutor(handler); 4235 synchronized (mLock) { 4236 mLOHSObserverProxy = 4237 new LocalOnlyHotspotObserverProxy(this, executor, observer); 4238 try { 4239 mService.startWatchLocalOnlyHotspot(mLOHSObserverProxy); 4240 mLOHSObserverProxy.registered(); 4241 } catch (RemoteException e) { 4242 mLOHSObserverProxy = null; 4243 throw e.rethrowFromSystemServer(); 4244 } 4245 } 4246 } 4247 4248 /** 4249 * Allow callers to stop watching LocalOnlyHotspot state changes. After calling this method, 4250 * applications will no longer receive callbacks. 4251 * 4252 * @hide 4253 */ unregisterLocalOnlyHotspotObserver()4254 public void unregisterLocalOnlyHotspotObserver() { 4255 synchronized (mLock) { 4256 if (mLOHSObserverProxy == null) { 4257 // nothing to do, the callback was already cleaned up 4258 return; 4259 } 4260 mLOHSObserverProxy = null; 4261 try { 4262 mService.stopWatchLocalOnlyHotspot(); 4263 } catch (RemoteException e) { 4264 throw e.rethrowFromSystemServer(); 4265 } 4266 } 4267 } 4268 4269 /** 4270 * Gets the tethered Wi-Fi hotspot enabled state. 4271 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 4272 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 4273 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 4274 * @see #isWifiApEnabled() 4275 * 4276 * @hide 4277 */ 4278 @SystemApi 4279 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) getWifiApState()4280 public int getWifiApState() { 4281 try { 4282 return mService.getWifiApEnabledState(); 4283 } catch (RemoteException e) { 4284 throw e.rethrowFromSystemServer(); 4285 } 4286 } 4287 4288 /** 4289 * Return whether tethered Wi-Fi AP is enabled or disabled. 4290 * @return {@code true} if tethered Wi-Fi AP is enabled 4291 * @see #getWifiApState() 4292 * 4293 * @hide 4294 */ 4295 @SystemApi 4296 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) isWifiApEnabled()4297 public boolean isWifiApEnabled() { 4298 return getWifiApState() == WIFI_AP_STATE_ENABLED; 4299 } 4300 4301 /** 4302 * Gets the tethered Wi-Fi AP Configuration. 4303 * @return AP details in WifiConfiguration 4304 * 4305 * Note that AP detail may contain configuration which is cannot be represented 4306 * by the legacy WifiConfiguration, in such cases a null will be returned. 4307 * 4308 * @deprecated This API is deprecated. Use {@link #getSoftApConfiguration()} instead. 4309 * @hide 4310 */ 4311 @Nullable 4312 @SystemApi 4313 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 4314 @Deprecated getWifiApConfiguration()4315 public WifiConfiguration getWifiApConfiguration() { 4316 try { 4317 return mService.getWifiApConfiguration(); 4318 } catch (RemoteException e) { 4319 throw e.rethrowFromSystemServer(); 4320 } 4321 } 4322 4323 /** 4324 * Gets the Wi-Fi tethered AP Configuration. 4325 * @return AP details in {@link SoftApConfiguration} 4326 * 4327 * @hide 4328 */ 4329 @NonNull 4330 @SystemApi 4331 @RequiresPermission(anyOf = { 4332 android.Manifest.permission.NETWORK_SETTINGS, 4333 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 4334 }) getSoftApConfiguration()4335 public SoftApConfiguration getSoftApConfiguration() { 4336 try { 4337 return mService.getSoftApConfiguration(); 4338 } catch (RemoteException e) { 4339 throw e.rethrowFromSystemServer(); 4340 } 4341 } 4342 4343 /** 4344 * Sets the tethered Wi-Fi AP Configuration. 4345 * @return {@code true} if the operation succeeded, {@code false} otherwise 4346 * 4347 * @deprecated This API is deprecated. Use {@link #setSoftApConfiguration(SoftApConfiguration)} 4348 * instead. 4349 * @hide 4350 */ 4351 @SystemApi 4352 @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) 4353 @Deprecated setWifiApConfiguration(WifiConfiguration wifiConfig)4354 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { 4355 try { 4356 return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName()); 4357 } catch (RemoteException e) { 4358 throw e.rethrowFromSystemServer(); 4359 } 4360 } 4361 4362 /** 4363 * Sets the tethered Wi-Fi AP Configuration. 4364 * 4365 * If the API is called while the tethered soft AP is enabled, the configuration will apply to 4366 * the current soft AP if the new configuration only includes 4367 * {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} 4368 * or {@link SoftApConfiguration.Builder#setShutdownTimeoutMillis(long)} 4369 * or {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)} 4370 * or {@link SoftApConfiguration.Builder#setBlockedClientList(List)} 4371 * or {@link SoftApConfiguration.Builder#setAllowedClientList(List)} 4372 * or {@link SoftApConfiguration.Builder#setAutoShutdownEnabled(boolean)} 4373 * or {@link SoftApConfiguration.Builder#setBridgedModeOpportunisticShutdownEnabled(boolean)} 4374 * 4375 * Otherwise, the configuration changes will be applied when the Soft AP is next started 4376 * (the framework will not stop/start the AP). 4377 * 4378 * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP. 4379 * @return {@code true} if the operation succeeded, {@code false} otherwise 4380 * 4381 * @hide 4382 */ 4383 @SystemApi 4384 @RequiresPermission(anyOf = { 4385 android.Manifest.permission.NETWORK_SETTINGS, 4386 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 4387 }) setSoftApConfiguration(@onNull SoftApConfiguration softApConfig)4388 public boolean setSoftApConfiguration(@NonNull SoftApConfiguration softApConfig) { 4389 try { 4390 return mService.setSoftApConfiguration( 4391 softApConfig, mContext.getOpPackageName()); 4392 } catch (RemoteException e) { 4393 throw e.rethrowFromSystemServer(); 4394 } 4395 } 4396 4397 /** 4398 * Enable/Disable TDLS on a specific local route. 4399 * 4400 * <p> 4401 * TDLS enables two wireless endpoints to talk to each other directly 4402 * without going through the access point that is managing the local 4403 * network. It saves bandwidth and improves quality of the link. 4404 * </p> 4405 * <p> 4406 * This API enables/disables the option of using TDLS. If enabled, the 4407 * underlying hardware is free to use TDLS or a hop through the access 4408 * point. If disabled, existing TDLS session is torn down and 4409 * hardware is restricted to use access point for transferring wireless 4410 * packets. Default value for all routes is 'disabled', meaning restricted 4411 * to use access point for transferring packets. 4412 * </p> 4413 * 4414 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 4415 * @param enable true = setup and false = tear down TDLS 4416 */ setTdlsEnabled(InetAddress remoteIPAddress, boolean enable)4417 public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) { 4418 try { 4419 mService.enableTdls(remoteIPAddress.getHostAddress(), enable); 4420 } catch (RemoteException e) { 4421 throw e.rethrowFromSystemServer(); 4422 } 4423 } 4424 4425 /** 4426 * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except 4427 * this version allows you to specify remote endpoint with a MAC address. 4428 * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab 4429 * @param enable true = setup and false = tear down TDLS 4430 */ setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable)4431 public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) { 4432 try { 4433 mService.enableTdlsWithMacAddress(remoteMacAddress, enable); 4434 } catch (RemoteException e) { 4435 throw e.rethrowFromSystemServer(); 4436 } 4437 } 4438 4439 /** 4440 * Passed with {@link ActionListener#onFailure}. 4441 * Indicates that the operation failed due to an internal error. 4442 * @hide 4443 */ 4444 public static final int ERROR = 0; 4445 4446 /** 4447 * Passed with {@link ActionListener#onFailure}. 4448 * Indicates that the operation is already in progress 4449 * @hide 4450 */ 4451 public static final int IN_PROGRESS = 1; 4452 4453 /** 4454 * Passed with {@link ActionListener#onFailure}. 4455 * Indicates that the operation failed because the framework is busy and 4456 * unable to service the request 4457 * @hide 4458 */ 4459 public static final int BUSY = 2; 4460 4461 /** @hide */ 4462 @Retention(RetentionPolicy.SOURCE) 4463 @IntDef({ERROR, IN_PROGRESS, BUSY}) 4464 public @interface ActionListenerFailureReason {} 4465 4466 /* WPS specific errors */ 4467 /** WPS overlap detected 4468 * @deprecated This is deprecated 4469 */ 4470 public static final int WPS_OVERLAP_ERROR = 3; 4471 /** WEP on WPS is prohibited 4472 * @deprecated This is deprecated 4473 */ 4474 public static final int WPS_WEP_PROHIBITED = 4; 4475 /** TKIP only prohibited 4476 * @deprecated This is deprecated 4477 */ 4478 public static final int WPS_TKIP_ONLY_PROHIBITED = 5; 4479 /** Authentication failure on WPS 4480 * @deprecated This is deprecated 4481 */ 4482 public static final int WPS_AUTH_FAILURE = 6; 4483 /** WPS timed out 4484 * @deprecated This is deprecated 4485 */ 4486 public static final int WPS_TIMED_OUT = 7; 4487 4488 /** 4489 * Passed with {@link ActionListener#onFailure}. 4490 * Indicates that the operation failed due to invalid inputs 4491 * @hide 4492 */ 4493 public static final int INVALID_ARGS = 8; 4494 4495 /** 4496 * Passed with {@link ActionListener#onFailure}. 4497 * Indicates that the operation failed due to user permissions. 4498 * @hide 4499 */ 4500 public static final int NOT_AUTHORIZED = 9; 4501 4502 /** 4503 * Interface for callback invocation on an application action 4504 * @hide 4505 */ 4506 @SystemApi 4507 public interface ActionListener { 4508 /** 4509 * The operation succeeded. 4510 */ onSuccess()4511 void onSuccess(); 4512 /** 4513 * The operation failed. 4514 * @param reason The reason for failure depends on the operation. 4515 */ onFailure(@ctionListenerFailureReason int reason)4516 void onFailure(@ActionListenerFailureReason int reason); 4517 } 4518 4519 /** Interface for callback invocation on a start WPS action 4520 * @deprecated This is deprecated 4521 */ 4522 public static abstract class WpsCallback { 4523 4524 /** WPS start succeeded 4525 * @deprecated This API is deprecated 4526 */ onStarted(String pin)4527 public abstract void onStarted(String pin); 4528 4529 /** WPS operation completed successfully 4530 * @deprecated This API is deprecated 4531 */ onSucceeded()4532 public abstract void onSucceeded(); 4533 4534 /** 4535 * WPS operation failed 4536 * @param reason The reason for failure could be one of 4537 * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR}, 4538 * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE} 4539 * and some generic errors. 4540 * @deprecated This API is deprecated 4541 */ onFailed(int reason)4542 public abstract void onFailed(int reason); 4543 } 4544 4545 /** 4546 * Base class for soft AP callback. Should be extended by applications and set when calling 4547 * {@link WifiManager#registerSoftApCallback(Executor, SoftApCallback)}. 4548 * 4549 * @hide 4550 */ 4551 @SystemApi 4552 public interface SoftApCallback { 4553 /** 4554 * Called when soft AP state changes. 4555 * 4556 * @param state the new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, 4557 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 4558 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 4559 * @param failureReason reason when in failed state. One of 4560 * {@link #SAP_START_FAILURE_GENERAL}, 4561 * {@link #SAP_START_FAILURE_NO_CHANNEL}, 4562 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION} 4563 */ onStateChanged(@ifiApState int state, @SapStartFailure int failureReason)4564 default void onStateChanged(@WifiApState int state, @SapStartFailure int failureReason) {} 4565 4566 /** 4567 * Called when the connected clients to soft AP changes. 4568 * 4569 * @param clients the currently connected clients 4570 * 4571 * @deprecated This API is deprecated. 4572 * Use {@link #onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} instead. 4573 */ 4574 @Deprecated onConnectedClientsChanged(@onNull List<WifiClient> clients)4575 default void onConnectedClientsChanged(@NonNull List<WifiClient> clients) {} 4576 4577 4578 /** 4579 * Called when the connected clients for a soft AP instance change. 4580 * 4581 * When the Soft AP is configured in single AP mode, this callback is invoked 4582 * with the same {@link SoftApInfo} for all connected clients changes. 4583 * When the Soft AP is configured as multiple Soft AP instances (using 4584 * {@link SoftApConfiguration.Builder#setBands(int[])} or 4585 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}), this 4586 * callback is invoked with the corresponding {@link SoftApInfo} for the instance in which 4587 * the connected clients changed. 4588 * 4589 * @param info The {@link SoftApInfo} of the AP. 4590 * @param clients The currently connected clients on the AP instance specified by 4591 * {@code info}. 4592 */ onConnectedClientsChanged(@onNull SoftApInfo info, @NonNull List<WifiClient> clients)4593 default void onConnectedClientsChanged(@NonNull SoftApInfo info, 4594 @NonNull List<WifiClient> clients) {} 4595 4596 /** 4597 * Called when the Soft AP information changes. 4598 * 4599 * Note: this API remains valid only when the Soft AP is configured as a single AP - 4600 * not as multiple Soft APs (which are bridged to each other). When multiple Soft APs are 4601 * configured (using {@link SoftApConfiguration.Builder#setBands(int[])} or 4602 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}) 4603 * this callback will not be triggered - use the 4604 * {@link #onInfoChanged(List<SoftApInfo>)} callback in that case. 4605 * 4606 * @param softApInfo is the Soft AP information. {@link SoftApInfo} 4607 * 4608 * @deprecated This API is deprecated. Use {@link #onInfoChanged(List<SoftApInfo>)} 4609 * instead. 4610 */ 4611 @Deprecated onInfoChanged(@onNull SoftApInfo softApInfo)4612 default void onInfoChanged(@NonNull SoftApInfo softApInfo) { 4613 // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. 4614 } 4615 4616 /** 4617 * Called when the Soft AP information changes. 4618 * 4619 * Returns information on all configured Soft AP instances. The number of the elements in 4620 * the list depends on Soft AP configuration and state: 4621 * <ul> 4622 * <li>An empty list will be returned when the Soft AP is disabled. 4623 * <li>One information element will be returned in the list when the Soft AP is configured 4624 * as a single AP or when a single Soft AP remains active. 4625 * <li>Two information elements will be returned in the list when the multiple Soft APs are 4626 * configured and are active. 4627 * (configured using {@link SoftApConfiguration.Builder#setBands(int[])} or 4628 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}). 4629 * </ul> 4630 * 4631 * Note: When multiple Soft AP instances are configured, one of the Soft APs may 4632 * be shut down independently of the other by the framework. This can happen if no devices 4633 * are connected to it for some duration. In that case, one information element will be 4634 * returned. 4635 * 4636 * See {@link #isBridgedApConcurrencySupported()} for support info of multiple (bridged) AP. 4637 * 4638 * @param softApInfoList is the list of the Soft AP information elements - 4639 * {@link SoftApInfo}. 4640 */ onInfoChanged(@onNull List<SoftApInfo> softApInfoList)4641 default void onInfoChanged(@NonNull List<SoftApInfo> softApInfoList) { 4642 // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. 4643 } 4644 4645 /** 4646 * Called when capability of Soft AP changes. 4647 * 4648 * @param softApCapability is the Soft AP capability. {@link SoftApCapability} 4649 */ onCapabilityChanged(@onNull SoftApCapability softApCapability)4650 default void onCapabilityChanged(@NonNull SoftApCapability softApCapability) { 4651 // Do nothing: can be updated to add SoftApCapability details (e.g. meximum supported 4652 // client number) to the UI. 4653 } 4654 4655 /** 4656 * Called when client trying to connect but device blocked the client with specific reason. 4657 * 4658 * Can be used to ask user to update client to allowed list or blocked list 4659 * when reason is {@link SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER}, or 4660 * indicate the block due to maximum supported client number limitation when reason is 4661 * {@link SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS}. 4662 * 4663 * @param client the currently blocked client. 4664 * @param blockedReason one of blocked reason from {@link SapClientBlockedReason} 4665 */ onBlockedClientConnecting(@onNull WifiClient client, @SapClientBlockedReason int blockedReason)4666 default void onBlockedClientConnecting(@NonNull WifiClient client, 4667 @SapClientBlockedReason int blockedReason) { 4668 // Do nothing: can be used to ask user to update client to allowed list or blocked list. 4669 } 4670 } 4671 4672 /** 4673 * Callback proxy for SoftApCallback objects. 4674 * 4675 * @hide 4676 */ 4677 private class SoftApCallbackProxy extends ISoftApCallback.Stub { 4678 private final Executor mExecutor; 4679 private final SoftApCallback mCallback; 4680 private Map<String, List<WifiClient>> mCurrentClients = new HashMap<>(); 4681 private Map<String, SoftApInfo> mCurrentInfos = new HashMap<>(); 4682 getConnectedClientList(Map<String, List<WifiClient>> clientsMap)4683 private List<WifiClient> getConnectedClientList(Map<String, List<WifiClient>> clientsMap) { 4684 List<WifiClient> connectedClientList = new ArrayList<>(); 4685 for (List<WifiClient> it : clientsMap.values()) { 4686 connectedClientList.addAll(it); 4687 } 4688 return connectedClientList; 4689 } 4690 SoftApCallbackProxy(Executor executor, SoftApCallback callback)4691 SoftApCallbackProxy(Executor executor, SoftApCallback callback) { 4692 mExecutor = executor; 4693 mCallback = callback; 4694 } 4695 4696 @Override onStateChanged(int state, int failureReason)4697 public void onStateChanged(int state, int failureReason) { 4698 if (mVerboseLoggingEnabled) { 4699 Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state 4700 + ", failureReason=" + failureReason); 4701 } 4702 4703 Binder.clearCallingIdentity(); 4704 mExecutor.execute(() -> { 4705 mCallback.onStateChanged(state, failureReason); 4706 }); 4707 } 4708 4709 @Override onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration)4710 public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, 4711 Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration) { 4712 if (mVerboseLoggingEnabled) { 4713 Log.v(TAG, "SoftApCallbackProxy: onConnectedClientsOrInfoChanged: clients: " 4714 + clients + ", infos: " + infos + ", isBridged is " + isBridged 4715 + ", isRegistration is " + isRegistration); 4716 } 4717 4718 List<SoftApInfo> changedInfoList = new ArrayList<>(infos.values()); 4719 Map<SoftApInfo, List<WifiClient>> changedInfoClients = new HashMap<>(); 4720 // Some devices may not support infos callback, allow them to support client 4721 // connection changed callback. 4722 boolean areClientsChangedWithoutInfosChanged = 4723 infos.size() == 0 && getConnectedClientList(clients).size() 4724 != getConnectedClientList(mCurrentClients).size(); 4725 boolean isInfoChanged = infos.size() != mCurrentInfos.size(); 4726 4727 if (isRegistration) { 4728 // Check if there are clients connected, put it to changedInfoClients 4729 for (SoftApInfo currentInfo : infos.values()) { 4730 String instance = currentInfo.getApInstanceIdentifier(); 4731 if (clients.getOrDefault(instance, Collections.emptyList()).size() > 0) { 4732 changedInfoClients.put(currentInfo, clients.get(instance)); 4733 } 4734 } 4735 } 4736 4737 // Check if old info removed or not (client changed case) 4738 for (SoftApInfo info : mCurrentInfos.values()) { 4739 String changedInstance = info.getApInstanceIdentifier(); 4740 if (!changedInfoList.contains(info)) { 4741 isInfoChanged = true; 4742 if (mCurrentClients.getOrDefault(changedInstance, 4743 Collections.emptyList()).size() > 0) { 4744 Log.d(TAG, "SoftApCallbackProxy: info changed on client connected" 4745 + " instance(Shut Down case)"); 4746 //Here should notify client changed on old info 4747 changedInfoClients.put(info, Collections.emptyList()); 4748 } 4749 } else { 4750 // info doesn't change, check client list 4751 List<WifiClient> changedClientList = clients.getOrDefault( 4752 changedInstance, Collections.emptyList()); 4753 if (changedClientList.size() 4754 != mCurrentClients 4755 .getOrDefault(changedInstance, Collections.emptyList()).size()) { 4756 // Here should notify client changed on new info(same as old info) 4757 changedInfoClients.put(info, changedClientList); 4758 } 4759 } 4760 } 4761 4762 mCurrentClients = clients; 4763 mCurrentInfos = infos; 4764 if (!isInfoChanged && changedInfoClients.isEmpty() 4765 && !isRegistration && !areClientsChangedWithoutInfosChanged) { 4766 Log.v(TAG, "SoftApCallbackProxy: No changed & Not Registration," 4767 + " don't need to notify the client"); 4768 return; 4769 } 4770 Binder.clearCallingIdentity(); 4771 // Notify the clients changed first for old info shutdown case 4772 for (SoftApInfo changedInfo : changedInfoClients.keySet()) { 4773 Log.v(TAG, "SoftApCallbackProxy: send onConnectedClientsChanged, changedInfo is " 4774 + changedInfo + " and clients are " + changedInfoClients.get(changedInfo)); 4775 mExecutor.execute(() -> { 4776 mCallback.onConnectedClientsChanged( 4777 changedInfo, changedInfoClients.get(changedInfo)); 4778 }); 4779 } 4780 4781 if (isInfoChanged || isRegistration) { 4782 if (!isBridged) { 4783 SoftApInfo newInfo = changedInfoList.isEmpty() 4784 ? new SoftApInfo() : changedInfoList.get(0); 4785 Log.v(TAG, "SoftApCallbackProxy: send InfoChanged, newInfo: " + newInfo); 4786 mExecutor.execute(() -> { 4787 mCallback.onInfoChanged(newInfo); 4788 }); 4789 } 4790 Log.v(TAG, "SoftApCallbackProxy: send InfoChanged, changedInfoList: " 4791 + changedInfoList); 4792 mExecutor.execute(() -> { 4793 mCallback.onInfoChanged(changedInfoList); 4794 }); 4795 } 4796 4797 if (isRegistration || !changedInfoClients.isEmpty() 4798 || areClientsChangedWithoutInfosChanged) { 4799 Log.v(TAG, "SoftApCallbackProxy: send onConnectedClientsChanged(clients): " 4800 + getConnectedClientList(clients)); 4801 mExecutor.execute(() -> { 4802 mCallback.onConnectedClientsChanged(getConnectedClientList(clients)); 4803 }); 4804 } 4805 } 4806 4807 @Override onCapabilityChanged(SoftApCapability capability)4808 public void onCapabilityChanged(SoftApCapability capability) { 4809 if (mVerboseLoggingEnabled) { 4810 Log.v(TAG, "SoftApCallbackProxy: onCapabilityChanged: SoftApCapability=" 4811 + capability); 4812 } 4813 4814 Binder.clearCallingIdentity(); 4815 mExecutor.execute(() -> { 4816 mCallback.onCapabilityChanged(capability); 4817 }); 4818 } 4819 4820 @Override onBlockedClientConnecting(@onNull WifiClient client, int blockedReason)4821 public void onBlockedClientConnecting(@NonNull WifiClient client, int blockedReason) { 4822 if (mVerboseLoggingEnabled) { 4823 Log.v(TAG, "SoftApCallbackProxy: onBlockedClientConnecting: client=" + client 4824 + " with reason = " + blockedReason); 4825 } 4826 4827 Binder.clearCallingIdentity(); 4828 mExecutor.execute(() -> { 4829 mCallback.onBlockedClientConnecting(client, blockedReason); 4830 }); 4831 } 4832 } 4833 4834 /** 4835 * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the 4836 * following callbacks on registration: 4837 * <ul> 4838 * <li> {@link SoftApCallback#onStateChanged(int, int)}</li> 4839 * <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li> 4840 * <li> {@link SoftApCallback#onInfoChanged(SoftApInfo)}</li> 4841 * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li> 4842 * <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li> 4843 * </ul> 4844 * 4845 * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know 4846 * if there are any clients connected to a specific bridged instance of this AP 4847 * (if bridged AP is enabled). 4848 * 4849 * Note: Caller will receive the callback 4850 * {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} 4851 * on registration when there are clients connected to AP. 4852 * 4853 * These will be dispatched on registration to provide the caller with the current state 4854 * (and are not an indication of any current change). Note that receiving an immediate 4855 * WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start 4856 * soft AP has failed. Caller can unregister a previously registered callback using 4857 * {@link #unregisterSoftApCallback} 4858 * <p> 4859 * Applications should have the 4860 * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers 4861 * without the permission will trigger a {@link java.lang.SecurityException}. 4862 * <p> 4863 * 4864 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 4865 * object. 4866 * @param callback Callback for soft AP events 4867 * @hide 4868 */ 4869 @SystemApi 4870 @RequiresPermission(anyOf = { 4871 android.Manifest.permission.NETWORK_SETTINGS, 4872 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 4873 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 4874 }) registerSoftApCallback(@onNull @allbackExecutor Executor executor, @NonNull SoftApCallback callback)4875 public void registerSoftApCallback(@NonNull @CallbackExecutor Executor executor, 4876 @NonNull SoftApCallback callback) { 4877 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 4878 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 4879 Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", executor=" + executor); 4880 4881 try { 4882 synchronized (sSoftApCallbackMap) { 4883 ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback); 4884 sSoftApCallbackMap.put(System.identityHashCode(callback), binderCallback); 4885 mService.registerSoftApCallback(binderCallback); 4886 } 4887 } catch (RemoteException e) { 4888 throw e.rethrowFromSystemServer(); 4889 } 4890 } 4891 4892 /** 4893 * Allow callers to unregister a previously registered callback. After calling this method, 4894 * applications will no longer receive soft AP events. 4895 * 4896 * @param callback Callback to unregister for soft AP events 4897 * 4898 * @hide 4899 */ 4900 @SystemApi 4901 @RequiresPermission(anyOf = { 4902 android.Manifest.permission.NETWORK_SETTINGS, 4903 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 4904 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 4905 }) unregisterSoftApCallback(@onNull SoftApCallback callback)4906 public void unregisterSoftApCallback(@NonNull SoftApCallback callback) { 4907 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 4908 Log.v(TAG, "unregisterSoftApCallback: callback=" + callback); 4909 4910 try { 4911 synchronized (sSoftApCallbackMap) { 4912 int callbackIdentifier = System.identityHashCode(callback); 4913 if (!sSoftApCallbackMap.contains(callbackIdentifier)) { 4914 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 4915 return; 4916 } 4917 mService.unregisterSoftApCallback(sSoftApCallbackMap.get(callbackIdentifier)); 4918 sSoftApCallbackMap.remove(callbackIdentifier); 4919 } 4920 } catch (RemoteException e) { 4921 throw e.rethrowFromSystemServer(); 4922 } 4923 } 4924 4925 /** 4926 * LocalOnlyHotspotReservation that contains the {@link SoftApConfiguration} for the active 4927 * LocalOnlyHotspot request. 4928 * <p> 4929 * Applications requesting LocalOnlyHotspot for sharing will receive an instance of the 4930 * LocalOnlyHotspotReservation in the 4931 * {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call. This 4932 * reservation contains the relevant {@link SoftApConfiguration}. 4933 * When an application is done with the LocalOnlyHotspot, they should call {@link 4934 * LocalOnlyHotspotReservation#close()}. Once this happens, the application will not receive 4935 * any further callbacks. If the LocalOnlyHotspot is stopped due to a 4936 * user triggered mode change, applications will be notified via the {@link 4937 * LocalOnlyHotspotCallback#onStopped()} callback. 4938 */ 4939 public class LocalOnlyHotspotReservation implements AutoCloseable { 4940 4941 private final CloseGuard mCloseGuard = new CloseGuard(); 4942 private final SoftApConfiguration mSoftApConfig; 4943 private final WifiConfiguration mWifiConfig; 4944 private boolean mClosed = false; 4945 4946 /** @hide */ 4947 @VisibleForTesting LocalOnlyHotspotReservation(SoftApConfiguration config)4948 public LocalOnlyHotspotReservation(SoftApConfiguration config) { 4949 mSoftApConfig = config; 4950 mWifiConfig = config.toWifiConfiguration(); 4951 mCloseGuard.open("close"); 4952 } 4953 4954 /** 4955 * Returns the {@link WifiConfiguration} of the current Local Only Hotspot (LOHS). 4956 * May be null if hotspot enabled and security type is not 4957 * {@code WifiConfiguration.KeyMgmt.None} or {@code WifiConfiguration.KeyMgmt.WPA2_PSK}. 4958 * 4959 * @deprecated Use {@code WifiManager#getSoftApConfiguration()} to get the 4960 * LOHS configuration. 4961 */ 4962 @Deprecated 4963 @Nullable getWifiConfiguration()4964 public WifiConfiguration getWifiConfiguration() { 4965 return mWifiConfig; 4966 } 4967 4968 /** 4969 * Returns the {@link SoftApConfiguration} of the current Local Only Hotspot (LOHS). 4970 */ 4971 @NonNull getSoftApConfiguration()4972 public SoftApConfiguration getSoftApConfiguration() { 4973 return mSoftApConfig; 4974 } 4975 4976 @Override close()4977 public void close() { 4978 try { 4979 synchronized (mLock) { 4980 if (!mClosed) { 4981 mClosed = true; 4982 stopLocalOnlyHotspot(); 4983 mCloseGuard.close(); 4984 } 4985 } 4986 } catch (Exception e) { 4987 Log.e(TAG, "Failed to stop Local Only Hotspot."); 4988 } finally { 4989 Reference.reachabilityFence(this); 4990 } 4991 } 4992 4993 @Override finalize()4994 protected void finalize() throws Throwable { 4995 try { 4996 if (mCloseGuard != null) { 4997 mCloseGuard.warnIfOpen(); 4998 } 4999 close(); 5000 } finally { 5001 super.finalize(); 5002 } 5003 } 5004 } 5005 5006 /** 5007 * Callback class for applications to receive updates about the LocalOnlyHotspot status. 5008 */ 5009 public static class LocalOnlyHotspotCallback { 5010 /** @hide */ 5011 public static final int REQUEST_REGISTERED = 0; 5012 5013 public static final int ERROR_NO_CHANNEL = 1; 5014 public static final int ERROR_GENERIC = 2; 5015 public static final int ERROR_INCOMPATIBLE_MODE = 3; 5016 public static final int ERROR_TETHERING_DISALLOWED = 4; 5017 5018 /** LocalOnlyHotspot start succeeded. */ onStarted(LocalOnlyHotspotReservation reservation)5019 public void onStarted(LocalOnlyHotspotReservation reservation) {}; 5020 5021 /** 5022 * LocalOnlyHotspot stopped. 5023 * <p> 5024 * The LocalOnlyHotspot can be disabled at any time by the user. When this happens, 5025 * applications will be notified that it was stopped. This will not be invoked when an 5026 * application calls {@link LocalOnlyHotspotReservation#close()}. 5027 */ onStopped()5028 public void onStopped() {}; 5029 5030 /** 5031 * LocalOnlyHotspot failed to start. 5032 * <p> 5033 * Applications can attempt to call 5034 * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} again at 5035 * a later time. 5036 * <p> 5037 * @param reason The reason for failure could be one of: {@link 5038 * #ERROR_TETHERING_DISALLOWED}, {@link #ERROR_INCOMPATIBLE_MODE}, 5039 * {@link #ERROR_NO_CHANNEL}, or {@link #ERROR_GENERIC}. 5040 */ onFailed(int reason)5041 public void onFailed(int reason) { }; 5042 } 5043 5044 /** 5045 * Callback proxy for LocalOnlyHotspotCallback objects. 5046 */ 5047 private static class LocalOnlyHotspotCallbackProxy extends ILocalOnlyHotspotCallback.Stub { 5048 private final WeakReference<WifiManager> mWifiManager; 5049 private final Executor mExecutor; 5050 private final LocalOnlyHotspotCallback mCallback; 5051 5052 /** 5053 * Constructs a {@link LocalOnlyHotspotCallbackProxy} using the specified executor. All 5054 * callbacks will run using the given executor. 5055 * 5056 * @param manager WifiManager 5057 * @param executor Executor for delivering callbacks. 5058 * @param callback LocalOnlyHotspotCallback to notify the calling application, or null. 5059 */ LocalOnlyHotspotCallbackProxy( @onNull WifiManager manager, @NonNull Executor executor, @Nullable LocalOnlyHotspotCallback callback)5060 LocalOnlyHotspotCallbackProxy( 5061 @NonNull WifiManager manager, 5062 @NonNull Executor executor, 5063 @Nullable LocalOnlyHotspotCallback callback) { 5064 mWifiManager = new WeakReference<>(manager); 5065 mExecutor = executor; 5066 mCallback = callback; 5067 } 5068 5069 @Override onHotspotStarted(SoftApConfiguration config)5070 public void onHotspotStarted(SoftApConfiguration config) { 5071 WifiManager manager = mWifiManager.get(); 5072 if (manager == null) return; 5073 5074 if (config == null) { 5075 Log.e(TAG, "LocalOnlyHotspotCallbackProxy: config cannot be null."); 5076 onHotspotFailed(LocalOnlyHotspotCallback.ERROR_GENERIC); 5077 return; 5078 } 5079 final LocalOnlyHotspotReservation reservation = 5080 manager.new LocalOnlyHotspotReservation(config); 5081 if (mCallback == null) return; 5082 mExecutor.execute(() -> mCallback.onStarted(reservation)); 5083 } 5084 5085 @Override onHotspotStopped()5086 public void onHotspotStopped() { 5087 WifiManager manager = mWifiManager.get(); 5088 if (manager == null) return; 5089 5090 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: hotspot stopped"); 5091 if (mCallback == null) return; 5092 mExecutor.execute(() -> mCallback.onStopped()); 5093 } 5094 5095 @Override onHotspotFailed(int reason)5096 public void onHotspotFailed(int reason) { 5097 WifiManager manager = mWifiManager.get(); 5098 if (manager == null) return; 5099 5100 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: failed to start. reason: " 5101 + reason); 5102 if (mCallback == null) return; 5103 mExecutor.execute(() -> mCallback.onFailed(reason)); 5104 } 5105 } 5106 5107 /** 5108 * LocalOnlyHotspotSubscription that is an AutoCloseable object for tracking applications 5109 * watching for LocalOnlyHotspot changes. 5110 * 5111 * @hide 5112 */ 5113 public class LocalOnlyHotspotSubscription implements AutoCloseable { 5114 private final CloseGuard mCloseGuard = new CloseGuard(); 5115 5116 /** @hide */ 5117 @VisibleForTesting LocalOnlyHotspotSubscription()5118 public LocalOnlyHotspotSubscription() { 5119 mCloseGuard.open("close"); 5120 } 5121 5122 @Override close()5123 public void close() { 5124 try { 5125 unregisterLocalOnlyHotspotObserver(); 5126 mCloseGuard.close(); 5127 } catch (Exception e) { 5128 Log.e(TAG, "Failed to unregister LocalOnlyHotspotObserver."); 5129 } finally { 5130 Reference.reachabilityFence(this); 5131 } 5132 } 5133 5134 @Override finalize()5135 protected void finalize() throws Throwable { 5136 try { 5137 if (mCloseGuard != null) { 5138 mCloseGuard.warnIfOpen(); 5139 } 5140 close(); 5141 } finally { 5142 super.finalize(); 5143 } 5144 } 5145 } 5146 5147 /** 5148 * Class to notify calling applications that watch for changes in LocalOnlyHotspot of updates. 5149 * 5150 * @hide 5151 */ 5152 public static class LocalOnlyHotspotObserver { 5153 /** 5154 * Confirm registration for LocalOnlyHotspotChanges by returning a 5155 * LocalOnlyHotspotSubscription. 5156 */ onRegistered(LocalOnlyHotspotSubscription subscription)5157 public void onRegistered(LocalOnlyHotspotSubscription subscription) {}; 5158 5159 /** 5160 * LocalOnlyHotspot started with the supplied config. 5161 */ onStarted(SoftApConfiguration config)5162 public void onStarted(SoftApConfiguration config) {}; 5163 5164 /** 5165 * LocalOnlyHotspot stopped. 5166 */ onStopped()5167 public void onStopped() {}; 5168 } 5169 5170 /** 5171 * Callback proxy for LocalOnlyHotspotObserver objects. 5172 */ 5173 private static class LocalOnlyHotspotObserverProxy extends ILocalOnlyHotspotCallback.Stub { 5174 private final WeakReference<WifiManager> mWifiManager; 5175 private final Executor mExecutor; 5176 private final LocalOnlyHotspotObserver mObserver; 5177 5178 /** 5179 * Constructs a {@link LocalOnlyHotspotObserverProxy} using the specified looper. 5180 * All callbacks will be delivered on the thread of the specified looper. 5181 * 5182 * @param manager WifiManager 5183 * @param executor Executor for delivering callbacks 5184 * @param observer LocalOnlyHotspotObserver to notify the calling application. 5185 */ LocalOnlyHotspotObserverProxy(WifiManager manager, Executor executor, final LocalOnlyHotspotObserver observer)5186 LocalOnlyHotspotObserverProxy(WifiManager manager, Executor executor, 5187 final LocalOnlyHotspotObserver observer) { 5188 mWifiManager = new WeakReference<>(manager); 5189 mExecutor = executor; 5190 mObserver = observer; 5191 } 5192 registered()5193 public void registered() throws RemoteException { 5194 WifiManager manager = mWifiManager.get(); 5195 if (manager == null) return; 5196 5197 mExecutor.execute(() -> 5198 mObserver.onRegistered(manager.new LocalOnlyHotspotSubscription())); 5199 } 5200 5201 @Override onHotspotStarted(SoftApConfiguration config)5202 public void onHotspotStarted(SoftApConfiguration config) { 5203 WifiManager manager = mWifiManager.get(); 5204 if (manager == null) return; 5205 5206 if (config == null) { 5207 Log.e(TAG, "LocalOnlyHotspotObserverProxy: config cannot be null."); 5208 return; 5209 } 5210 mExecutor.execute(() -> mObserver.onStarted(config)); 5211 } 5212 5213 @Override onHotspotStopped()5214 public void onHotspotStopped() { 5215 WifiManager manager = mWifiManager.get(); 5216 if (manager == null) return; 5217 5218 mExecutor.execute(() -> mObserver.onStopped()); 5219 } 5220 5221 @Override onHotspotFailed(int reason)5222 public void onHotspotFailed(int reason) { 5223 // do nothing 5224 } 5225 } 5226 5227 /** 5228 * Callback proxy for ActionListener objects. 5229 */ 5230 private class ActionListenerProxy extends IActionListener.Stub { 5231 private final String mActionTag; 5232 private final Handler mHandler; 5233 private final ActionListener mCallback; 5234 ActionListenerProxy(String actionTag, Looper looper, ActionListener callback)5235 ActionListenerProxy(String actionTag, Looper looper, ActionListener callback) { 5236 mActionTag = actionTag; 5237 mHandler = new Handler(looper); 5238 mCallback = callback; 5239 } 5240 5241 @Override onSuccess()5242 public void onSuccess() { 5243 if (mVerboseLoggingEnabled) { 5244 Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onSuccess"); 5245 } 5246 mHandler.post(() -> { 5247 mCallback.onSuccess(); 5248 }); 5249 } 5250 5251 @Override onFailure(@ctionListenerFailureReason int reason)5252 public void onFailure(@ActionListenerFailureReason int reason) { 5253 if (mVerboseLoggingEnabled) { 5254 Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onFailure=" + reason); 5255 } 5256 mHandler.post(() -> { 5257 mCallback.onFailure(reason); 5258 }); 5259 } 5260 } 5261 connectInternal(@ullable WifiConfiguration config, int networkId, @Nullable ActionListener listener)5262 private void connectInternal(@Nullable WifiConfiguration config, int networkId, 5263 @Nullable ActionListener listener) { 5264 ActionListenerProxy listenerProxy = null; 5265 if (listener != null) { 5266 listenerProxy = new ActionListenerProxy("connect", mLooper, listener); 5267 } 5268 try { 5269 mService.connect(config, networkId, listenerProxy); 5270 } catch (RemoteException e) { 5271 if (listenerProxy != null) listenerProxy.onFailure(ERROR); 5272 } catch (SecurityException e) { 5273 if (listenerProxy != null) listenerProxy.onFailure(NOT_AUTHORIZED); 5274 } 5275 } 5276 5277 /** 5278 * Connect to a network with the given configuration. The network also 5279 * gets added to the list of configured networks for the foreground user. 5280 * 5281 * For a new network, this function is used instead of a 5282 * sequence of addNetwork(), enableNetwork(), and reconnect() 5283 * 5284 * @param config the set of variables that describe the configuration, 5285 * contained in a {@link WifiConfiguration} object. 5286 * @param listener for callbacks on success or failure. Can be null. 5287 * @throws IllegalStateException if the WifiManager instance needs to be 5288 * initialized again 5289 * 5290 * @hide 5291 */ 5292 @SystemApi 5293 @RequiresPermission(anyOf = { 5294 android.Manifest.permission.NETWORK_SETTINGS, 5295 android.Manifest.permission.NETWORK_SETUP_WIZARD, 5296 android.Manifest.permission.NETWORK_STACK 5297 }) connect(@onNull WifiConfiguration config, @Nullable ActionListener listener)5298 public void connect(@NonNull WifiConfiguration config, @Nullable ActionListener listener) { 5299 if (config == null) throw new IllegalArgumentException("config cannot be null"); 5300 connectInternal(config, WifiConfiguration.INVALID_NETWORK_ID, listener); 5301 } 5302 5303 /** 5304 * Connect to a network with the given networkId. 5305 * 5306 * This function is used instead of a enableNetwork() and reconnect() 5307 * 5308 * <li> This API will cause reconnect if the credentials of the current active 5309 * connection has been changed.</li> 5310 * <li> This API will cause reconnect if the current active connection is marked metered.</li> 5311 * 5312 * @param networkId the ID of the network as returned by {@link #addNetwork} or {@link 5313 * getConfiguredNetworks}. 5314 * @param listener for callbacks on success or failure. Can be null. 5315 * @throws IllegalStateException if the WifiManager instance needs to be 5316 * initialized again 5317 * @hide 5318 */ 5319 @SystemApi 5320 @RequiresPermission(anyOf = { 5321 android.Manifest.permission.NETWORK_SETTINGS, 5322 android.Manifest.permission.NETWORK_SETUP_WIZARD, 5323 android.Manifest.permission.NETWORK_STACK 5324 }) connect(int networkId, @Nullable ActionListener listener)5325 public void connect(int networkId, @Nullable ActionListener listener) { 5326 if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 5327 connectInternal(null, networkId, listener); 5328 } 5329 5330 /** 5331 * Temporarily disable autojoin for all currently visible and provisioned (saved, suggested) 5332 * wifi networks except merged carrier networks from the provided subscription ID. 5333 * 5334 * Disabled networks will get automatically re-enabled when they are out of range for a period 5335 * of time, or after the maximum disable duration specified in the framework. 5336 * 5337 * Calling {@link #stopRestrictingAutoJoinToSubscriptionId()} will immediately re-enable 5338 * autojoin on all disabled networks. 5339 * 5340 * @param subscriptionId the subscription ID of the carrier whose merged wifi networks won't be 5341 * disabled {@link android.telephony.SubscriptionInfo#getSubscriptionId()} 5342 * @hide 5343 */ 5344 @SystemApi 5345 @RequiresPermission(anyOf = { 5346 android.Manifest.permission.NETWORK_SETTINGS, 5347 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 5348 @RequiresApi(Build.VERSION_CODES.S) startRestrictingAutoJoinToSubscriptionId(int subscriptionId)5349 public void startRestrictingAutoJoinToSubscriptionId(int subscriptionId) { 5350 try { 5351 mService.startRestrictingAutoJoinToSubscriptionId(subscriptionId); 5352 } catch (RemoteException e) { 5353 throw e.rethrowFromSystemServer(); 5354 } 5355 } 5356 5357 /** 5358 * Re-enable autojoin for all non carrier merged wifi networks temporarily disconnected by 5359 * {@link #startRestrictingAutoJoinToSubscriptionId(int)}. 5360 * @hide 5361 */ 5362 @SystemApi 5363 @RequiresPermission(anyOf = { 5364 android.Manifest.permission.NETWORK_SETTINGS, 5365 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 5366 @RequiresApi(Build.VERSION_CODES.S) stopRestrictingAutoJoinToSubscriptionId()5367 public void stopRestrictingAutoJoinToSubscriptionId() { 5368 try { 5369 mService.stopRestrictingAutoJoinToSubscriptionId(); 5370 } catch (RemoteException e) { 5371 throw e.rethrowFromSystemServer(); 5372 } 5373 } 5374 5375 /** 5376 * Save the given network to the list of configured networks for the 5377 * foreground user. If the network already exists, the configuration 5378 * is updated. Any new network is enabled by default. 5379 * 5380 * For a new network, this function is used instead of a 5381 * sequence of addNetwork() and enableNetwork(). 5382 * 5383 * For an existing network, it accomplishes the task of updateNetwork() 5384 * 5385 * <li> This API will cause reconnect if the credentials of the current active 5386 * connection has been changed.</li> 5387 * <li> This API will cause disconnect if the current active connection is marked metered.</li> 5388 * 5389 * @param config the set of variables that describe the configuration, 5390 * contained in a {@link WifiConfiguration} object. 5391 * @param listener for callbacks on success or failure. Can be null. 5392 * @throws IllegalStateException if the WifiManager instance needs to be 5393 * initialized again 5394 * @hide 5395 */ 5396 @SystemApi 5397 @RequiresPermission(anyOf = { 5398 android.Manifest.permission.NETWORK_SETTINGS, 5399 android.Manifest.permission.NETWORK_SETUP_WIZARD, 5400 android.Manifest.permission.NETWORK_STACK 5401 }) save(@onNull WifiConfiguration config, @Nullable ActionListener listener)5402 public void save(@NonNull WifiConfiguration config, @Nullable ActionListener listener) { 5403 if (config == null) throw new IllegalArgumentException("config cannot be null"); 5404 ActionListenerProxy listenerProxy = null; 5405 if (listener != null) { 5406 listenerProxy = new ActionListenerProxy("save", mLooper, listener); 5407 } 5408 try { 5409 mService.save(config, listenerProxy); 5410 } catch (RemoteException e) { 5411 if (listenerProxy != null) listenerProxy.onFailure(ERROR); 5412 } catch (SecurityException e) { 5413 if (listenerProxy != null) listenerProxy.onFailure(NOT_AUTHORIZED); 5414 } 5415 } 5416 5417 /** 5418 * Delete the network from the list of configured networks for the 5419 * foreground user. 5420 * 5421 * This function is used instead of a sequence of removeNetwork() 5422 * 5423 * @param config the set of variables that describe the configuration, 5424 * contained in a {@link WifiConfiguration} object. 5425 * @param listener for callbacks on success or failure. Can be null. 5426 * @throws IllegalStateException if the WifiManager instance needs to be 5427 * initialized again 5428 * @hide 5429 */ 5430 @SystemApi 5431 @RequiresPermission(anyOf = { 5432 android.Manifest.permission.NETWORK_SETTINGS, 5433 android.Manifest.permission.NETWORK_SETUP_WIZARD, 5434 android.Manifest.permission.NETWORK_STACK 5435 }) forget(int netId, @Nullable ActionListener listener)5436 public void forget(int netId, @Nullable ActionListener listener) { 5437 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 5438 ActionListenerProxy listenerProxy = null; 5439 if (listener != null) { 5440 listenerProxy = new ActionListenerProxy("forget", mLooper, listener); 5441 } 5442 try { 5443 mService.forget(netId, listenerProxy); 5444 } catch (RemoteException e) { 5445 if (listenerProxy != null) listenerProxy.onFailure(ERROR); 5446 } catch (SecurityException e) { 5447 if (listenerProxy != null) listenerProxy.onFailure(NOT_AUTHORIZED); 5448 } 5449 } 5450 5451 /** 5452 * Disable network 5453 * 5454 * @param netId is the network Id 5455 * @param listener for callbacks on success or failure. Can be null. 5456 * @throws IllegalStateException if the WifiManager instance needs to be 5457 * initialized again 5458 * @deprecated This API is deprecated. Use {@link #disableNetwork(int)} instead. 5459 * @hide 5460 */ 5461 @SystemApi 5462 @RequiresPermission(anyOf = { 5463 android.Manifest.permission.NETWORK_SETTINGS, 5464 android.Manifest.permission.NETWORK_SETUP_WIZARD, 5465 android.Manifest.permission.NETWORK_STACK 5466 }) 5467 @Deprecated disable(int netId, @Nullable ActionListener listener)5468 public void disable(int netId, @Nullable ActionListener listener) { 5469 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 5470 // Simple wrapper which forwards the call to disableNetwork. This is a temporary 5471 // implementation until we can remove this API completely. 5472 boolean status = disableNetwork(netId); 5473 if (listener != null) { 5474 if (status) { 5475 listener.onSuccess(); 5476 } else { 5477 listener.onFailure(ERROR); 5478 } 5479 } 5480 } 5481 5482 /** 5483 * Enable/disable auto-join globally. 5484 * 5485 * @param allowAutojoin true to allow auto-join, false to disallow auto-join 5486 * @hide 5487 */ 5488 @SystemApi 5489 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) allowAutojoinGlobal(boolean allowAutojoin)5490 public void allowAutojoinGlobal(boolean allowAutojoin) { 5491 try { 5492 mService.allowAutojoinGlobal(allowAutojoin); 5493 } catch (RemoteException e) { 5494 throw e.rethrowFromSystemServer(); 5495 } 5496 } 5497 5498 5499 /** 5500 * Sets the user choice for allowing auto-join to a network. 5501 * The updated choice will be made available through the updated config supplied by the 5502 * CONFIGURED_NETWORKS_CHANGED broadcast. 5503 * 5504 * @param netId the id of the network to allow/disallow auto-join for. 5505 * @param allowAutojoin true to allow auto-join, false to disallow auto-join 5506 * @hide 5507 */ 5508 @SystemApi 5509 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) allowAutojoin(int netId, boolean allowAutojoin)5510 public void allowAutojoin(int netId, boolean allowAutojoin) { 5511 try { 5512 mService.allowAutojoin(netId, allowAutojoin); 5513 } catch (RemoteException e) { 5514 throw e.rethrowFromSystemServer(); 5515 } 5516 } 5517 5518 /** 5519 * Configure auto-join settings for a Passpoint profile. 5520 * 5521 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 5522 * @param allowAutojoin true to enable auto-join, false to disable auto-join. 5523 * @hide 5524 */ 5525 @SystemApi 5526 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) allowAutojoinPasspoint(@onNull String fqdn, boolean allowAutojoin)5527 public void allowAutojoinPasspoint(@NonNull String fqdn, boolean allowAutojoin) { 5528 try { 5529 mService.allowAutojoinPasspoint(fqdn, allowAutojoin); 5530 } catch (RemoteException e) { 5531 throw e.rethrowFromSystemServer(); 5532 } 5533 } 5534 5535 /** 5536 * Configure MAC randomization setting for a Passpoint profile. 5537 * MAC randomization is enabled by default. 5538 * 5539 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 5540 * @param enable true to enable MAC randomization, false to disable MAC randomization. 5541 * @hide 5542 */ 5543 @SystemApi 5544 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setMacRandomizationSettingPasspointEnabled(@onNull String fqdn, boolean enable)5545 public void setMacRandomizationSettingPasspointEnabled(@NonNull String fqdn, boolean enable) { 5546 try { 5547 mService.setMacRandomizationSettingPasspointEnabled(fqdn, enable); 5548 } catch (RemoteException e) { 5549 throw e.rethrowFromSystemServer(); 5550 } 5551 } 5552 5553 /** 5554 * Sets the user's choice of metered override for a Passpoint profile. 5555 * 5556 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 5557 * @param meteredOverride One of three values: {@link WifiConfiguration#METERED_OVERRIDE_NONE}, 5558 * {@link WifiConfiguration#METERED_OVERRIDE_METERED}, 5559 * {@link WifiConfiguration#METERED_OVERRIDE_NOT_METERED} 5560 * @hide 5561 */ 5562 @SystemApi 5563 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setPasspointMeteredOverride(@onNull String fqdn, @WifiConfiguration.MeteredOverride int meteredOverride)5564 public void setPasspointMeteredOverride(@NonNull String fqdn, 5565 @WifiConfiguration.MeteredOverride int meteredOverride) { 5566 try { 5567 mService.setPasspointMeteredOverride(fqdn, meteredOverride); 5568 } catch (RemoteException e) { 5569 throw e.rethrowFromSystemServer(); 5570 } 5571 } 5572 5573 /** 5574 * Temporarily disable a network. Should always trigger with user disconnect network. 5575 * 5576 * @param network Input can be SSID or FQDN. And caller must ensure that the SSID passed thru 5577 * this API matched the WifiConfiguration.SSID rules, and thus be surrounded by 5578 * quotes. 5579 * @hide 5580 */ 5581 @SystemApi 5582 @RequiresPermission(anyOf = { 5583 android.Manifest.permission.NETWORK_SETTINGS, 5584 android.Manifest.permission.NETWORK_STACK 5585 }) disableEphemeralNetwork(@onNull String network)5586 public void disableEphemeralNetwork(@NonNull String network) { 5587 if (TextUtils.isEmpty(network)) { 5588 throw new IllegalArgumentException("SSID cannot be null or empty!"); 5589 } 5590 try { 5591 mService.disableEphemeralNetwork(network, mContext.getOpPackageName()); 5592 } catch (RemoteException e) { 5593 throw e.rethrowFromSystemServer(); 5594 } 5595 } 5596 5597 /** 5598 * WPS suport has been deprecated from Client mode and this method will immediately trigger 5599 * {@link WpsCallback#onFailed(int)} with a generic error. 5600 * 5601 * @param config WPS configuration (does not support {@link WpsInfo#LABEL}) 5602 * @param listener for callbacks on success or failure. Can be null. 5603 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 5604 * @deprecated This API is deprecated 5605 */ startWps(WpsInfo config, WpsCallback listener)5606 public void startWps(WpsInfo config, WpsCallback listener) { 5607 if (listener != null ) { 5608 listener.onFailed(ERROR); 5609 } 5610 } 5611 5612 /** 5613 * WPS support has been deprecated from Client mode and this method will immediately trigger 5614 * {@link WpsCallback#onFailed(int)} with a generic error. 5615 * 5616 * @param listener for callbacks on success or failure. Can be null. 5617 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 5618 * @deprecated This API is deprecated 5619 */ cancelWps(WpsCallback listener)5620 public void cancelWps(WpsCallback listener) { 5621 if (listener != null) { 5622 listener.onFailed(ERROR); 5623 } 5624 } 5625 5626 /** 5627 * Allows an application to keep the Wi-Fi radio awake. 5628 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 5629 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 5630 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 5631 * WifiLocks are held in any application. 5632 * <p> 5633 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 5634 * could function over a mobile network, if available. A program that needs to download large 5635 * files should hold a WifiLock to ensure that the download will complete, but a program whose 5636 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 5637 * affecting battery life. 5638 * <p> 5639 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 5640 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 5641 * is idle. 5642 * <p> 5643 * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK} 5644 * permission in an {@code <uses-permission>} element of the application's manifest. 5645 */ 5646 public class WifiLock { 5647 private String mTag; 5648 private final IBinder mBinder; 5649 private int mRefCount; 5650 int mLockType; 5651 private boolean mRefCounted; 5652 private boolean mHeld; 5653 private WorkSource mWorkSource; 5654 WifiLock(int lockType, String tag)5655 private WifiLock(int lockType, String tag) { 5656 mTag = tag; 5657 mLockType = lockType; 5658 mBinder = new Binder(); 5659 mRefCount = 0; 5660 mRefCounted = true; 5661 mHeld = false; 5662 } 5663 5664 /** 5665 * Locks the Wi-Fi radio on until {@link #release} is called. 5666 * 5667 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 5668 * reference count, and the radio will remain locked as long as the reference count is 5669 * above zero. 5670 * 5671 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 5672 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 5673 * will be required, regardless of the number of times that {@code acquire} is called. 5674 */ acquire()5675 public void acquire() { 5676 synchronized (mBinder) { 5677 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 5678 try { 5679 mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); 5680 synchronized (WifiManager.this) { 5681 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 5682 mService.releaseWifiLock(mBinder); 5683 throw new UnsupportedOperationException( 5684 "Exceeded maximum number of wifi locks"); 5685 } 5686 mActiveLockCount++; 5687 } 5688 } catch (RemoteException e) { 5689 throw e.rethrowFromSystemServer(); 5690 } 5691 mHeld = true; 5692 } 5693 } 5694 } 5695 5696 /** 5697 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 5698 * 5699 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 5700 * reference count, and the radio will be unlocked only when the reference count reaches 5701 * zero. If the reference count goes below zero (that is, if {@code release} is called 5702 * a greater number of times than {@link #acquire}), an exception is thrown. 5703 * 5704 * If this WifiLock is not reference-counted, the first call to {@code release} (after 5705 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 5706 * calls will be ignored. 5707 */ release()5708 public void release() { 5709 synchronized (mBinder) { 5710 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 5711 try { 5712 mService.releaseWifiLock(mBinder); 5713 synchronized (WifiManager.this) { 5714 mActiveLockCount--; 5715 } 5716 } catch (RemoteException e) { 5717 throw e.rethrowFromSystemServer(); 5718 } 5719 mHeld = false; 5720 } 5721 if (mRefCount < 0) { 5722 throw new RuntimeException("WifiLock under-locked " + mTag); 5723 } 5724 } 5725 } 5726 5727 /** 5728 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 5729 * 5730 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 5731 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 5732 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 5733 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 5734 * radio whenever {@link #release} is called and it is locked. 5735 * 5736 * @param refCounted true if this WifiLock should keep a reference count 5737 */ setReferenceCounted(boolean refCounted)5738 public void setReferenceCounted(boolean refCounted) { 5739 mRefCounted = refCounted; 5740 } 5741 5742 /** 5743 * Checks whether this WifiLock is currently held. 5744 * 5745 * @return true if this WifiLock is held, false otherwise 5746 */ isHeld()5747 public boolean isHeld() { 5748 synchronized (mBinder) { 5749 return mHeld; 5750 } 5751 } 5752 setWorkSource(WorkSource ws)5753 public void setWorkSource(WorkSource ws) { 5754 synchronized (mBinder) { 5755 if (ws != null && ws.isEmpty()) { 5756 ws = null; 5757 } 5758 boolean changed = true; 5759 if (ws == null) { 5760 mWorkSource = null; 5761 } else { 5762 ws = ws.withoutNames(); 5763 if (mWorkSource == null) { 5764 changed = mWorkSource != null; 5765 mWorkSource = new WorkSource(ws); 5766 } else { 5767 changed = !mWorkSource.equals(ws); 5768 if (changed) { 5769 mWorkSource.set(ws); 5770 } 5771 } 5772 } 5773 if (changed && mHeld) { 5774 try { 5775 mService.updateWifiLockWorkSource(mBinder, mWorkSource); 5776 } catch (RemoteException e) { 5777 throw e.rethrowFromSystemServer(); 5778 } 5779 } 5780 } 5781 } 5782 toString()5783 public String toString() { 5784 String s1, s2, s3; 5785 synchronized (mBinder) { 5786 s1 = Integer.toHexString(System.identityHashCode(this)); 5787 s2 = mHeld ? "held; " : ""; 5788 if (mRefCounted) { 5789 s3 = "refcounted: refcount = " + mRefCount; 5790 } else { 5791 s3 = "not refcounted"; 5792 } 5793 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 5794 } 5795 } 5796 5797 @Override finalize()5798 protected void finalize() throws Throwable { 5799 super.finalize(); 5800 synchronized (mBinder) { 5801 if (mHeld) { 5802 try { 5803 mService.releaseWifiLock(mBinder); 5804 synchronized (WifiManager.this) { 5805 mActiveLockCount--; 5806 } 5807 } catch (RemoteException e) { 5808 throw e.rethrowFromSystemServer(); 5809 } 5810 } 5811 } 5812 } 5813 } 5814 5815 /** 5816 * Creates a new WifiLock. 5817 * 5818 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL_HIGH_PERF} 5819 * and {@link #WIFI_MODE_FULL_LOW_LATENCY} for descriptions of the types of Wi-Fi locks. 5820 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 5821 * never shown to the user under normal conditions, but should be descriptive 5822 * enough to identify your application and the specific WifiLock within it, if it 5823 * holds multiple WifiLocks. 5824 * 5825 * @return a new, unacquired WifiLock with the given tag. 5826 * 5827 * @see WifiLock 5828 */ createWifiLock(int lockType, String tag)5829 public WifiLock createWifiLock(int lockType, String tag) { 5830 return new WifiLock(lockType, tag); 5831 } 5832 5833 /** 5834 * Creates a new WifiLock. 5835 * 5836 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 5837 * never shown to the user under normal conditions, but should be descriptive 5838 * enough to identify your application and the specific WifiLock within it, if it 5839 * holds multiple WifiLocks. 5840 * 5841 * @return a new, unacquired WifiLock with the given tag. 5842 * 5843 * @see WifiLock 5844 * 5845 * @deprecated This API is non-functional. 5846 */ 5847 @Deprecated createWifiLock(String tag)5848 public WifiLock createWifiLock(String tag) { 5849 return new WifiLock(WIFI_MODE_FULL, tag); 5850 } 5851 5852 /** 5853 * Create a new MulticastLock 5854 * 5855 * @param tag a tag for the MulticastLock to identify it in debugging 5856 * messages. This string is never shown to the user under 5857 * normal conditions, but should be descriptive enough to 5858 * identify your application and the specific MulticastLock 5859 * within it, if it holds multiple MulticastLocks. 5860 * 5861 * @return a new, unacquired MulticastLock with the given tag. 5862 * 5863 * @see MulticastLock 5864 */ createMulticastLock(String tag)5865 public MulticastLock createMulticastLock(String tag) { 5866 return new MulticastLock(tag); 5867 } 5868 5869 /** 5870 * Allows an application to receive Wifi Multicast packets. 5871 * Normally the Wifi stack filters out packets not explicitly 5872 * addressed to this device. Acquring a MulticastLock will 5873 * cause the stack to receive packets addressed to multicast 5874 * addresses. Processing these extra packets can cause a noticeable 5875 * battery drain and should be disabled when not needed. 5876 */ 5877 public class MulticastLock { 5878 private String mTag; 5879 private final IBinder mBinder; 5880 private int mRefCount; 5881 private boolean mRefCounted; 5882 private boolean mHeld; 5883 MulticastLock(String tag)5884 private MulticastLock(String tag) { 5885 mTag = tag; 5886 mBinder = new Binder(); 5887 mRefCount = 0; 5888 mRefCounted = true; 5889 mHeld = false; 5890 } 5891 5892 /** 5893 * Locks Wifi Multicast on until {@link #release} is called. 5894 * 5895 * If this MulticastLock is reference-counted each call to 5896 * {@code acquire} will increment the reference count, and the 5897 * wifi interface will receive multicast packets as long as the 5898 * reference count is above zero. 5899 * 5900 * If this MulticastLock is not reference-counted, the first call to 5901 * {@code acquire} will turn on the multicast packets, but subsequent 5902 * calls will be ignored. Only one call to {@link #release} will 5903 * be required, regardless of the number of times that {@code acquire} 5904 * is called. 5905 * 5906 * Note that other applications may also lock Wifi Multicast on. 5907 * Only they can relinquish their lock. 5908 * 5909 * Also note that applications cannot leave Multicast locked on. 5910 * When an app exits or crashes, any Multicast locks will be released. 5911 */ acquire()5912 public void acquire() { 5913 synchronized (mBinder) { 5914 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 5915 try { 5916 mService.acquireMulticastLock(mBinder, mTag); 5917 synchronized (WifiManager.this) { 5918 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 5919 mService.releaseMulticastLock(mTag); 5920 throw new UnsupportedOperationException( 5921 "Exceeded maximum number of wifi locks"); 5922 } 5923 mActiveLockCount++; 5924 } 5925 } catch (RemoteException e) { 5926 throw e.rethrowFromSystemServer(); 5927 } 5928 mHeld = true; 5929 } 5930 } 5931 } 5932 5933 /** 5934 * Unlocks Wifi Multicast, restoring the filter of packets 5935 * not addressed specifically to this device and saving power. 5936 * 5937 * If this MulticastLock is reference-counted, each call to 5938 * {@code release} will decrement the reference count, and the 5939 * multicast packets will only stop being received when the reference 5940 * count reaches zero. If the reference count goes below zero (that 5941 * is, if {@code release} is called a greater number of times than 5942 * {@link #acquire}), an exception is thrown. 5943 * 5944 * If this MulticastLock is not reference-counted, the first call to 5945 * {@code release} (after the radio was multicast locked using 5946 * {@link #acquire}) will unlock the multicast, and subsequent calls 5947 * will be ignored. 5948 * 5949 * Note that if any other Wifi Multicast Locks are still outstanding 5950 * this {@code release} call will not have an immediate effect. Only 5951 * when all applications have released all their Multicast Locks will 5952 * the Multicast filter be turned back on. 5953 * 5954 * Also note that when an app exits or crashes all of its Multicast 5955 * Locks will be automatically released. 5956 */ release()5957 public void release() { 5958 synchronized (mBinder) { 5959 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 5960 try { 5961 mService.releaseMulticastLock(mTag); 5962 synchronized (WifiManager.this) { 5963 mActiveLockCount--; 5964 } 5965 } catch (RemoteException e) { 5966 throw e.rethrowFromSystemServer(); 5967 } 5968 mHeld = false; 5969 } 5970 if (mRefCount < 0) { 5971 throw new RuntimeException("MulticastLock under-locked " 5972 + mTag); 5973 } 5974 } 5975 } 5976 5977 /** 5978 * Controls whether this is a reference-counted or non-reference- 5979 * counted MulticastLock. 5980 * 5981 * Reference-counted MulticastLocks keep track of the number of calls 5982 * to {@link #acquire} and {@link #release}, and only stop the 5983 * reception of multicast packets when every call to {@link #acquire} 5984 * has been balanced with a call to {@link #release}. Non-reference- 5985 * counted MulticastLocks allow the reception of multicast packets 5986 * whenever {@link #acquire} is called and stop accepting multicast 5987 * packets whenever {@link #release} is called. 5988 * 5989 * @param refCounted true if this MulticastLock should keep a reference 5990 * count 5991 */ setReferenceCounted(boolean refCounted)5992 public void setReferenceCounted(boolean refCounted) { 5993 mRefCounted = refCounted; 5994 } 5995 5996 /** 5997 * Checks whether this MulticastLock is currently held. 5998 * 5999 * @return true if this MulticastLock is held, false otherwise 6000 */ isHeld()6001 public boolean isHeld() { 6002 synchronized (mBinder) { 6003 return mHeld; 6004 } 6005 } 6006 toString()6007 public String toString() { 6008 String s1, s2, s3; 6009 synchronized (mBinder) { 6010 s1 = Integer.toHexString(System.identityHashCode(this)); 6011 s2 = mHeld ? "held; " : ""; 6012 if (mRefCounted) { 6013 s3 = "refcounted: refcount = " + mRefCount; 6014 } else { 6015 s3 = "not refcounted"; 6016 } 6017 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 6018 } 6019 } 6020 6021 @Override finalize()6022 protected void finalize() throws Throwable { 6023 super.finalize(); 6024 setReferenceCounted(false); 6025 release(); 6026 } 6027 } 6028 6029 /** 6030 * Check multicast filter status. 6031 * 6032 * @return true if multicast packets are allowed. 6033 * 6034 * @hide pending API council approval 6035 */ isMulticastEnabled()6036 public boolean isMulticastEnabled() { 6037 try { 6038 return mService.isMulticastEnabled(); 6039 } catch (RemoteException e) { 6040 throw e.rethrowFromSystemServer(); 6041 } 6042 } 6043 6044 /** 6045 * Initialize the multicast filtering to 'on' 6046 * @hide no intent to publish 6047 */ 6048 @UnsupportedAppUsage initializeMulticastFiltering()6049 public boolean initializeMulticastFiltering() { 6050 try { 6051 mService.initializeMulticastFiltering(); 6052 return true; 6053 } catch (RemoteException e) { 6054 throw e.rethrowFromSystemServer(); 6055 } 6056 } 6057 6058 /** 6059 * Set Wi-Fi verbose logging level from developer settings. 6060 * 6061 * @param enable true to enable verbose logging, false to disable. 6062 * 6063 * @hide 6064 */ 6065 @SystemApi 6066 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setVerboseLoggingEnabled(boolean enable)6067 public void setVerboseLoggingEnabled(boolean enable) { 6068 enableVerboseLogging(enable ? VERBOSE_LOGGING_LEVEL_ENABLED 6069 : VERBOSE_LOGGING_LEVEL_DISABLED); 6070 } 6071 6072 /** 6073 * Set Wi-Fi verbose logging level from developer settings. 6074 * 6075 * @param verbose the verbose logging mode which could be 6076 * {@link #VERBOSE_LOGGING_LEVEL_DISABLED}, {@link #VERBOSE_LOGGING_LEVEL_ENABLED}, or 6077 * {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}. 6078 * 6079 * @hide 6080 */ 6081 @SystemApi 6082 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setVerboseLoggingLevel(@erboseLoggingLevel int verbose)6083 public void setVerboseLoggingLevel(@VerboseLoggingLevel int verbose) { 6084 enableVerboseLogging(verbose); 6085 } 6086 6087 /** @hide */ 6088 @UnsupportedAppUsage( 6089 maxTargetSdk = Build.VERSION_CODES.Q, 6090 publicAlternatives = "Use {@code #setVerboseLoggingEnabled(boolean)} instead." 6091 ) 6092 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) enableVerboseLogging(@erboseLoggingLevel int verbose)6093 public void enableVerboseLogging(@VerboseLoggingLevel int verbose) { 6094 try { 6095 mService.enableVerboseLogging(verbose); 6096 } catch (RemoteException e) { 6097 throw e.rethrowFromSystemServer(); 6098 } 6099 } 6100 6101 /** 6102 * Get the persisted Wi-Fi verbose logging level, set by 6103 * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}. 6104 * No permissions are required to call this method. 6105 * 6106 * @return true to indicate that verbose logging is enabled, false to indicate that verbose 6107 * logging is disabled. 6108 * 6109 * @hide 6110 */ 6111 @SystemApi isVerboseLoggingEnabled()6112 public boolean isVerboseLoggingEnabled() { 6113 return getVerboseLoggingLevel() > 0; 6114 } 6115 6116 /** 6117 * Get the persisted Wi-Fi verbose logging level, set by 6118 * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}. 6119 * No permissions are required to call this method. 6120 * 6121 * @return one of {@link #VERBOSE_LOGGING_LEVEL_DISABLED}, 6122 * {@link #VERBOSE_LOGGING_LEVEL_ENABLED}, 6123 * or {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}. 6124 * 6125 * @hide 6126 */ 6127 @SystemApi getVerboseLoggingLevel()6128 public @VerboseLoggingLevel int getVerboseLoggingLevel() { 6129 try { 6130 return mService.getVerboseLoggingLevel(); 6131 } catch (RemoteException e) { 6132 throw e.rethrowFromSystemServer(); 6133 } 6134 } 6135 6136 /** 6137 * Removes all saved Wi-Fi networks, Passpoint configurations, ephemeral networks, Network 6138 * Requests, and Network Suggestions. 6139 * 6140 * @hide 6141 */ 6142 @SystemApi 6143 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) factoryReset()6144 public void factoryReset() { 6145 try { 6146 mService.factoryReset(mContext.getOpPackageName()); 6147 } catch (RemoteException e) { 6148 throw e.rethrowFromSystemServer(); 6149 } 6150 } 6151 6152 /** 6153 * Get {@link Network} object of current wifi network, or null if not connected. 6154 * @hide 6155 */ 6156 @Nullable 6157 @SystemApi 6158 @RequiresPermission(anyOf = { 6159 android.Manifest.permission.NETWORK_SETTINGS, 6160 android.Manifest.permission.NETWORK_SETUP_WIZARD 6161 }) getCurrentNetwork()6162 public Network getCurrentNetwork() { 6163 try { 6164 return mService.getCurrentNetwork(); 6165 } catch (RemoteException e) { 6166 throw e.rethrowFromSystemServer(); 6167 } 6168 } 6169 6170 /** 6171 * Deprecated 6172 * returns false 6173 * @hide 6174 * @deprecated 6175 */ setEnableAutoJoinWhenAssociated(boolean enabled)6176 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 6177 return false; 6178 } 6179 6180 /** 6181 * Deprecated 6182 * returns false 6183 * @hide 6184 * @deprecated 6185 */ getEnableAutoJoinWhenAssociated()6186 public boolean getEnableAutoJoinWhenAssociated() { 6187 return false; 6188 } 6189 6190 /** 6191 * Returns a byte stream representing the data that needs to be backed up to save the 6192 * current Wifi state. 6193 * This Wifi state can be restored by calling {@link #restoreBackupData(byte[])}. 6194 * @hide 6195 */ 6196 @NonNull 6197 @SystemApi 6198 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) retrieveBackupData()6199 public byte[] retrieveBackupData() { 6200 try { 6201 return mService.retrieveBackupData(); 6202 } catch (RemoteException e) { 6203 throw e.rethrowFromSystemServer(); 6204 } 6205 } 6206 6207 /** 6208 * Restore state from the backed up data. 6209 * @param data byte stream in the same format produced by {@link #retrieveBackupData()} 6210 * @hide 6211 */ 6212 @SystemApi 6213 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreBackupData(@onNull byte[] data)6214 public void restoreBackupData(@NonNull byte[] data) { 6215 try { 6216 mService.restoreBackupData(data); 6217 } catch (RemoteException e) { 6218 throw e.rethrowFromSystemServer(); 6219 } 6220 } 6221 6222 /** 6223 * Returns a byte stream representing the data that needs to be backed up to save the 6224 * current soft ap config data. 6225 * 6226 * This soft ap config can be restored by calling {@link #restoreSoftApBackupData(byte[])} 6227 * @hide 6228 */ 6229 @NonNull 6230 @SystemApi 6231 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) retrieveSoftApBackupData()6232 public byte[] retrieveSoftApBackupData() { 6233 try { 6234 return mService.retrieveSoftApBackupData(); 6235 } catch (RemoteException e) { 6236 throw e.rethrowFromSystemServer(); 6237 } 6238 } 6239 6240 /** 6241 * Returns soft ap config from the backed up data or null if data is invalid. 6242 * @param data byte stream in the same format produced by {@link #retrieveSoftApBackupData()} 6243 * 6244 * @hide 6245 */ 6246 @Nullable 6247 @SystemApi 6248 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreSoftApBackupData(@onNull byte[] data)6249 public SoftApConfiguration restoreSoftApBackupData(@NonNull byte[] data) { 6250 try { 6251 return mService.restoreSoftApBackupData(data); 6252 } catch (RemoteException e) { 6253 throw e.rethrowFromSystemServer(); 6254 } 6255 } 6256 6257 /** 6258 * Restore state from the older version of back up data. 6259 * The old backup data was essentially a backup of wpa_supplicant.conf 6260 * and ipconfig.txt file. 6261 * @param supplicantData bytes representing wpa_supplicant.conf 6262 * @param ipConfigData bytes representing ipconfig.txt 6263 * @hide 6264 */ 6265 @SystemApi 6266 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreSupplicantBackupData( @onNull byte[] supplicantData, @NonNull byte[] ipConfigData)6267 public void restoreSupplicantBackupData( 6268 @NonNull byte[] supplicantData, @NonNull byte[] ipConfigData) { 6269 try { 6270 mService.restoreSupplicantBackupData(supplicantData, ipConfigData); 6271 } catch (RemoteException e) { 6272 throw e.rethrowFromSystemServer(); 6273 } 6274 } 6275 6276 /** 6277 * Start subscription provisioning flow 6278 * 6279 * @param provider {@link OsuProvider} to provision with 6280 * @param executor the Executor on which to run the callback. 6281 * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow 6282 * @hide 6283 */ 6284 @SystemApi 6285 @RequiresPermission(anyOf = { 6286 android.Manifest.permission.NETWORK_SETTINGS, 6287 android.Manifest.permission.NETWORK_SETUP_WIZARD 6288 }) startSubscriptionProvisioning(@onNull OsuProvider provider, @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback)6289 public void startSubscriptionProvisioning(@NonNull OsuProvider provider, 6290 @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback) { 6291 // Verify arguments 6292 if (executor == null) { 6293 throw new IllegalArgumentException("executor must not be null"); 6294 } 6295 if (callback == null) { 6296 throw new IllegalArgumentException("callback must not be null"); 6297 } 6298 try { 6299 mService.startSubscriptionProvisioning(provider, 6300 new ProvisioningCallbackProxy(executor, callback)); 6301 } catch (RemoteException e) { 6302 throw e.rethrowFromSystemServer(); 6303 } 6304 } 6305 6306 /** 6307 * Helper class to support OSU Provisioning callbacks 6308 */ 6309 private static class ProvisioningCallbackProxy extends IProvisioningCallback.Stub { 6310 private final Executor mExecutor; 6311 private final ProvisioningCallback mCallback; 6312 ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback)6313 ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback) { 6314 mExecutor = executor; 6315 mCallback = callback; 6316 } 6317 6318 @Override onProvisioningStatus(int status)6319 public void onProvisioningStatus(int status) { 6320 mExecutor.execute(() -> mCallback.onProvisioningStatus(status)); 6321 } 6322 6323 @Override onProvisioningFailure(int status)6324 public void onProvisioningFailure(int status) { 6325 mExecutor.execute(() -> mCallback.onProvisioningFailure(status)); 6326 } 6327 6328 @Override onProvisioningComplete()6329 public void onProvisioningComplete() { 6330 mExecutor.execute(() -> mCallback.onProvisioningComplete()); 6331 } 6332 } 6333 6334 /** 6335 * Interface for Traffic state callback. Should be extended by applications and set when 6336 * calling {@link #registerTrafficStateCallback(Executor, WifiManager.TrafficStateCallback)}. 6337 * @hide 6338 */ 6339 @SystemApi 6340 public interface TrafficStateCallback { 6341 /** @hide */ 6342 @Retention(RetentionPolicy.SOURCE) 6343 @IntDef(prefix = {"DATA_ACTIVITY_"}, value = { 6344 DATA_ACTIVITY_NONE, 6345 DATA_ACTIVITY_IN, 6346 DATA_ACTIVITY_OUT, 6347 DATA_ACTIVITY_INOUT}) 6348 @interface DataActivity {} 6349 6350 // Lowest bit indicates data reception and the second lowest bit indicates data transmitted 6351 /** No data in or out */ 6352 int DATA_ACTIVITY_NONE = 0x00; 6353 /** Data in, no data out */ 6354 int DATA_ACTIVITY_IN = 0x01; 6355 /** Data out, no data in */ 6356 int DATA_ACTIVITY_OUT = 0x02; 6357 /** Data in and out */ 6358 int DATA_ACTIVITY_INOUT = 0x03; 6359 6360 /** 6361 * Callback invoked to inform clients about the current traffic state. 6362 * 6363 * @param state One of the values: {@link #DATA_ACTIVITY_NONE}, {@link #DATA_ACTIVITY_IN}, 6364 * {@link #DATA_ACTIVITY_OUT} & {@link #DATA_ACTIVITY_INOUT}. 6365 */ onStateChanged(@ataActivity int state)6366 void onStateChanged(@DataActivity int state); 6367 } 6368 6369 /** 6370 * Callback proxy for TrafficStateCallback objects. 6371 * 6372 * @hide 6373 */ 6374 private class TrafficStateCallbackProxy extends ITrafficStateCallback.Stub { 6375 private final Executor mExecutor; 6376 private final TrafficStateCallback mCallback; 6377 TrafficStateCallbackProxy(Executor executor, TrafficStateCallback callback)6378 TrafficStateCallbackProxy(Executor executor, TrafficStateCallback callback) { 6379 mExecutor = executor; 6380 mCallback = callback; 6381 } 6382 6383 @Override onStateChanged(int state)6384 public void onStateChanged(int state) { 6385 if (mVerboseLoggingEnabled) { 6386 Log.v(TAG, "TrafficStateCallbackProxy: onStateChanged state=" + state); 6387 } 6388 Binder.clearCallingIdentity(); 6389 mExecutor.execute(() -> { 6390 mCallback.onStateChanged(state); 6391 }); 6392 } 6393 } 6394 6395 /** 6396 * Registers a callback for monitoring traffic state. See {@link TrafficStateCallback}. These 6397 * callbacks will be invoked periodically by platform to inform clients about the current 6398 * traffic state. Caller can unregister a previously registered callback using 6399 * {@link #unregisterTrafficStateCallback(TrafficStateCallback)} 6400 * <p> 6401 * Applications should have the 6402 * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers 6403 * without the permission will trigger a {@link java.lang.SecurityException}. 6404 * <p> 6405 * 6406 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 6407 * object. 6408 * @param callback Callback for traffic state events 6409 * @hide 6410 */ 6411 @SystemApi 6412 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) registerTrafficStateCallback(@onNull @allbackExecutor Executor executor, @NonNull TrafficStateCallback callback)6413 public void registerTrafficStateCallback(@NonNull @CallbackExecutor Executor executor, 6414 @NonNull TrafficStateCallback callback) { 6415 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 6416 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 6417 Log.v(TAG, "registerTrafficStateCallback: callback=" + callback + ", executor=" + executor); 6418 6419 try { 6420 synchronized (sTrafficStateCallbackMap) { 6421 ITrafficStateCallback.Stub binderCallback = new TrafficStateCallbackProxy(executor, 6422 callback); 6423 sTrafficStateCallbackMap.put(System.identityHashCode(callback), binderCallback); 6424 mService.registerTrafficStateCallback(binderCallback); 6425 } 6426 } catch (RemoteException e) { 6427 throw e.rethrowFromSystemServer(); 6428 } 6429 } 6430 6431 /** 6432 * Allow callers to unregister a previously registered callback. After calling this method, 6433 * applications will no longer receive traffic state notifications. 6434 * 6435 * @param callback Callback to unregister for traffic state events 6436 * @hide 6437 */ 6438 @SystemApi 6439 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) unregisterTrafficStateCallback(@onNull TrafficStateCallback callback)6440 public void unregisterTrafficStateCallback(@NonNull TrafficStateCallback callback) { 6441 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 6442 Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback); 6443 6444 try { 6445 synchronized (sTrafficStateCallbackMap) { 6446 int callbackIdentifier = System.identityHashCode(callback); 6447 if (!sTrafficStateCallbackMap.contains(callbackIdentifier)) { 6448 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 6449 return; 6450 } 6451 mService.unregisterTrafficStateCallback( 6452 sTrafficStateCallbackMap.get(callbackIdentifier)); 6453 sTrafficStateCallbackMap.remove(callbackIdentifier); 6454 } 6455 } catch (RemoteException e) { 6456 throw e.rethrowFromSystemServer(); 6457 } 6458 } 6459 6460 /** 6461 * Helper method to update the local verbose logging flag based on the verbose logging 6462 * level from wifi service. 6463 */ updateVerboseLoggingEnabledFromService()6464 private void updateVerboseLoggingEnabledFromService() { 6465 mVerboseLoggingEnabled = isVerboseLoggingEnabled(); 6466 } 6467 6468 /** 6469 * @return true if this device supports WPA3-Personal SAE 6470 */ isWpa3SaeSupported()6471 public boolean isWpa3SaeSupported() { 6472 return isFeatureSupported(WIFI_FEATURE_WPA3_SAE); 6473 } 6474 6475 /** 6476 * @return true if this device supports WPA3-Enterprise Suite-B-192 6477 */ isWpa3SuiteBSupported()6478 public boolean isWpa3SuiteBSupported() { 6479 return isFeatureSupported(WIFI_FEATURE_WPA3_SUITE_B); 6480 } 6481 6482 /** 6483 * @return true if this device supports Wi-Fi Enhanced Open (OWE) 6484 */ isEnhancedOpenSupported()6485 public boolean isEnhancedOpenSupported() { 6486 return isFeatureSupported(WIFI_FEATURE_OWE); 6487 } 6488 6489 /** 6490 * Wi-Fi Easy Connect (DPP) introduces standardized mechanisms to simplify the provisioning and 6491 * configuration of Wi-Fi devices. 6492 * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and 6493 * search for "Easy Connect" or "Device Provisioning Protocol specification". 6494 * 6495 * @return true if this device supports Wi-Fi Easy-connect (Device Provisioning Protocol) 6496 */ isEasyConnectSupported()6497 public boolean isEasyConnectSupported() { 6498 return isFeatureSupported(WIFI_FEATURE_DPP); 6499 } 6500 6501 /** 6502 * @return true if this device supports Wi-Fi Easy Connect (DPP) Enrollee Responder mode. 6503 */ isEasyConnectEnrolleeResponderModeSupported()6504 public boolean isEasyConnectEnrolleeResponderModeSupported() { 6505 return isFeatureSupported(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER); 6506 } 6507 6508 /** 6509 * @return true if this device supports WAPI. 6510 */ isWapiSupported()6511 public boolean isWapiSupported() { 6512 return isFeatureSupported(WIFI_FEATURE_WAPI); 6513 } 6514 6515 /** 6516 * @return true if this device supports WPA3 SAE Public Key. 6517 */ isWpa3SaePublicKeySupported()6518 public boolean isWpa3SaePublicKeySupported() { 6519 // This feature is not fully implemented in the framework yet. 6520 // After the feature complete, it returns whether WIFI_FEATURE_SAE_PK 6521 // is supported or not directly. 6522 return false; 6523 } 6524 6525 /** 6526 * @return true if this device supports Wi-Fi Passpoint Terms and Conditions feature. 6527 */ isPasspointTermsAndConditionsSupported()6528 public boolean isPasspointTermsAndConditionsSupported() { 6529 return isFeatureSupported(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS); 6530 } 6531 6532 /** 6533 * @return true if this device supports WPA3 SAE Hash-to-Element. 6534 */ isWpa3SaeH2eSupported()6535 public boolean isWpa3SaeH2eSupported() { 6536 return isFeatureSupported(WIFI_FEATURE_SAE_H2E); 6537 } 6538 6539 /** 6540 * @return true if this device supports Wi-Fi Display R2. 6541 */ isWifiDisplayR2Supported()6542 public boolean isWifiDisplayR2Supported() { 6543 return isFeatureSupported(WIFI_FEATURE_WFD_R2); 6544 } 6545 6546 /** 6547 * @return true if this device supports RFC 7542 decorated identity. 6548 */ isDecoratedIdentitySupported()6549 public boolean isDecoratedIdentitySupported() { 6550 return isFeatureSupported(WIFI_FEATURE_DECORATED_IDENTITY); 6551 } 6552 6553 /** 6554 * Gets the factory Wi-Fi MAC addresses. 6555 * @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array 6556 * if failed. 6557 * @hide 6558 */ 6559 @NonNull 6560 @SystemApi 6561 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) getFactoryMacAddresses()6562 public String[] getFactoryMacAddresses() { 6563 try { 6564 return mService.getFactoryMacAddresses(); 6565 } catch (RemoteException e) { 6566 throw e.rethrowFromSystemServer(); 6567 } 6568 } 6569 6570 /** @hide */ 6571 @Retention(RetentionPolicy.SOURCE) 6572 @IntDef(prefix = {"DEVICE_MOBILITY_STATE_"}, value = { 6573 DEVICE_MOBILITY_STATE_UNKNOWN, 6574 DEVICE_MOBILITY_STATE_HIGH_MVMT, 6575 DEVICE_MOBILITY_STATE_LOW_MVMT, 6576 DEVICE_MOBILITY_STATE_STATIONARY}) 6577 public @interface DeviceMobilityState {} 6578 6579 /** 6580 * Unknown device mobility state 6581 * 6582 * @see #setDeviceMobilityState(int) 6583 * 6584 * @hide 6585 */ 6586 @SystemApi 6587 public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0; 6588 6589 /** 6590 * High movement device mobility state. 6591 * e.g. on a bike, in a motor vehicle 6592 * 6593 * @see #setDeviceMobilityState(int) 6594 * 6595 * @hide 6596 */ 6597 @SystemApi 6598 public static final int DEVICE_MOBILITY_STATE_HIGH_MVMT = 1; 6599 6600 /** 6601 * Low movement device mobility state. 6602 * e.g. walking, running 6603 * 6604 * @see #setDeviceMobilityState(int) 6605 * 6606 * @hide 6607 */ 6608 @SystemApi 6609 public static final int DEVICE_MOBILITY_STATE_LOW_MVMT = 2; 6610 6611 /** 6612 * Stationary device mobility state 6613 * 6614 * @see #setDeviceMobilityState(int) 6615 * 6616 * @hide 6617 */ 6618 @SystemApi 6619 public static final int DEVICE_MOBILITY_STATE_STATIONARY = 3; 6620 6621 /** 6622 * Updates the device mobility state. Wifi uses this information to adjust the interval between 6623 * Wifi scans in order to balance power consumption with scan accuracy. 6624 * The default mobility state when the device boots is {@link #DEVICE_MOBILITY_STATE_UNKNOWN}. 6625 * This API should be called whenever there is a change in the mobility state. 6626 * @param state the updated device mobility state 6627 * @hide 6628 */ 6629 @SystemApi 6630 @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) setDeviceMobilityState(@eviceMobilityState int state)6631 public void setDeviceMobilityState(@DeviceMobilityState int state) { 6632 try { 6633 mService.setDeviceMobilityState(state); 6634 } catch (RemoteException e) { 6635 throw e.rethrowFromSystemServer(); 6636 } 6637 } 6638 6639 /* Easy Connect - AKA Device Provisioning Protocol (DPP) */ 6640 6641 /** 6642 * Easy Connect Network role: Station. 6643 * 6644 * @hide 6645 */ 6646 @SystemApi 6647 public static final int EASY_CONNECT_NETWORK_ROLE_STA = 0; 6648 6649 /** 6650 * Easy Connect Network role: Access Point. 6651 * 6652 * @hide 6653 */ 6654 @SystemApi 6655 public static final int EASY_CONNECT_NETWORK_ROLE_AP = 1; 6656 6657 /** @hide */ 6658 @IntDef(prefix = {"EASY_CONNECT_NETWORK_ROLE_"}, value = { 6659 EASY_CONNECT_NETWORK_ROLE_STA, 6660 EASY_CONNECT_NETWORK_ROLE_AP, 6661 }) 6662 @Retention(RetentionPolicy.SOURCE) 6663 public @interface EasyConnectNetworkRole { 6664 } 6665 6666 /** Easy Connect Device information maximum allowed length */ 6667 private static final int EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH = 40; 6668 6669 /** 6670 * Easy Connect Cryptography Curve name: prime256v1 6671 * 6672 * @hide 6673 */ 6674 @SystemApi 6675 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1 = 0; 6676 6677 /** 6678 * Easy Connect Cryptography Curve name: secp384r1 6679 * 6680 * @hide 6681 */ 6682 @SystemApi 6683 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1 = 1; 6684 6685 /** 6686 * Easy Connect Cryptography Curve name: secp521r1 6687 * 6688 * @hide 6689 */ 6690 @SystemApi 6691 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1 = 2; 6692 6693 6694 /** 6695 * Easy Connect Cryptography Curve name: brainpoolP256r1 6696 * 6697 * @hide 6698 */ 6699 @SystemApi 6700 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1 = 3; 6701 6702 6703 /** 6704 * Easy Connect Cryptography Curve name: brainpoolP384r1 6705 * 6706 * @hide 6707 */ 6708 @SystemApi 6709 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1 = 4; 6710 6711 6712 /** 6713 * Easy Connect Cryptography Curve name: brainpoolP512r1 6714 * 6715 * @hide 6716 */ 6717 @SystemApi 6718 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1 = 5; 6719 6720 /** @hide */ 6721 @IntDef(prefix = {"EASY_CONNECT_CRYPTOGRAPHY_CURVE_"}, value = { 6722 EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1, 6723 EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1, 6724 EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1, 6725 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1, 6726 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1, 6727 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1, 6728 }) 6729 @Retention(RetentionPolicy.SOURCE) 6730 public @interface EasyConnectCryptographyCurve { 6731 } 6732 6733 /** 6734 * Verbose logging mode: DISABLED. 6735 * @hide 6736 */ 6737 @SystemApi 6738 public static final int VERBOSE_LOGGING_LEVEL_DISABLED = 0; 6739 6740 /** 6741 * Verbose logging mode: ENABLED. 6742 * @hide 6743 */ 6744 @SystemApi 6745 public static final int VERBOSE_LOGGING_LEVEL_ENABLED = 1; 6746 6747 /** 6748 * Verbose logging mode: ENABLED_SHOW_KEY. 6749 * This mode causes the Wi-Fi password and encryption keys to be output to the logcat. 6750 * This is security sensitive information useful for debugging. 6751 * This configuration is enabled for 30 seconds and then falls back to 6752 * the regular verbose mode (i.e. to {@link VERBOSE_LOGGING_LEVEL_ENABLED}). 6753 * Show key mode is not persistent, i.e. rebooting the device would fallback to 6754 * the regular verbose mode. 6755 * @hide 6756 */ 6757 @SystemApi 6758 public static final int VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY = 2; 6759 6760 /** @hide */ 6761 @IntDef(prefix = {"VERBOSE_LOGGING_LEVEL_"}, value = { 6762 VERBOSE_LOGGING_LEVEL_DISABLED, 6763 VERBOSE_LOGGING_LEVEL_ENABLED, 6764 VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY, 6765 }) 6766 @Retention(RetentionPolicy.SOURCE) 6767 public @interface VerboseLoggingLevel { 6768 } 6769 6770 /** 6771 * Start Easy Connect (DPP) in Configurator-Initiator role. The current device will initiate 6772 * Easy Connect bootstrapping with a peer, and configure the peer with the SSID and password of 6773 * the specified network using the Easy Connect protocol on an encrypted link. 6774 * 6775 * @param enrolleeUri URI of the Enrollee obtained separately (e.g. QR code scanning) 6776 * @param selectedNetworkId Selected network ID to be sent to the peer 6777 * @param enrolleeNetworkRole The network role of the enrollee 6778 * @param callback Callback for status updates 6779 * @param executor The Executor on which to run the callback. 6780 * @hide 6781 */ 6782 @SystemApi 6783 @RequiresPermission(anyOf = { 6784 android.Manifest.permission.NETWORK_SETTINGS, 6785 android.Manifest.permission.NETWORK_SETUP_WIZARD}) startEasyConnectAsConfiguratorInitiator(@onNull String enrolleeUri, int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)6786 public void startEasyConnectAsConfiguratorInitiator(@NonNull String enrolleeUri, 6787 int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole, 6788 @NonNull @CallbackExecutor Executor executor, 6789 @NonNull EasyConnectStatusCallback callback) { 6790 Binder binder = new Binder(); 6791 try { 6792 mService.startDppAsConfiguratorInitiator(binder, mContext.getOpPackageName(), 6793 enrolleeUri, selectedNetworkId, enrolleeNetworkRole, 6794 new EasyConnectCallbackProxy(executor, callback)); 6795 } catch (RemoteException e) { 6796 throw e.rethrowFromSystemServer(); 6797 } 6798 } 6799 6800 /** 6801 * Start Easy Connect (DPP) in Enrollee-Initiator role. The current device will initiate Easy 6802 * Connect bootstrapping with a peer, and receive the SSID and password from the peer 6803 * configurator. 6804 * 6805 * @param configuratorUri URI of the Configurator obtained separately (e.g. QR code scanning) 6806 * @param callback Callback for status updates 6807 * @param executor The Executor on which to run the callback. 6808 * @hide 6809 */ 6810 @SystemApi 6811 @RequiresPermission(anyOf = { 6812 android.Manifest.permission.NETWORK_SETTINGS, 6813 android.Manifest.permission.NETWORK_SETUP_WIZARD}) startEasyConnectAsEnrolleeInitiator(@onNull String configuratorUri, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)6814 public void startEasyConnectAsEnrolleeInitiator(@NonNull String configuratorUri, 6815 @NonNull @CallbackExecutor Executor executor, 6816 @NonNull EasyConnectStatusCallback callback) { 6817 Binder binder = new Binder(); 6818 try { 6819 mService.startDppAsEnrolleeInitiator(binder, configuratorUri, 6820 new EasyConnectCallbackProxy(executor, callback)); 6821 } catch (RemoteException e) { 6822 throw e.rethrowFromSystemServer(); 6823 } 6824 } 6825 6826 /** 6827 * Start Easy Connect (DPP) in Enrollee-Responder role. 6828 * The device will: 6829 * 1. Generate a DPP bootstrap URI and return it using the 6830 * {@link EasyConnectStatusCallback#onBootstrapUriGenerated(Uri)} method. 6831 * 2. Start DPP as a Responder, waiting for an Initiator device to start the DPP 6832 * authentication process. 6833 * The caller should use the URI provided in step #1, for instance display it as a QR code 6834 * or communicate it in some other way to the initiator device. 6835 * 6836 * @param deviceInfo Device specific information to add to the DPP URI. This field allows 6837 * the users of the configurators to identify the device. 6838 * Optional - if not provided or in case of an empty string, 6839 * Info field (I:) will be skipped in the generated DPP URI. 6840 * Allowed Range of ASCII characters in deviceInfo - %x20-7E. 6841 * semicolon and space are not allowed. Due to the limitation of maximum 6842 * allowed characters in QR code, framework adds a limit to maximum 6843 * characters in deviceInfo. Users must call 6844 * {@link WifiManager#getEasyConnectMaxAllowedResponderDeviceInfoLength() 6845 * } method to know max allowed length. Violation of these rules will 6846 * result in an exception. 6847 * @param curve Elliptic curve cryptography used to generate DPP 6848 * public/private key pair. If application is not interested in a 6849 * specific curve, use specification mandated NIST P-256 elliptic curve, 6850 * {@link WifiManager#EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1}. 6851 * @param callback Callback for status updates 6852 * @param executor The Executor on which to run the callback. 6853 * @hide 6854 */ 6855 @SystemApi 6856 @RequiresPermission(anyOf = { 6857 android.Manifest.permission.NETWORK_SETTINGS, 6858 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 6859 @RequiresApi(Build.VERSION_CODES.S) startEasyConnectAsEnrolleeResponder(@ullable String deviceInfo, @EasyConnectCryptographyCurve int curve, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)6860 public void startEasyConnectAsEnrolleeResponder(@Nullable String deviceInfo, 6861 @EasyConnectCryptographyCurve int curve, 6862 @NonNull @CallbackExecutor Executor executor, 6863 @NonNull EasyConnectStatusCallback callback) { 6864 Binder binder = new Binder(); 6865 try { 6866 mService.startDppAsEnrolleeResponder(binder, deviceInfo, curve, 6867 new EasyConnectCallbackProxy(executor, callback)); 6868 } catch (RemoteException e) { 6869 throw e.rethrowFromSystemServer(); 6870 } 6871 } 6872 6873 /** 6874 * Maximum allowed length of Device specific information that can be added to the URI of 6875 * Easy Connect responder device. 6876 * @see #startEasyConnectAsEnrolleeResponder(String, int, Executor, EasyConnectStatusCallback)} 6877 * 6878 * @hide 6879 */ 6880 @SystemApi getEasyConnectMaxAllowedResponderDeviceInfoLength()6881 public static int getEasyConnectMaxAllowedResponderDeviceInfoLength() { 6882 return EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH; 6883 } 6884 6885 /** 6886 * Stop or abort a current Easy Connect (DPP) session. This call, once processed, will 6887 * terminate any ongoing transaction, and clean up all associated resources. Caller should not 6888 * expect any callbacks once this call is made. However, due to the asynchronous nature of 6889 * this call, a callback may be fired if it was already pending in the queue. 6890 * 6891 * @hide 6892 */ 6893 @SystemApi 6894 @RequiresPermission(anyOf = { 6895 android.Manifest.permission.NETWORK_SETTINGS, 6896 android.Manifest.permission.NETWORK_SETUP_WIZARD}) stopEasyConnectSession()6897 public void stopEasyConnectSession() { 6898 try { 6899 /* Request lower layers to stop/abort and clear resources */ 6900 mService.stopDppSession(); 6901 } catch (RemoteException e) { 6902 throw e.rethrowFromSystemServer(); 6903 } 6904 } 6905 6906 /** 6907 * Helper class to support Easy Connect (DPP) callbacks 6908 * 6909 * @hide 6910 */ 6911 private static class EasyConnectCallbackProxy extends IDppCallback.Stub { 6912 private final Executor mExecutor; 6913 private final EasyConnectStatusCallback mEasyConnectStatusCallback; 6914 EasyConnectCallbackProxy(Executor executor, EasyConnectStatusCallback easyConnectStatusCallback)6915 EasyConnectCallbackProxy(Executor executor, 6916 EasyConnectStatusCallback easyConnectStatusCallback) { 6917 mExecutor = executor; 6918 mEasyConnectStatusCallback = easyConnectStatusCallback; 6919 } 6920 6921 @Override onSuccessConfigReceived(int newNetworkId)6922 public void onSuccessConfigReceived(int newNetworkId) { 6923 Log.d(TAG, "Easy Connect onSuccessConfigReceived callback"); 6924 Binder.clearCallingIdentity(); 6925 mExecutor.execute(() -> { 6926 mEasyConnectStatusCallback.onEnrolleeSuccess(newNetworkId); 6927 }); 6928 } 6929 6930 @Override onSuccess(int status)6931 public void onSuccess(int status) { 6932 Log.d(TAG, "Easy Connect onSuccess callback"); 6933 Binder.clearCallingIdentity(); 6934 mExecutor.execute(() -> { 6935 mEasyConnectStatusCallback.onConfiguratorSuccess(status); 6936 }); 6937 } 6938 6939 @Override onFailure(int status, String ssid, String channelList, int[] operatingClassArray)6940 public void onFailure(int status, String ssid, String channelList, 6941 int[] operatingClassArray) { 6942 Log.d(TAG, "Easy Connect onFailure callback"); 6943 Binder.clearCallingIdentity(); 6944 mExecutor.execute(() -> { 6945 SparseArray<int[]> channelListArray = parseDppChannelList(channelList); 6946 mEasyConnectStatusCallback.onFailure(status, ssid, channelListArray, 6947 operatingClassArray); 6948 }); 6949 } 6950 6951 @Override onProgress(int status)6952 public void onProgress(int status) { 6953 Log.d(TAG, "Easy Connect onProgress callback"); 6954 Binder.clearCallingIdentity(); 6955 mExecutor.execute(() -> { 6956 mEasyConnectStatusCallback.onProgress(status); 6957 }); 6958 } 6959 6960 @Override onBootstrapUriGenerated(@onNull String uri)6961 public void onBootstrapUriGenerated(@NonNull String uri) { 6962 Log.d(TAG, "Easy Connect onBootstrapUriGenerated callback"); 6963 if (!SdkLevel.isAtLeastS()) { 6964 Log.e(TAG, "Easy Connect bootstrap URI callback supported only on S+"); 6965 return; 6966 } 6967 Binder.clearCallingIdentity(); 6968 mExecutor.execute(() -> { 6969 mEasyConnectStatusCallback.onBootstrapUriGenerated(Uri.parse(uri)); 6970 }); 6971 } 6972 } 6973 6974 /** 6975 * Interface for Wi-Fi usability statistics listener. Should be implemented by applications and 6976 * set when calling {@link WifiManager#addOnWifiUsabilityStatsListener(Executor, 6977 * OnWifiUsabilityStatsListener)}. 6978 * 6979 * @hide 6980 */ 6981 @SystemApi 6982 public interface OnWifiUsabilityStatsListener { 6983 /** 6984 * Called when Wi-Fi usability statistics is updated. 6985 * 6986 * @param seqNum The sequence number of statistics, used to derive the timing of updated 6987 * Wi-Fi usability statistics, set by framework and incremented by one after 6988 * each update. 6989 * @param isSameBssidAndFreq The flag to indicate whether the BSSID and the frequency of 6990 * network stays the same or not relative to the last update of 6991 * Wi-Fi usability stats. 6992 * @param stats The updated Wi-Fi usability statistics. 6993 */ onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, @NonNull WifiUsabilityStatsEntry stats)6994 void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, 6995 @NonNull WifiUsabilityStatsEntry stats); 6996 } 6997 6998 /** 6999 * Interface for Wi-Fi verbose logging status listener. Should be implemented by applications 7000 * and set when calling {@link WifiManager#addWifiVerboseLoggingStatusListener(Executor, 7001 * WifiVerboseLoggingStatusListener)}. 7002 * 7003 * @hide 7004 */ 7005 @SystemApi 7006 public interface WifiVerboseLoggingStatusChangedListener { 7007 /** 7008 * Called when Wi-Fi verbose logging setting is updated. 7009 * 7010 * @param enabled true if verbose logging is enabled, false if verbose logging is disabled. 7011 */ onWifiVerboseLoggingStatusChanged(boolean enabled)7012 void onWifiVerboseLoggingStatusChanged(boolean enabled); 7013 } 7014 7015 /** 7016 * Adds a listener for Wi-Fi usability statistics. See {@link OnWifiUsabilityStatsListener}. 7017 * Multiple listeners can be added. Callers will be invoked periodically by framework to 7018 * inform clients about the current Wi-Fi usability statistics. Callers can remove a previously 7019 * added listener using 7020 * {@link #removeOnWifiUsabilityStatsListener(OnWifiUsabilityStatsListener)}. 7021 * 7022 * @param executor The executor on which callback will be invoked. 7023 * @param listener Listener for Wifi usability statistics. 7024 * 7025 * @hide 7026 */ 7027 @SystemApi 7028 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) addOnWifiUsabilityStatsListener(@onNull @allbackExecutor Executor executor, @NonNull OnWifiUsabilityStatsListener listener)7029 public void addOnWifiUsabilityStatsListener(@NonNull @CallbackExecutor Executor executor, 7030 @NonNull OnWifiUsabilityStatsListener listener) { 7031 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 7032 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 7033 if (mVerboseLoggingEnabled) { 7034 Log.v(TAG, "addOnWifiUsabilityStatsListener: listener=" + listener); 7035 } 7036 try { 7037 synchronized (sOnWifiUsabilityStatsListenerMap) { 7038 IOnWifiUsabilityStatsListener.Stub binderCallback = 7039 new IOnWifiUsabilityStatsListener.Stub() { 7040 @Override 7041 public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, 7042 WifiUsabilityStatsEntry stats) { 7043 if (mVerboseLoggingEnabled) { 7044 Log.v(TAG, "OnWifiUsabilityStatsListener: " 7045 + "onWifiUsabilityStats: seqNum=" + seqNum); 7046 } 7047 Binder.clearCallingIdentity(); 7048 executor.execute(() -> listener.onWifiUsabilityStats( 7049 seqNum, isSameBssidAndFreq, stats)); 7050 } 7051 }; 7052 sOnWifiUsabilityStatsListenerMap.put(System.identityHashCode(listener), 7053 binderCallback); 7054 mService.addOnWifiUsabilityStatsListener(binderCallback); 7055 } 7056 } catch (RemoteException e) { 7057 throw e.rethrowFromSystemServer(); 7058 } 7059 } 7060 7061 /** 7062 * Allow callers to remove a previously registered listener. After calling this method, 7063 * applications will no longer receive Wi-Fi usability statistics. 7064 * 7065 * @param listener Listener to remove the Wi-Fi usability statistics. 7066 * 7067 * @hide 7068 */ 7069 @SystemApi 7070 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) removeOnWifiUsabilityStatsListener(@onNull OnWifiUsabilityStatsListener listener)7071 public void removeOnWifiUsabilityStatsListener(@NonNull OnWifiUsabilityStatsListener listener) { 7072 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 7073 if (mVerboseLoggingEnabled) { 7074 Log.v(TAG, "removeOnWifiUsabilityStatsListener: listener=" + listener); 7075 } 7076 try { 7077 synchronized (sOnWifiUsabilityStatsListenerMap) { 7078 int listenerIdentifier = System.identityHashCode(listener); 7079 if (!sOnWifiUsabilityStatsListenerMap.contains(listenerIdentifier)) { 7080 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 7081 return; 7082 } 7083 mService.removeOnWifiUsabilityStatsListener( 7084 sOnWifiUsabilityStatsListenerMap.get(listenerIdentifier)); 7085 sOnWifiUsabilityStatsListenerMap.remove(listenerIdentifier); 7086 } 7087 } catch (RemoteException e) { 7088 throw e.rethrowFromSystemServer(); 7089 } 7090 } 7091 7092 /** 7093 * Provide a Wi-Fi usability score information to be recorded (but not acted upon) by the 7094 * framework. The Wi-Fi usability score is derived from {@link OnWifiUsabilityStatsListener} 7095 * where a score is matched to Wi-Fi usability statistics using the sequence number. The score 7096 * is used to quantify whether Wi-Fi is usable in a future time. 7097 * 7098 * @param seqNum Sequence number of the Wi-Fi usability score. 7099 * @param score The Wi-Fi usability score, expected range: [0, 100]. 7100 * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score in second, 7101 * expected range: [0, 30]. 7102 * 7103 * @hide 7104 */ 7105 @SystemApi 7106 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec)7107 public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { 7108 try { 7109 mService.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec); 7110 } catch (RemoteException e) { 7111 throw e.rethrowFromSystemServer(); 7112 } 7113 } 7114 7115 /** 7116 * Abstract class for scan results callback. Should be extended by applications and set when 7117 * calling {@link WifiManager#registerScanResultsCallback(Executor, ScanResultsCallback)}. 7118 */ 7119 public abstract static class ScanResultsCallback { 7120 private final ScanResultsCallbackProxy mScanResultsCallbackProxy; 7121 ScanResultsCallback()7122 public ScanResultsCallback() { 7123 mScanResultsCallbackProxy = new ScanResultsCallbackProxy(); 7124 } 7125 7126 /** 7127 * Called when new scan results are available. 7128 * Clients should use {@link WifiManager#getScanResults()} to get the scan results. 7129 */ onScanResultsAvailable()7130 public abstract void onScanResultsAvailable(); 7131 getProxy()7132 /*package*/ @NonNull ScanResultsCallbackProxy getProxy() { 7133 return mScanResultsCallbackProxy; 7134 } 7135 7136 private static class ScanResultsCallbackProxy extends IScanResultsCallback.Stub { 7137 private final Object mLock = new Object(); 7138 @Nullable @GuardedBy("mLock") private Executor mExecutor; 7139 @Nullable @GuardedBy("mLock") private ScanResultsCallback mCallback; 7140 ScanResultsCallbackProxy()7141 ScanResultsCallbackProxy() { 7142 mCallback = null; 7143 mExecutor = null; 7144 } 7145 initProxy(@onNull Executor executor, @NonNull ScanResultsCallback callback)7146 /*package*/ void initProxy(@NonNull Executor executor, 7147 @NonNull ScanResultsCallback callback) { 7148 synchronized (mLock) { 7149 mExecutor = executor; 7150 mCallback = callback; 7151 } 7152 } 7153 cleanUpProxy()7154 /*package*/ void cleanUpProxy() { 7155 synchronized (mLock) { 7156 mExecutor = null; 7157 mCallback = null; 7158 } 7159 } 7160 7161 @Override onScanResultsAvailable()7162 public void onScanResultsAvailable() { 7163 ScanResultsCallback callback; 7164 Executor executor; 7165 synchronized (mLock) { 7166 executor = mExecutor; 7167 callback = mCallback; 7168 } 7169 if (callback == null || executor == null) { 7170 return; 7171 } 7172 Binder.clearCallingIdentity(); 7173 executor.execute(callback::onScanResultsAvailable); 7174 } 7175 } 7176 } 7177 7178 /** 7179 * Register a callback for Scan Results. See {@link ScanResultsCallback}. 7180 * Caller will receive the event when scan results are available. 7181 * Caller should use {@link WifiManager#getScanResults()} requires 7182 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} to get the scan results. 7183 * Caller can remove a previously registered callback using 7184 * {@link WifiManager#unregisterScanResultsCallback(ScanResultsCallback)} 7185 * Same caller can add multiple listeners. 7186 * <p> 7187 * Applications should have the 7188 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission. Callers 7189 * without the permission will trigger a {@link java.lang.SecurityException}. 7190 * <p> 7191 * 7192 * @param executor The executor to execute the callback of the {@code callback} object. 7193 * @param callback callback for Scan Results events 7194 */ 7195 7196 @RequiresPermission(ACCESS_WIFI_STATE) registerScanResultsCallback(@onNull @allbackExecutor Executor executor, @NonNull ScanResultsCallback callback)7197 public void registerScanResultsCallback(@NonNull @CallbackExecutor Executor executor, 7198 @NonNull ScanResultsCallback callback) { 7199 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 7200 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 7201 7202 Log.v(TAG, "registerScanResultsCallback: callback=" + callback 7203 + ", executor=" + executor); 7204 ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy(); 7205 proxy.initProxy(executor, callback); 7206 try { 7207 mService.registerScanResultsCallback(proxy); 7208 } catch (RemoteException e) { 7209 throw e.rethrowFromSystemServer(); 7210 } 7211 } 7212 7213 /** 7214 * Allow callers to unregister a previously registered callback. After calling this method, 7215 * applications will no longer receive Scan Results events. 7216 * 7217 * @param callback callback to unregister for Scan Results events 7218 */ 7219 @RequiresPermission(ACCESS_WIFI_STATE) unregisterScanResultsCallback(@onNull ScanResultsCallback callback)7220 public void unregisterScanResultsCallback(@NonNull ScanResultsCallback callback) { 7221 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 7222 Log.v(TAG, "unregisterScanResultsCallback: Callback=" + callback); 7223 ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy(); 7224 try { 7225 mService.unregisterScanResultsCallback(proxy); 7226 } catch (RemoteException e) { 7227 throw e.rethrowFromSystemServer(); 7228 } finally { 7229 proxy.cleanUpProxy(); 7230 } 7231 } 7232 7233 /** 7234 * Interface for suggestion connection status listener. 7235 * Should be implemented by applications and set when calling 7236 * {@link WifiManager#addSuggestionConnectionStatusListener( 7237 * Executor, SuggestionConnectionStatusListener)}. 7238 */ 7239 public interface SuggestionConnectionStatusListener { 7240 7241 /** 7242 * Called when the framework attempted to connect to a suggestion provided by the 7243 * registering app, but the connection to the suggestion failed. 7244 * @param wifiNetworkSuggestion The suggestion which failed to connect. 7245 * @param failureReason the connection failure reason code. One of 7246 * {@link #STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION}, 7247 * {@link #STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION}, 7248 * {@link #STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING} 7249 * {@link #STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN} 7250 */ onConnectionStatus( @onNull WifiNetworkSuggestion wifiNetworkSuggestion, @SuggestionConnectionStatusCode int failureReason)7251 void onConnectionStatus( 7252 @NonNull WifiNetworkSuggestion wifiNetworkSuggestion, 7253 @SuggestionConnectionStatusCode int failureReason); 7254 } 7255 7256 private class SuggestionConnectionStatusListenerProxy extends 7257 ISuggestionConnectionStatusListener.Stub { 7258 private final Executor mExecutor; 7259 private final SuggestionConnectionStatusListener mListener; 7260 SuggestionConnectionStatusListenerProxy(@onNull Executor executor, @NonNull SuggestionConnectionStatusListener listener)7261 SuggestionConnectionStatusListenerProxy(@NonNull Executor executor, 7262 @NonNull SuggestionConnectionStatusListener listener) { 7263 mExecutor = executor; 7264 mListener = listener; 7265 } 7266 7267 @Override onConnectionStatus(@onNull WifiNetworkSuggestion wifiNetworkSuggestion, int failureReason)7268 public void onConnectionStatus(@NonNull WifiNetworkSuggestion wifiNetworkSuggestion, 7269 int failureReason) { 7270 mExecutor.execute(() -> 7271 mListener.onConnectionStatus(wifiNetworkSuggestion, failureReason)); 7272 } 7273 7274 } 7275 7276 /** 7277 * Add a listener listening to wifi verbose logging changes. 7278 * See {@link WifiVerboseLoggingStatusChangedListener}. 7279 * Caller can remove a previously registered listener using 7280 * {@link WifiManager#removeWifiVerboseLoggingStatusChangedListener( 7281 * WifiVerboseLoggingStatusChangedListener)} 7282 * Same caller can add multiple listeners to monitor the event. 7283 * <p> 7284 * Applications should have the 7285 * {@link android.Manifest.permission#ACCESS_WIFI_STATE}. 7286 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 7287 * <p> 7288 * @param executor The executor to execute the listener of the {@code listener} object. 7289 * @param listener listener for changes in wifi verbose logging. 7290 * 7291 * @hide 7292 */ 7293 @SystemApi 7294 @RequiresPermission(ACCESS_WIFI_STATE) addWifiVerboseLoggingStatusChangedListener( @onNull @allbackExecutor Executor executor, @NonNull WifiVerboseLoggingStatusChangedListener listener)7295 public void addWifiVerboseLoggingStatusChangedListener( 7296 @NonNull @CallbackExecutor Executor executor, 7297 @NonNull WifiVerboseLoggingStatusChangedListener listener) { 7298 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 7299 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 7300 if (mVerboseLoggingEnabled) { 7301 Log.v(TAG, "addWifiVerboseLoggingStatusChangedListener listener=" + listener 7302 + ", executor=" + executor); 7303 } 7304 try { 7305 synchronized (sWifiVerboseLoggingStatusChangedListenerMap) { 7306 IWifiVerboseLoggingStatusChangedListener.Stub binderCallback = 7307 new IWifiVerboseLoggingStatusChangedListener.Stub() { 7308 @Override 7309 public void onStatusChanged(boolean enabled) { 7310 if (mVerboseLoggingEnabled) { 7311 Log.v(TAG, "WifiVerboseLoggingStatusListener: " 7312 + "onVerboseLoggingStatusChanged: enabled=" + enabled); 7313 } 7314 Binder.clearCallingIdentity(); 7315 executor.execute(() -> listener.onWifiVerboseLoggingStatusChanged( 7316 enabled)); 7317 } 7318 }; 7319 sWifiVerboseLoggingStatusChangedListenerMap.put(System.identityHashCode(listener), 7320 binderCallback); 7321 mService.addWifiVerboseLoggingStatusChangedListener(binderCallback); 7322 } 7323 } catch (RemoteException e) { 7324 throw e.rethrowFromSystemServer(); 7325 } 7326 } 7327 7328 /** 7329 * Allow callers to remove a previously registered listener. 7330 * <p> 7331 * Applications should have the 7332 * {@link android.Manifest.permission#ACCESS_WIFI_STATE}. 7333 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 7334 * <p> 7335 * @param listener listener to remove. 7336 * 7337 * @hide 7338 */ 7339 @SystemApi 7340 @RequiresPermission(ACCESS_WIFI_STATE) removeWifiVerboseLoggingStatusChangedListener( @onNull WifiVerboseLoggingStatusChangedListener listener)7341 public void removeWifiVerboseLoggingStatusChangedListener( 7342 @NonNull WifiVerboseLoggingStatusChangedListener listener) { 7343 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 7344 Log.v(TAG, "removeWifiVerboseLoggingStatusChangedListener: listener=" + listener); 7345 try { 7346 synchronized (sWifiVerboseLoggingStatusChangedListenerMap) { 7347 int listenerIdentifier = System.identityHashCode(listener); 7348 if (!sWifiVerboseLoggingStatusChangedListenerMap.contains(listenerIdentifier)) { 7349 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 7350 return; 7351 } 7352 mService.removeWifiVerboseLoggingStatusChangedListener( 7353 sWifiVerboseLoggingStatusChangedListenerMap.get(listenerIdentifier)); 7354 sWifiVerboseLoggingStatusChangedListenerMap.remove(listenerIdentifier); 7355 } 7356 } catch (RemoteException e) { 7357 throw e.rethrowFromSystemServer(); 7358 } 7359 } 7360 7361 /** 7362 * Add a listener for suggestion networks. See {@link SuggestionConnectionStatusListener}. 7363 * Caller will receive the event when suggested network have connection failure. 7364 * Caller can remove a previously registered listener using 7365 * {@link WifiManager#removeSuggestionConnectionStatusListener( 7366 * SuggestionConnectionStatusListener)} 7367 * Same caller can add multiple listeners to monitor the event. 7368 * <p> 7369 * Applications should have the 7370 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and 7371 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permissions. 7372 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 7373 * <p> 7374 * 7375 * @param executor The executor to execute the listener of the {@code listener} object. 7376 * @param listener listener for suggestion network connection failure. 7377 */ 7378 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) addSuggestionConnectionStatusListener(@onNull @allbackExecutor Executor executor, @NonNull SuggestionConnectionStatusListener listener)7379 public void addSuggestionConnectionStatusListener(@NonNull @CallbackExecutor Executor executor, 7380 @NonNull SuggestionConnectionStatusListener listener) { 7381 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 7382 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 7383 Log.v(TAG, "addSuggestionConnectionStatusListener listener=" + listener 7384 + ", executor=" + executor); 7385 try { 7386 synchronized (sSuggestionConnectionStatusListenerMap) { 7387 ISuggestionConnectionStatusListener.Stub binderCallback = 7388 new SuggestionConnectionStatusListenerProxy(executor, listener); 7389 sSuggestionConnectionStatusListenerMap.put(System.identityHashCode(listener), 7390 binderCallback); 7391 mService.registerSuggestionConnectionStatusListener(binderCallback, 7392 mContext.getOpPackageName(), mContext.getAttributionTag()); 7393 } 7394 } catch (RemoteException e) { 7395 throw e.rethrowFromSystemServer(); 7396 } 7397 7398 } 7399 7400 /** 7401 * Allow callers to remove a previously registered listener. After calling this method, 7402 * applications will no longer receive suggestion connection events through that listener. 7403 * 7404 * @param listener listener to remove. 7405 */ 7406 @RequiresPermission(ACCESS_WIFI_STATE) removeSuggestionConnectionStatusListener( @onNull SuggestionConnectionStatusListener listener)7407 public void removeSuggestionConnectionStatusListener( 7408 @NonNull SuggestionConnectionStatusListener listener) { 7409 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 7410 Log.v(TAG, "removeSuggestionConnectionStatusListener: listener=" + listener); 7411 try { 7412 synchronized (sSuggestionConnectionStatusListenerMap) { 7413 int listenerIdentifier = System.identityHashCode(listener); 7414 if (!sSuggestionConnectionStatusListenerMap.contains(listenerIdentifier)) { 7415 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 7416 return; 7417 } 7418 mService.unregisterSuggestionConnectionStatusListener( 7419 sSuggestionConnectionStatusListenerMap.get(listenerIdentifier), 7420 mContext.getOpPackageName()); 7421 sSuggestionConnectionStatusListenerMap.remove(listenerIdentifier); 7422 } 7423 } catch (RemoteException e) { 7424 throw e.rethrowFromSystemServer(); 7425 } 7426 } 7427 7428 /** 7429 * Parse the list of channels the DPP enrollee reports when it fails to find an AP. 7430 * 7431 * @param channelList List of channels in the format defined in the DPP specification. 7432 * @return A parsed sparse array, where the operating class is the key. 7433 * @hide 7434 */ 7435 @VisibleForTesting parseDppChannelList(String channelList)7436 public static SparseArray<int[]> parseDppChannelList(String channelList) { 7437 SparseArray<int[]> channelListArray = new SparseArray<>(); 7438 7439 if (TextUtils.isEmpty(channelList)) { 7440 return channelListArray; 7441 } 7442 StringTokenizer str = new StringTokenizer(channelList, ","); 7443 String classStr = null; 7444 List<Integer> channelsInClass = new ArrayList<>(); 7445 7446 try { 7447 while (str.hasMoreElements()) { 7448 String cur = str.nextToken(); 7449 7450 /** 7451 * Example for a channel list: 7452 * 7453 * 81/1,2,3,4,5,6,7,8,9,10,11,115/36,40,44,48,118/52,56,60,64,121/100,104,108,112, 7454 * 116,120,124,128,132,136,140,0/144,124/149,153,157,161,125/165 7455 * 7456 * Detect operating class by the delimiter of '/' and use a string tokenizer with 7457 * ',' as a delimiter. 7458 */ 7459 int classDelim = cur.indexOf('/'); 7460 if (classDelim != -1) { 7461 if (classStr != null) { 7462 // Store the last channel array in the sparse array, where the operating 7463 // class is the key (as an integer). 7464 int[] channelsArray = new int[channelsInClass.size()]; 7465 for (int i = 0; i < channelsInClass.size(); i++) { 7466 channelsArray[i] = channelsInClass.get(i); 7467 } 7468 channelListArray.append(Integer.parseInt(classStr), channelsArray); 7469 channelsInClass = new ArrayList<>(); 7470 } 7471 7472 // Init a new operating class and store the first channel 7473 classStr = cur.substring(0, classDelim); 7474 String channelStr = cur.substring(classDelim + 1); 7475 channelsInClass.add(Integer.parseInt(channelStr)); 7476 } else { 7477 if (classStr == null) { 7478 // Invalid format 7479 Log.e(TAG, "Cannot parse DPP channel list"); 7480 return new SparseArray<>(); 7481 } 7482 channelsInClass.add(Integer.parseInt(cur)); 7483 } 7484 } 7485 7486 // Store the last array 7487 if (classStr != null) { 7488 int[] channelsArray = new int[channelsInClass.size()]; 7489 for (int i = 0; i < channelsInClass.size(); i++) { 7490 channelsArray[i] = channelsInClass.get(i); 7491 } 7492 channelListArray.append(Integer.parseInt(classStr), channelsArray); 7493 } 7494 return channelListArray; 7495 } catch (NumberFormatException e) { 7496 Log.e(TAG, "Cannot parse DPP channel list"); 7497 return new SparseArray<>(); 7498 } 7499 } 7500 7501 /** 7502 * Callback interface for framework to receive network status updates and trigger of updating 7503 * {@link WifiUsabilityStatsEntry}. 7504 * 7505 * @hide 7506 */ 7507 @SystemApi 7508 public interface ScoreUpdateObserver { 7509 /** 7510 * Called by applications to indicate network status. For applications targeting 7511 * {@link android.os.Build.VERSION_CODES#S} or above: The score is not used to take action 7512 * on network selection but for the purpose of Wifi metric collection only; Network 7513 * selection is influenced by inputs from 7514 * {@link ScoreUpdateObserver#notifyStatusUpdate(int, boolean)}, 7515 * {@link ScoreUpdateObserver#requestNudOperation(int, boolean)}, and 7516 * {@link ScoreUpdateObserver#blocklistCurrentBssid(int)}. 7517 * 7518 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 7519 * {@link WifiConnectedNetworkScorer#onStart(int)}. 7520 * @param score The score representing link quality of current Wi-Fi network connection. 7521 * Populated by connected network scorer in applications.. 7522 */ notifyScoreUpdate(int sessionId, int score)7523 void notifyScoreUpdate(int sessionId, int score); 7524 7525 /** 7526 * Called by applications to trigger an update of {@link WifiUsabilityStatsEntry}. 7527 * To receive update applications need to add WifiUsabilityStatsEntry listener. See 7528 * {@link addOnWifiUsabilityStatsListener(Executor, OnWifiUsabilityStatsListener)}. 7529 * 7530 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 7531 * {@link WifiConnectedNetworkScorer#onStart(int)}. 7532 */ triggerUpdateOfWifiUsabilityStats(int sessionId)7533 void triggerUpdateOfWifiUsabilityStats(int sessionId); 7534 7535 /** 7536 * Called by applications to indicate whether current Wi-Fi network is usable or not. 7537 * 7538 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 7539 * {@link WifiConnectedNetworkScorer#onStart(int)}. 7540 * @param isUsable The boolean representing whether current Wi-Fi network is usable, and it 7541 * may be sent to ConnectivityService and used for setting default network. 7542 * Populated by connected network scorer in applications. 7543 */ 7544 @RequiresApi(Build.VERSION_CODES.S) notifyStatusUpdate(int sessionId, boolean isUsable)7545 default void notifyStatusUpdate(int sessionId, boolean isUsable) {} 7546 7547 /** 7548 * Called by applications to start a NUD (Neighbor Unreachability Detection) operation. The 7549 * framework throttles NUD operations to no more frequently than every five seconds 7550 * (see {@link WifiScoreReport#NUD_THROTTLE_MILLIS}). The framework keeps track of requests 7551 * and executes them as soon as possible based on the throttling criteria. 7552 * 7553 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 7554 * {@link WifiConnectedNetworkScorer#onStart(int)}. 7555 */ 7556 @RequiresApi(Build.VERSION_CODES.S) requestNudOperation(int sessionId)7557 default void requestNudOperation(int sessionId) {} 7558 7559 /** 7560 * Called by applications to blocklist currently connected BSSID. No blocklisting operation 7561 * if called after disconnection. 7562 * 7563 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 7564 * {@link WifiConnectedNetworkScorer#onStart(int)}. 7565 */ 7566 @RequiresApi(Build.VERSION_CODES.S) blocklistCurrentBssid(int sessionId)7567 default void blocklistCurrentBssid(int sessionId) {} 7568 } 7569 7570 /** 7571 * Callback proxy for {@link ScoreUpdateObserver} objects. 7572 * 7573 * @hide 7574 */ 7575 private class ScoreUpdateObserverProxy implements ScoreUpdateObserver { 7576 private final IScoreUpdateObserver mScoreUpdateObserver; 7577 ScoreUpdateObserverProxy(IScoreUpdateObserver observer)7578 private ScoreUpdateObserverProxy(IScoreUpdateObserver observer) { 7579 mScoreUpdateObserver = observer; 7580 } 7581 7582 @Override notifyScoreUpdate(int sessionId, int score)7583 public void notifyScoreUpdate(int sessionId, int score) { 7584 try { 7585 mScoreUpdateObserver.notifyScoreUpdate(sessionId, score); 7586 } catch (RemoteException e) { 7587 throw e.rethrowFromSystemServer(); 7588 } 7589 } 7590 7591 @Override triggerUpdateOfWifiUsabilityStats(int sessionId)7592 public void triggerUpdateOfWifiUsabilityStats(int sessionId) { 7593 try { 7594 mScoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(sessionId); 7595 } catch (RemoteException e) { 7596 throw e.rethrowFromSystemServer(); 7597 } 7598 } 7599 7600 @Override notifyStatusUpdate(int sessionId, boolean isUsable)7601 public void notifyStatusUpdate(int sessionId, boolean isUsable) { 7602 if (!SdkLevel.isAtLeastS()) { 7603 throw new UnsupportedOperationException(); 7604 } 7605 try { 7606 mScoreUpdateObserver.notifyStatusUpdate(sessionId, isUsable); 7607 } catch (RemoteException e) { 7608 throw e.rethrowFromSystemServer(); 7609 } 7610 } 7611 7612 @Override requestNudOperation(int sessionId)7613 public void requestNudOperation(int sessionId) { 7614 if (!SdkLevel.isAtLeastS()) { 7615 throw new UnsupportedOperationException(); 7616 } 7617 try { 7618 mScoreUpdateObserver.requestNudOperation(sessionId); 7619 } catch (RemoteException e) { 7620 throw e.rethrowFromSystemServer(); 7621 } 7622 } 7623 7624 @Override blocklistCurrentBssid(int sessionId)7625 public void blocklistCurrentBssid(int sessionId) { 7626 if (!SdkLevel.isAtLeastS()) { 7627 throw new UnsupportedOperationException(); 7628 } 7629 try { 7630 mScoreUpdateObserver.blocklistCurrentBssid(sessionId); 7631 } catch (RemoteException e) { 7632 throw e.rethrowFromSystemServer(); 7633 } 7634 } 7635 } 7636 7637 /** 7638 * Interface for Wi-Fi connected network scorer. Should be implemented by applications and set 7639 * when calling 7640 * {@link WifiManager#setWifiConnectedNetworkScorer(Executor, WifiConnectedNetworkScorer)}. 7641 * 7642 * @hide 7643 */ 7644 @SystemApi 7645 public interface WifiConnectedNetworkScorer { 7646 /** 7647 * Called by framework to indicate the start of a network connection. 7648 * @param sessionId The ID to indicate current Wi-Fi network connection. 7649 * @deprecated This API is deprecated. Please use 7650 * {@link WifiConnectedNetworkScorer#onStart(WifiConnectedSessionInfo)}. 7651 */ 7652 @Deprecated onStart(int sessionId)7653 default void onStart(int sessionId) {} 7654 7655 /** 7656 * Called by framework to indicate the start of a network connection. 7657 * @param sessionInfo The session information to indicate current Wi-Fi network connection. 7658 * See {@link WifiConnectedSessionInfo}. 7659 */ onStart(@onNull WifiConnectedSessionInfo sessionInfo)7660 default void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) { 7661 onStart(sessionInfo.getSessionId()); 7662 } 7663 7664 /** 7665 * Called by framework to indicate the end of a network connection. 7666 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 7667 * {@link WifiConnectedNetworkScorer#onStart(int)}. 7668 */ onStop(int sessionId)7669 void onStop(int sessionId); 7670 7671 /** 7672 * Framework sets callback for score change events after application sets its scorer. 7673 * @param observerImpl The instance for {@link WifiManager#ScoreUpdateObserver}. Should be 7674 * implemented and instantiated by framework. 7675 */ onSetScoreUpdateObserver(@onNull ScoreUpdateObserver observerImpl)7676 void onSetScoreUpdateObserver(@NonNull ScoreUpdateObserver observerImpl); 7677 } 7678 7679 /** 7680 * Callback proxy for {@link WifiConnectedNetworkScorer} objects. 7681 * 7682 * @hide 7683 */ 7684 private class WifiConnectedNetworkScorerProxy extends IWifiConnectedNetworkScorer.Stub { 7685 private Executor mExecutor; 7686 private WifiConnectedNetworkScorer mScorer; 7687 WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer)7688 WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer) { 7689 mExecutor = executor; 7690 mScorer = scorer; 7691 } 7692 7693 @Override onStart(@onNull WifiConnectedSessionInfo sessionInfo)7694 public void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) { 7695 if (mVerboseLoggingEnabled) { 7696 Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStart: sessionInfo=" + sessionInfo); 7697 } 7698 Binder.clearCallingIdentity(); 7699 mExecutor.execute(() -> mScorer.onStart(sessionInfo)); 7700 } 7701 7702 @Override onStop(int sessionId)7703 public void onStop(int sessionId) { 7704 if (mVerboseLoggingEnabled) { 7705 Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStop: sessionId=" + sessionId); 7706 } 7707 Binder.clearCallingIdentity(); 7708 mExecutor.execute(() -> mScorer.onStop(sessionId)); 7709 } 7710 7711 @Override onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl)7712 public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) { 7713 if (mVerboseLoggingEnabled) { 7714 Log.v(TAG, "WifiConnectedNetworkScorer: " 7715 + "onSetScoreUpdateObserver: observerImpl=" + observerImpl); 7716 } 7717 Binder.clearCallingIdentity(); 7718 mExecutor.execute(() -> mScorer.onSetScoreUpdateObserver( 7719 new ScoreUpdateObserverProxy(observerImpl))); 7720 } 7721 } 7722 7723 /** 7724 * Set a callback for Wi-Fi connected network scorer. See {@link WifiConnectedNetworkScorer}. 7725 * Only a single scorer can be set. Caller will be invoked periodically by framework to inform 7726 * client about start and stop of Wi-Fi connection. Caller can clear a previously set scorer 7727 * using {@link clearWifiConnectedNetworkScorer()}. 7728 * 7729 * @param executor The executor on which callback will be invoked. 7730 * @param scorer Scorer for Wi-Fi network implemented by application. 7731 * @return true Scorer is set successfully. 7732 * 7733 * @hide 7734 */ 7735 @SystemApi 7736 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) setWifiConnectedNetworkScorer(@onNull @allbackExecutor Executor executor, @NonNull WifiConnectedNetworkScorer scorer)7737 public boolean setWifiConnectedNetworkScorer(@NonNull @CallbackExecutor Executor executor, 7738 @NonNull WifiConnectedNetworkScorer scorer) { 7739 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 7740 if (scorer == null) throw new IllegalArgumentException("scorer cannot be null"); 7741 if (mVerboseLoggingEnabled) { 7742 Log.v(TAG, "setWifiConnectedNetworkScorer: scorer=" + scorer); 7743 } 7744 try { 7745 return mService.setWifiConnectedNetworkScorer(new Binder(), 7746 new WifiConnectedNetworkScorerProxy(executor, scorer)); 7747 } catch (RemoteException e) { 7748 throw e.rethrowFromSystemServer(); 7749 } 7750 } 7751 7752 /** 7753 * Allow caller to clear a previously set scorer. After calling this method, 7754 * client will no longer receive information about start and stop of Wi-Fi connection. 7755 * 7756 * @hide 7757 */ 7758 @SystemApi 7759 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) clearWifiConnectedNetworkScorer()7760 public void clearWifiConnectedNetworkScorer() { 7761 if (mVerboseLoggingEnabled) { 7762 Log.v(TAG, "clearWifiConnectedNetworkScorer"); 7763 } 7764 try { 7765 mService.clearWifiConnectedNetworkScorer(); 7766 } catch (RemoteException e) { 7767 throw e.rethrowFromSystemServer(); 7768 } 7769 } 7770 7771 /** 7772 * Enable/disable wifi scan throttling from 3rd party apps. 7773 * 7774 * <p> 7775 * The throttling limits for apps are described in 7776 * <a href="Wi-Fi Scan Throttling"> 7777 * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a> 7778 * </p> 7779 * 7780 * @param enable true to allow scan throttling, false to disallow scan throttling. 7781 * @hide 7782 */ 7783 @SystemApi 7784 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setScanThrottleEnabled(boolean enable)7785 public void setScanThrottleEnabled(boolean enable) { 7786 try { 7787 mService.setScanThrottleEnabled(enable); 7788 } catch (RemoteException e) { 7789 throw e.rethrowFromSystemServer(); 7790 } 7791 } 7792 7793 /** 7794 * Get the persisted Wi-Fi scan throttle state. Defaults to true, unless changed by the user via 7795 * Developer options. 7796 * 7797 * <p> 7798 * The throttling limits for apps are described in 7799 * <a href="Wi-Fi Scan Throttling"> 7800 * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a> 7801 * </p> 7802 * 7803 * @return true to indicate that scan throttling is enabled, false to indicate that scan 7804 * throttling is disabled. 7805 */ 7806 @RequiresPermission(ACCESS_WIFI_STATE) isScanThrottleEnabled()7807 public boolean isScanThrottleEnabled() { 7808 try { 7809 return mService.isScanThrottleEnabled(); 7810 } catch (RemoteException e) { 7811 throw e.rethrowFromSystemServer(); 7812 } 7813 } 7814 7815 /** 7816 * Enable/disable wifi auto wakeup feature. 7817 * 7818 * <p> 7819 * The feature is described in 7820 * <a href="Wi-Fi Turn on automatically"> 7821 * https://source.android.com/devices/tech/connect/wifi-infrastructure 7822 * #turn_on_wi-fi_automatically 7823 * </a> 7824 * 7825 * @param enable true to enable, false to disable. 7826 * @hide 7827 */ 7828 @SystemApi 7829 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setAutoWakeupEnabled(boolean enable)7830 public void setAutoWakeupEnabled(boolean enable) { 7831 try { 7832 mService.setAutoWakeupEnabled(enable); 7833 } catch (RemoteException e) { 7834 throw e.rethrowFromSystemServer(); 7835 } 7836 } 7837 7838 /** 7839 * Get the persisted Wi-Fi auto wakeup feature state. Defaults to false, unless changed by the 7840 * user via Settings. 7841 * 7842 * <p> 7843 * The feature is described in 7844 * <a href="Wi-Fi Turn on automatically"> 7845 * https://source.android.com/devices/tech/connect/wifi-infrastructure 7846 * #turn_on_wi-fi_automatically 7847 * </a> 7848 * 7849 * @return true to indicate that wakeup feature is enabled, false to indicate that wakeup 7850 * feature is disabled. 7851 */ 7852 @RequiresPermission(ACCESS_WIFI_STATE) isAutoWakeupEnabled()7853 public boolean isAutoWakeupEnabled() { 7854 try { 7855 return mService.isAutoWakeupEnabled(); 7856 } catch (RemoteException e) { 7857 throw e.rethrowFromSystemServer(); 7858 } 7859 } 7860 7861 /** 7862 * Sets the state of carrier offload on merged or unmerged networks for specified subscription. 7863 * 7864 * <p> 7865 * When a subscription's carrier network offload is disabled, all network suggestions related to 7866 * this subscription will not be considered for auto join. 7867 * <p> 7868 * If calling app want disable all carrier network offload from a specified subscription, should 7869 * call this API twice to disable both merged and unmerged carrier network suggestions. 7870 * 7871 * @param subscriptionId See {@link SubscriptionInfo#getSubscriptionId()}. 7872 * @param merged True for carrier merged network, false otherwise. 7873 * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} 7874 * @param enabled True for enable carrier network offload, false otherwise. 7875 * @see #isCarrierNetworkOffloadEnabled(int, boolean) 7876 * @hide 7877 */ 7878 @SystemApi 7879 @RequiresPermission(anyOf = { 7880 android.Manifest.permission.NETWORK_SETTINGS, 7881 android.Manifest.permission.NETWORK_SETUP_WIZARD}) setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, boolean enabled)7882 public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, 7883 boolean enabled) { 7884 try { 7885 mService.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled); 7886 } catch (RemoteException e) { 7887 throw e.rethrowFromSystemServer(); 7888 } 7889 } 7890 7891 /** 7892 * Get the carrier network offload state for merged or unmerged networks for specified 7893 * subscription. 7894 * @param subscriptionId subscription ID see {@link SubscriptionInfo#getSubscriptionId()} 7895 * @param merged True for carrier merged network, false otherwise. 7896 * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} 7897 * @return True to indicate that carrier network offload is enabled, false otherwise. 7898 */ 7899 @RequiresPermission(ACCESS_WIFI_STATE) isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged)7900 public boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged) { 7901 try { 7902 return mService.isCarrierNetworkOffloadEnabled(subscriptionId, merged); 7903 } catch (RemoteException e) { 7904 throw e.rethrowFromSystemServer(); 7905 } 7906 } 7907 7908 /** 7909 * Interface for network suggestion user approval status change listener. 7910 * Should be implemented by applications and registered using 7911 * {@link #addSuggestionUserApprovalStatusListener(Executor, 7912 * SuggestionUserApprovalStatusListener)} ( 7913 */ 7914 public interface SuggestionUserApprovalStatusListener { 7915 7916 /** 7917 * Called when the user approval status of the App has changed. 7918 * @param status The current status code for the user approval. One of the 7919 * {@code STATUS_SUGGESTION_APPROVAL_} values. 7920 */ onUserApprovalStatusChange(@uggestionUserApprovalStatus int status)7921 void onUserApprovalStatusChange(@SuggestionUserApprovalStatus int status); 7922 } 7923 7924 private class SuggestionUserApprovalStatusListenerProxy extends 7925 ISuggestionUserApprovalStatusListener.Stub { 7926 private final Executor mExecutor; 7927 private final SuggestionUserApprovalStatusListener mListener; 7928 SuggestionUserApprovalStatusListenerProxy(@onNull Executor executor, @NonNull SuggestionUserApprovalStatusListener listener)7929 SuggestionUserApprovalStatusListenerProxy(@NonNull Executor executor, 7930 @NonNull SuggestionUserApprovalStatusListener listener) { 7931 mExecutor = executor; 7932 mListener = listener; 7933 } 7934 7935 @Override onUserApprovalStatusChange(int status)7936 public void onUserApprovalStatusChange(int status) { 7937 mExecutor.execute(() -> mListener.onUserApprovalStatusChange(status)); 7938 } 7939 7940 } 7941 7942 /** 7943 * Add a listener for Wi-Fi network suggestion user approval status. 7944 * See {@link SuggestionUserApprovalStatusListener}. 7945 * Caller will receive a callback immediately after adding a listener and when the user approval 7946 * status of the caller has changed. 7947 * Caller can remove a previously registered listener using 7948 * {@link WifiManager#removeSuggestionUserApprovalStatusListener( 7949 * SuggestionUserApprovalStatusListener)} 7950 * A caller can add multiple listeners to monitor the event. 7951 * @param executor The executor to execute the listener of the {@code listener} object. 7952 * @param listener listener for suggestion user approval status changes. 7953 */ 7954 @RequiresPermission(ACCESS_WIFI_STATE) addSuggestionUserApprovalStatusListener( @onNull @allbackExecutor Executor executor, @NonNull SuggestionUserApprovalStatusListener listener)7955 public void addSuggestionUserApprovalStatusListener( 7956 @NonNull @CallbackExecutor Executor executor, 7957 @NonNull SuggestionUserApprovalStatusListener listener) { 7958 if (listener == null) throw new NullPointerException("Listener cannot be null"); 7959 if (executor == null) throw new NullPointerException("Executor cannot be null"); 7960 Log.v(TAG, "addSuggestionUserApprovalStatusListener listener=" + listener 7961 + ", executor=" + executor); 7962 try { 7963 synchronized (sSuggestionUserApprovalStatusListenerMap) { 7964 ISuggestionUserApprovalStatusListener.Stub binderCallback = 7965 new SuggestionUserApprovalStatusListenerProxy(executor, listener); 7966 sSuggestionUserApprovalStatusListenerMap.put(System.identityHashCode(listener), 7967 binderCallback); 7968 mService.addSuggestionUserApprovalStatusListener(binderCallback, 7969 mContext.getOpPackageName()); 7970 } 7971 } catch (RemoteException e) { 7972 throw e.rethrowFromSystemServer(); 7973 } 7974 7975 } 7976 7977 /** 7978 * Allow callers to remove a previously registered listener using 7979 * {@link #addSuggestionUserApprovalStatusListener(Executor, 7980 * SuggestionUserApprovalStatusListener)}. After calling this method, 7981 * applications will no longer receive network suggestion user approval status change through 7982 * that listener. 7983 */ 7984 @RequiresPermission(ACCESS_WIFI_STATE) removeSuggestionUserApprovalStatusListener( @onNull SuggestionUserApprovalStatusListener listener)7985 public void removeSuggestionUserApprovalStatusListener( 7986 @NonNull SuggestionUserApprovalStatusListener listener) { 7987 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 7988 Log.v(TAG, "removeSuggestionUserApprovalStatusListener: listener=" + listener); 7989 try { 7990 synchronized (sSuggestionUserApprovalStatusListenerMap) { 7991 int listenerIdentifier = System.identityHashCode(listener); 7992 if (!sSuggestionUserApprovalStatusListenerMap.contains(listenerIdentifier)) { 7993 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 7994 return; 7995 } 7996 mService.removeSuggestionUserApprovalStatusListener( 7997 sSuggestionUserApprovalStatusListenerMap.get(listenerIdentifier), 7998 mContext.getOpPackageName()); 7999 sSuggestionUserApprovalStatusListenerMap.remove(listenerIdentifier); 8000 } 8001 } catch (RemoteException e) { 8002 throw e.rethrowFromSystemServer(); 8003 } 8004 } 8005 8006 /** 8007 * Indicates the start/end of an emergency scan request being processed by {@link WifiScanner}. 8008 * The wifi stack should ensure that the wifi chip remains on for the duration of the scan. 8009 * WifiScanner detects emergency scan requests via 8010 * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag. 8011 * 8012 * If the wifi stack is off (because location & wifi toggles are off) when this indication is 8013 * received, the wifi stack will temporarily move to a scan only mode. Since location toggle 8014 * is off, only scan with 8015 * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag set will be 8016 * allowed to be processed for this duration. 8017 * 8018 * @hide 8019 */ 8020 @RequiresPermission(android.Manifest.permission.NETWORK_STACK) setEmergencyScanRequestInProgress(boolean inProgress)8021 public void setEmergencyScanRequestInProgress(boolean inProgress) { 8022 try { 8023 mService.setEmergencyScanRequestInProgress(inProgress); 8024 } catch (RemoteException e) { 8025 throw e.rethrowFromSystemServer(); 8026 } 8027 } 8028 8029 /** 8030 * Enable or disable Wi-Fi scoring. Wi-Fi network status is evaluated by Wi-Fi scoring 8031 * {@link WifiScoreReport}. This API enables/disables Wi-Fi scoring to take action on network 8032 * selection. 8033 * 8034 * @param enabled {@code true} to enable, {@code false} to disable. 8035 * @return true The status of Wifi scoring is set successfully. 8036 * @hide 8037 */ 8038 @SystemApi 8039 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setWifiScoringEnabled(boolean enabled)8040 public boolean setWifiScoringEnabled(boolean enabled) { 8041 if (mVerboseLoggingEnabled) { 8042 Log.v(TAG, "setWifiScoringEnabled: " + enabled); 8043 } 8044 try { 8045 return mService.setWifiScoringEnabled(enabled); 8046 } catch (RemoteException e) { 8047 throw e.rethrowFromSystemServer(); 8048 } 8049 } 8050 8051 /** 8052 * Flush Passpoint ANQP cache, and clear pending ANQP requests. Allows the caller to reset the 8053 * Passpoint ANQP state, if required. 8054 * 8055 * Notes: 8056 * 1. Flushing the ANQP cache may cause delays in discovering and connecting to Passpoint 8057 * networks. 8058 * 2. Intended to be used by Device Owner (DO), Profile Owner (PO), Settings and provisioning 8059 * apps. 8060 */ 8061 @RequiresPermission(anyOf = { 8062 android.Manifest.permission.NETWORK_SETTINGS, 8063 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, 8064 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING 8065 }) flushPasspointAnqpCache()8066 public void flushPasspointAnqpCache() { 8067 try { 8068 mService.flushPasspointAnqpCache(mContext.getOpPackageName()); 8069 } catch (RemoteException e) { 8070 throw e.rethrowFromSystemServer(); 8071 } 8072 } 8073 8074 /** 8075 * Returns a list of {@link WifiAvailableChannel} for the specified band and operational 8076 * mode(s), that is allowed for the current regulatory domain. An empty list implies that there 8077 * are no available channels for use. 8078 * 8079 * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} 8080 * constants. 8081 * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED} - no band specified; Looks for the 8082 * channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz 8083 * 2. {@code WifiScanner#WIFI_BAND_24_GHZ} 8084 * 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS} 8085 * 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS} 8086 * 5. {@code WifiScanner#WIFI_BAND_6_GHZ} 8087 * 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ} 8088 * 7. {@code WifiScanner#WIFI_BAND_60_GHZ} 8089 * 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ} 8090 * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants 8091 * e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE} 8092 * @return a list of {@link WifiAvailableChannel} 8093 * 8094 * @throws UnsupportedOperationException - if this API is not supported on this device 8095 * or IllegalArgumentException - if the band specified is not one among the list 8096 * of bands mentioned above. 8097 * @hide 8098 */ 8099 @RequiresApi(Build.VERSION_CODES.S) 8100 @SystemApi 8101 @NonNull 8102 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) getAllowedChannels( @ifiScanner.WifiBand int band, @WifiAvailableChannel.OpMode int mode)8103 public List<WifiAvailableChannel> getAllowedChannels( 8104 @WifiScanner.WifiBand int band, 8105 @WifiAvailableChannel.OpMode int mode) { 8106 if (!SdkLevel.isAtLeastS()) { 8107 throw new UnsupportedOperationException(); 8108 } 8109 try { 8110 return mService.getUsableChannels(band, mode, 8111 WifiAvailableChannel.FILTER_REGULATORY); 8112 } catch (RemoteException e) { 8113 throw e.rethrowFromSystemServer(); 8114 } 8115 } 8116 8117 /** 8118 * Returns a list of {@link WifiAvailableChannel} for the specified band and operational 8119 * mode(s) per the current regulatory domain and device-specific constraints such as concurrency 8120 * state and interference due to other radios. An empty list implies that there are no available 8121 * channels for use. 8122 * 8123 * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} 8124 * constants. 8125 * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED} - no band specified; Looks for the 8126 * channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz 8127 * 2. {@code WifiScanner#WIFI_BAND_24_GHZ} 8128 * 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS} 8129 * 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS} 8130 * 5. {@code WifiScanner#WIFI_BAND_6_GHZ} 8131 * 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ} 8132 * 7. {@code WifiScanner#WIFI_BAND_60_GHZ} 8133 * 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ} 8134 * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants 8135 * e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE} 8136 * @return a list of {@link WifiAvailableChannel} 8137 * 8138 * @throws UnsupportedOperationException - if this API is not supported on this device 8139 * or IllegalArgumentException - if the band specified is not one among the list 8140 * of bands mentioned above. 8141 * @hide 8142 */ 8143 @RequiresApi(Build.VERSION_CODES.S) 8144 @SystemApi 8145 @NonNull 8146 @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) getUsableChannels( @ifiScanner.WifiBand int band, @WifiAvailableChannel.OpMode int mode)8147 public List<WifiAvailableChannel> getUsableChannels( 8148 @WifiScanner.WifiBand int band, 8149 @WifiAvailableChannel.OpMode int mode) { 8150 if (!SdkLevel.isAtLeastS()) { 8151 throw new UnsupportedOperationException(); 8152 } 8153 try { 8154 return mService.getUsableChannels(band, mode, 8155 WifiAvailableChannel.getUsableFilter()); 8156 } catch (RemoteException e) { 8157 throw e.rethrowFromSystemServer(); 8158 } 8159 } 8160 } 8161