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.CHANGE_WIFI_STATE; 22 import static android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION; 23 import static android.Manifest.permission.NEARBY_WIFI_DEVICES; 24 import static android.Manifest.permission.NETWORK_SETTINGS; 25 import static android.Manifest.permission.NETWORK_SETUP_WIZARD; 26 import static android.Manifest.permission.READ_WIFI_CREDENTIAL; 27 import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION; 28 29 import android.Manifest; 30 import android.annotation.CallbackExecutor; 31 import android.annotation.FlaggedApi; 32 import android.annotation.IntDef; 33 import android.annotation.IntRange; 34 import android.annotation.NonNull; 35 import android.annotation.Nullable; 36 import android.annotation.RequiresPermission; 37 import android.annotation.SdkConstant; 38 import android.annotation.SdkConstant.SdkConstantType; 39 import android.annotation.StringDef; 40 import android.annotation.SuppressLint; 41 import android.annotation.SystemApi; 42 import android.annotation.SystemService; 43 import android.app.ActivityManager; 44 import android.app.admin.WifiSsidPolicy; 45 import android.compat.annotation.ChangeId; 46 import android.compat.annotation.EnabledAfter; 47 import android.compat.annotation.UnsupportedAppUsage; 48 import android.content.Context; 49 import android.net.ConnectivityManager; 50 import android.net.ConnectivityManager.NetworkCallback; 51 import android.net.DhcpInfo; 52 import android.net.DhcpOption; 53 import android.net.LinkProperties; 54 import android.net.MacAddress; 55 import android.net.Network; 56 import android.net.NetworkCapabilities; 57 import android.net.NetworkRequest; 58 import android.net.NetworkStack; 59 import android.net.TetheringManager; 60 import android.net.Uri; 61 import android.net.wifi.hotspot2.IProvisioningCallback; 62 import android.net.wifi.hotspot2.OsuProvider; 63 import android.net.wifi.hotspot2.PasspointConfiguration; 64 import android.net.wifi.hotspot2.ProvisioningCallback; 65 import android.net.wifi.p2p.WifiP2pConfig; 66 import android.net.wifi.p2p.WifiP2pDiscoveryConfig; 67 import android.net.wifi.p2p.WifiP2pManager; 68 import android.net.wifi.twt.TwtRequest; 69 import android.net.wifi.twt.TwtSession; 70 import android.net.wifi.twt.TwtSessionCallback; 71 import android.os.Binder; 72 import android.os.Build; 73 import android.os.Bundle; 74 import android.os.Handler; 75 import android.os.IBinder; 76 import android.os.Looper; 77 import android.os.Parcel; 78 import android.os.Parcelable; 79 import android.os.RemoteException; 80 import android.os.WorkSource; 81 import android.os.connectivity.WifiActivityEnergyInfo; 82 import android.telephony.SubscriptionInfo; 83 import android.text.TextUtils; 84 import android.util.ArraySet; 85 import android.util.CloseGuard; 86 import android.util.Log; 87 import android.util.Pair; 88 import android.util.SparseArray; 89 90 import androidx.annotation.RequiresApi; 91 92 import com.android.internal.annotations.GuardedBy; 93 import com.android.internal.annotations.VisibleForTesting; 94 import com.android.modules.utils.HandlerExecutor; 95 import com.android.modules.utils.ParceledListSlice; 96 import com.android.modules.utils.build.SdkLevel; 97 import com.android.wifi.flags.Flags; 98 99 import java.lang.annotation.Retention; 100 import java.lang.annotation.RetentionPolicy; 101 import java.lang.ref.Reference; 102 import java.lang.ref.WeakReference; 103 import java.net.InetAddress; 104 import java.time.Duration; 105 import java.util.ArrayList; 106 import java.util.Arrays; 107 import java.util.Collections; 108 import java.util.HashMap; 109 import java.util.List; 110 import java.util.Map; 111 import java.util.Objects; 112 import java.util.Set; 113 import java.util.StringTokenizer; 114 import java.util.concurrent.Executor; 115 import java.util.function.BiConsumer; 116 import java.util.function.Consumer; 117 import java.util.function.IntConsumer; 118 119 /** 120 * This class provides the primary API for managing all aspects of Wi-Fi 121 * connectivity. 122 * <p> 123 * On releases before {@link android.os.Build.VERSION_CODES#N}, this object 124 * should only be obtained from an {@linkplain Context#getApplicationContext() 125 * application context}, and not from any other derived context to avoid memory 126 * leaks within the calling process. 127 * <p> 128 * It deals with several categories of items: 129 * </p> 130 * <ul> 131 * <li>The list of configured networks. The list can be viewed and updated, and 132 * attributes of individual entries can be modified.</li> 133 * <li>The currently active Wi-Fi network, if any. Connectivity can be 134 * established or torn down, and dynamic information about the state of the 135 * network can be queried.</li> 136 * <li>Results of access point scans, containing enough information to make 137 * decisions about what access point to connect to.</li> 138 * <li>It defines the names of various Intent actions that are broadcast upon 139 * any sort of change in Wi-Fi state. 140 * </ul> 141 * <p> 142 * This is the API to use when performing Wi-Fi specific operations. To perform 143 * operations that pertain to network connectivity at an abstract level, use 144 * {@link android.net.ConnectivityManager}. 145 * </p> 146 */ 147 @SystemService(Context.WIFI_SERVICE) 148 public class WifiManager { 149 150 private static final String TAG = "WifiManager"; 151 152 /** 153 * Local networks should not be modified by B&R since the user may have 154 * updated it with the latest configurations. 155 * @hide 156 */ 157 @ChangeId 158 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2) 159 public static final long NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE = 234793325L; 160 161 // Supplicant error codes: 162 /** 163 * The error code if there was a problem authenticating. 164 * @deprecated This is no longer supported. 165 */ 166 @Deprecated 167 public static final int ERROR_AUTHENTICATING = 1; 168 169 /** 170 * The reason code if there is no error during authentication. 171 * It could also imply that there no authentication in progress, 172 * this reason code also serves as a reset value. 173 * @deprecated This is no longer supported. 174 * @hide 175 */ 176 @Deprecated 177 public static final int ERROR_AUTH_FAILURE_NONE = 0; 178 179 /** 180 * The reason code if there was a timeout authenticating. 181 * @deprecated This is no longer supported. 182 * @hide 183 */ 184 @Deprecated 185 public static final int ERROR_AUTH_FAILURE_TIMEOUT = 1; 186 187 /** 188 * The reason code if there was a wrong password while 189 * authenticating. 190 * @deprecated This is no longer supported. 191 * @hide 192 */ 193 @Deprecated 194 public static final int ERROR_AUTH_FAILURE_WRONG_PSWD = 2; 195 196 /** 197 * The reason code if there was EAP failure while 198 * authenticating. 199 * @deprecated This is no longer supported. 200 * @hide 201 */ 202 @Deprecated 203 public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3; 204 205 /** @hide */ 206 public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM = 256; 207 208 /** @hide */ 209 public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM = 1024; 210 211 /** 212 * Reason code if all of the network suggestions were successfully added or removed. 213 */ 214 public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; 215 216 /** 217 * Reason code if there was an internal error in the platform while processing the addition or 218 * removal of suggestions. 219 */ 220 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1; 221 222 /** 223 * Reason code if the user has disallowed "android:change_wifi_state" app-ops from the app. 224 * @see android.app.AppOpsManager#unsafeCheckOp(String, int, String). 225 */ 226 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED = 2; 227 228 /** 229 * Reason code if one or more of the network suggestions added already exists in platform's 230 * database. 231 * Note: this code will not be returned with Android 11 as in-place modification is allowed, 232 * please check {@link #addNetworkSuggestions(List)}. 233 * @see WifiNetworkSuggestion#equals(Object) 234 */ 235 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 3; 236 237 /** 238 * Reason code if the number of network suggestions provided by the app crosses the max 239 * threshold set per app. 240 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} if 241 * the total size exceeds the limit. 242 * @see #getMaxNumberOfNetworkSuggestionsPerApp() 243 */ 244 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 4; 245 246 /** 247 * Reason code if one or more of the network suggestions removed does not exist in platform's 248 * database. 249 * The framework won't remove any suggestions if one or more of suggestions provided 250 * by {@link #removeNetworkSuggestions(List)} does not exist in database. 251 * @see WifiNetworkSuggestion#equals(Object) 252 */ 253 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5; 254 255 /** 256 * Reason code if one or more of the network suggestions added is not allowed. 257 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} 258 * if one or more of them is not allowed. 259 * This error may be caused by suggestion is using SIM-based encryption method, but calling app 260 * is not carrier privileged. 261 */ 262 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED = 6; 263 264 /** 265 * Reason code if one or more of the network suggestions added is invalid. Framework will reject 266 * all the suggestions in the list. 267 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} 268 * if one or more of them is invalid. 269 * Please use {@link WifiNetworkSuggestion.Builder} to create network suggestions. 270 */ 271 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID = 7; 272 273 /** 274 * Reason code if {@link android.os.UserManager#DISALLOW_ADD_WIFI_CONFIG} user restriction 275 * is set and calling app is restricted by device admin. 276 */ 277 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN = 8; 278 279 /** @hide */ 280 @IntDef(prefix = { "STATUS_NETWORK_SUGGESTIONS_" }, value = { 281 STATUS_NETWORK_SUGGESTIONS_SUCCESS, 282 STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, 283 STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED, 284 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE, 285 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP, 286 STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, 287 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED, 288 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, 289 STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN, 290 }) 291 @Retention(RetentionPolicy.SOURCE) 292 public @interface NetworkSuggestionsStatusCode {} 293 294 /** 295 * Reason code if suggested network connection attempt failed with an unknown failure. 296 */ 297 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN = 0; 298 /** 299 * Reason code if suggested network connection attempt failed with association failure. 300 */ 301 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION = 1; 302 /** 303 * Reason code if suggested network connection attempt failed with an authentication failure. 304 */ 305 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION = 2; 306 /** 307 * Reason code if suggested network connection attempt failed with an IP provision failure. 308 */ 309 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING = 3; 310 311 /** @hide */ 312 @IntDef(prefix = {"STATUS_SUGGESTION_CONNECTION_FAILURE_"}, 313 value = {STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN, 314 STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION, 315 STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION, 316 STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING 317 }) 318 @Retention(RetentionPolicy.SOURCE) 319 public @interface SuggestionConnectionStatusCode {} 320 321 /** 322 * Reason code if local-only network connection attempt failed with an unknown failure. 323 */ 324 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_UNKNOWN = 0; 325 /** 326 * Reason code if local-only network connection attempt failed with association failure. 327 */ 328 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_ASSOCIATION = 1; 329 /** 330 * Reason code if local-only network connection attempt failed with an authentication failure. 331 */ 332 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION = 2; 333 /** 334 * Reason code if local-only network connection attempt failed with an IP provisioning failure. 335 */ 336 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING = 3; 337 /** 338 * Reason code if local-only network connection attempt failed with AP not in range. 339 */ 340 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND = 4; 341 /** 342 * Reason code if local-only network connection attempt failed with AP not responding 343 */ 344 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE = 5; 345 346 /** @hide */ 347 @IntDef(prefix = {"STATUS_LOCAL_ONLY_CONNECTION_FAILURE_"}, 348 value = {STATUS_LOCAL_ONLY_CONNECTION_FAILURE_UNKNOWN, 349 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_ASSOCIATION, 350 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION, 351 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING, 352 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND, 353 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE 354 }) 355 @Retention(RetentionPolicy.SOURCE) 356 public @interface LocalOnlyConnectionStatusCode {} 357 358 /** 359 * Status code if suggestion approval status is unknown, an App which hasn't made any 360 * suggestions will get this code. 361 */ 362 public static final int STATUS_SUGGESTION_APPROVAL_UNKNOWN = 0; 363 364 /** 365 * Status code if the calling app is still pending user approval for suggestions. 366 */ 367 public static final int STATUS_SUGGESTION_APPROVAL_PENDING = 1; 368 369 /** 370 * Status code if the calling app got the user approval for suggestions. 371 */ 372 public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER = 2; 373 374 /** 375 * Status code if the calling app suggestions were rejected by the user. 376 */ 377 public static final int STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER = 3; 378 379 /** 380 * Status code if the calling app was approved by virtue of being a carrier privileged app. 381 * 382 * @see android.telephony.TelephonyManager#hasCarrierPrivileges() 383 */ 384 public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE = 4; 385 386 /** @hide */ 387 @IntDef(prefix = {"STATUS_SUGGESTION_APPROVAL_"}, 388 value = {STATUS_SUGGESTION_APPROVAL_UNKNOWN, 389 STATUS_SUGGESTION_APPROVAL_PENDING, 390 STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER, 391 STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER, 392 STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE 393 }) 394 @Retention(RetentionPolicy.SOURCE) 395 public @interface SuggestionUserApprovalStatus {} 396 397 /** 398 * Disable PNO scan until device reboot. 399 * @hide 400 */ 401 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 402 @SystemApi 403 public static final int PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT = 0; 404 405 /** 406 * Disable PNO scan until device reboot or Wi-Fi is toggled. 407 * @hide 408 */ 409 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 410 @SystemApi 411 public static final int PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE = 1; 412 413 /** 414 * Enable PNO scan. 415 * @hide 416 */ 417 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 418 @SystemApi 419 public static final int PNO_SCAN_STATE_ENABLED = 2; 420 421 /** @hide */ 422 @IntDef(prefix = {"PNO_SCAN_STATE_"}, 423 value = {PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT, 424 PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE, 425 PNO_SCAN_STATE_ENABLED 426 }) 427 @Retention(RetentionPolicy.SOURCE) 428 public @interface PnoScanState {} 429 430 /** 431 * If one of the removed suggestions is currently connected, that network will be disconnected 432 * after a short delay as opposed to immediately (which will be done by 433 * {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT}). The {@link ConnectivityManager} may call the 434 * {@link NetworkCallback#onLosing(Network, int)} on such networks. 435 */ 436 public static final int ACTION_REMOVE_SUGGESTION_LINGER = 1; 437 438 /** 439 * If one of the removed suggestions is currently connected, trigger an immediate disconnect 440 * after suggestions removal 441 */ 442 public static final int ACTION_REMOVE_SUGGESTION_DISCONNECT = 2; 443 444 /** @hide */ 445 @IntDef(prefix = {"ACTION_REMOVE_SUGGESTION_"}, 446 value = {ACTION_REMOVE_SUGGESTION_LINGER, 447 ACTION_REMOVE_SUGGESTION_DISCONNECT 448 }) 449 @Retention(RetentionPolicy.SOURCE) 450 public @interface ActionAfterRemovingSuggestion {} 451 452 /** 453 * Only available on Android S or later. 454 * @hide 455 **/ 456 public static final String EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE = 457 "EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE"; 458 459 /** 460 * Broadcast intent action indicating whether Wi-Fi scanning is currently available. 461 * Available extras: 462 * - {@link #EXTRA_SCAN_AVAILABLE} 463 */ 464 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 465 public static final String ACTION_WIFI_SCAN_AVAILABILITY_CHANGED = 466 "android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED"; 467 468 /** 469 * A boolean extra indicating whether scanning is currently available. 470 * Sent in the broadcast {@link #ACTION_WIFI_SCAN_AVAILABILITY_CHANGED}. 471 * Its value is true if scanning is currently available, false otherwise. 472 */ 473 public static final String EXTRA_SCAN_AVAILABLE = "android.net.wifi.extra.SCAN_AVAILABLE"; 474 475 /** 476 * Broadcast intent action indicating that the credential of a Wi-Fi network 477 * has been changed. One extra provides the ssid of the network. Another 478 * extra provides the event type, whether the credential is saved or forgot. 479 * @hide 480 */ 481 @SystemApi 482 public static final String WIFI_CREDENTIAL_CHANGED_ACTION = 483 "android.net.wifi.WIFI_CREDENTIAL_CHANGED"; 484 /** @hide */ 485 @SystemApi 486 public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et"; 487 /** @hide */ 488 @SystemApi 489 public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid"; 490 /** @hide */ 491 @SystemApi 492 public static final int WIFI_CREDENTIAL_SAVED = 0; 493 /** @hide */ 494 @SystemApi 495 public static final int WIFI_CREDENTIAL_FORGOT = 1; 496 497 /** @hide */ 498 @SystemApi 499 public static final int PASSPOINT_HOME_NETWORK = 0; 500 501 /** @hide */ 502 @SystemApi 503 public static final int PASSPOINT_ROAMING_NETWORK = 1; 504 505 /** @hide */ 506 @Retention(RetentionPolicy.SOURCE) 507 @IntDef(value = { 508 API_SCANNING_ENABLED, 509 API_WIFI_ENABLED, 510 API_SOFT_AP, 511 API_TETHERED_HOTSPOT, 512 API_AUTOJOIN_GLOBAL, 513 API_SET_SCAN_SCHEDULE, 514 API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY, 515 API_SET_NETWORK_SELECTION_CONFIG, 516 API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG, 517 API_ADD_NETWORK, 518 API_UPDATE_NETWORK, 519 API_ALLOW_AUTOJOIN, 520 API_CONNECT_CONFIG, 521 API_CONNECT_NETWORK_ID, 522 API_DISABLE_NETWORK, 523 API_ENABLE_NETWORK, 524 API_FORGET, 525 API_SAVE, 526 API_START_SCAN, 527 API_START_LOCAL_ONLY_HOTSPOT, 528 API_P2P_DISCOVER_PEERS, 529 API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS, 530 API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY, 531 API_P2P_STOP_PEER_DISCOVERY, 532 API_P2P_CONNECT, 533 API_P2P_CANCEL_CONNECT, 534 API_P2P_CREATE_GROUP, 535 API_P2P_CREATE_GROUP_P2P_CONFIG, 536 API_P2P_REMOVE_GROUP, 537 API_P2P_START_LISTENING, 538 API_P2P_STOP_LISTENING, 539 API_P2P_SET_CHANNELS, 540 API_WIFI_SCANNER_START_SCAN, 541 API_SET_TDLS_ENABLED, 542 API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS, 543 API_P2P_DISCOVER_PEERS_WITH_CONFIG_PARAMS 544 }) 545 public @interface ApiType {} 546 547 /** 548 * A constant used in 549 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 550 * Tracks usage of {@link WifiScanner#setScanningEnabled(boolean)} 551 * @hide 552 */ 553 @SystemApi 554 public static final int API_SCANNING_ENABLED = 1; 555 /** 556 * A constant used in 557 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 558 * Tracks usage of {@link WifiManager#setWifiEnabled(boolean)} . 559 * @hide 560 */ 561 @SystemApi 562 public static final int API_WIFI_ENABLED = 2; 563 /** 564 * A constant used in 565 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 566 * Tracks usage of {@link WifiManager#startSoftAp(WifiConfiguration)} and 567 * {@link WifiManager#stopSoftAp()}. 568 * @hide 569 */ 570 @SystemApi 571 public static final int API_SOFT_AP = 3; 572 /** 573 * A constant used in 574 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 575 * Tracks usage of {@link WifiManager#startTetheredHotspot(SoftApConfiguration)}. 576 * @hide 577 */ 578 @SystemApi 579 public static final int API_TETHERED_HOTSPOT = 4; 580 /** 581 * A constant used in 582 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 583 * Tracks usage of {@link WifiManager#allowAutojoinGlobal(boolean)}. 584 * @hide 585 */ 586 @SystemApi 587 public static final int API_AUTOJOIN_GLOBAL = 5; 588 /** 589 * A constant used in 590 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 591 * Tracks usage of {@link WifiManager#setScreenOnScanSchedule(List)}. 592 * @hide 593 */ 594 @SystemApi 595 public static final int API_SET_SCAN_SCHEDULE = 6; 596 597 /** 598 * A constant used in 599 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 600 * Tracks usage of {@link WifiManager#setOneShotScreenOnConnectivityScanDelayMillis(int)}. 601 * @hide 602 */ 603 @SystemApi 604 public static final int API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY = 7; 605 606 /** 607 * A constant used in 608 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 609 * Tracks usage of 610 * {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)} 611 * @hide 612 */ 613 @SystemApi 614 public static final int API_SET_NETWORK_SELECTION_CONFIG = 8; 615 616 /** 617 * A constant used in 618 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 619 * Tracks usage of 620 * {@link WifiManager#setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} 621 * @hide 622 */ 623 @SystemApi 624 public static final int API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG = 9; 625 626 /** 627 * A constant used in 628 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 629 * Tracks usage of 630 * {@link WifiManager#addNetwork(WifiConfiguration)} 631 * @hide 632 */ 633 @SystemApi 634 public static final int API_ADD_NETWORK = 10; 635 636 /** 637 * A constant used in 638 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 639 * Tracks usage of 640 * {@link WifiManager#updateNetwork(WifiConfiguration)} 641 * @hide 642 */ 643 @SystemApi 644 public static final int API_UPDATE_NETWORK = 11; 645 646 /** 647 * A constant used in 648 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 649 * Tracks usage of 650 * {@link WifiManager#allowAutojoin(int, boolean)} 651 * @hide 652 */ 653 @SystemApi 654 public static final int API_ALLOW_AUTOJOIN = 12; 655 656 /** 657 * A constant used in 658 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 659 * Tracks usage of 660 * {@link WifiManager#connect(WifiConfiguration, ActionListener)} 661 * @hide 662 */ 663 @SystemApi 664 public static final int API_CONNECT_CONFIG = 13; 665 666 /** 667 * A constant used in 668 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 669 * Tracks usage of 670 * {@link WifiManager#connect(int, ActionListener)} 671 * @hide 672 */ 673 @SystemApi 674 public static final int API_CONNECT_NETWORK_ID = 14; 675 676 /** 677 * A constant used in 678 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 679 * Tracks usage of 680 * {@link WifiManager#disableNetwork(int)} 681 * @hide 682 */ 683 @SystemApi 684 public static final int API_DISABLE_NETWORK = 15; 685 686 /** 687 * A constant used in 688 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 689 * Tracks usage of 690 * {@link WifiManager#enableNetwork(int, boolean)} 691 * @hide 692 */ 693 @SystemApi 694 public static final int API_ENABLE_NETWORK = 16; 695 696 /** 697 * A constant used in 698 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 699 * Tracks usage of 700 * {@link WifiManager#forget(int, ActionListener)} 701 * @hide 702 */ 703 @SystemApi 704 public static final int API_FORGET = 17; 705 706 /** 707 * A constant used in 708 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 709 * Tracks usage of 710 * {@link WifiManager#save(WifiConfiguration, ActionListener)} 711 * @hide 712 */ 713 @SystemApi 714 public static final int API_SAVE = 18; 715 716 /** 717 * A constant used in 718 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 719 * Tracks usage of 720 * {@link WifiManager#startScan()} 721 * @hide 722 */ 723 @SystemApi 724 public static final int API_START_SCAN = 19; 725 726 /** 727 * A constant used in 728 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 729 * Tracks usage of 730 * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} 731 * @hide 732 */ 733 @SystemApi 734 public static final int API_START_LOCAL_ONLY_HOTSPOT = 20; 735 736 /** 737 * A constant used in 738 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 739 * Tracks usage of 740 * {@link WifiP2pManager#discoverPeers(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 741 * @hide 742 */ 743 @SystemApi 744 public static final int API_P2P_DISCOVER_PEERS = 21; 745 746 /** 747 * A constant used in 748 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 749 * Tracks usage of 750 * {@link WifiP2pManager#discoverPeersOnSocialChannels(WifiP2pManager.Channel, 751 * WifiP2pManager.ActionListener)} 752 * @hide 753 */ 754 @SystemApi 755 public static final int API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS = 22; 756 757 /** 758 * A constant used in 759 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 760 * Tracks usage of 761 * {@link WifiP2pManager#discoverPeersOnSpecificFrequency(WifiP2pManager.Channel, int, 762 * WifiP2pManager.ActionListener)} 763 * @hide 764 */ 765 @SystemApi 766 public static final int API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY = 23; 767 768 /** 769 * A constant used in 770 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 771 * Tracks usage of 772 * {@link WifiP2pManager#stopPeerDiscovery(WifiP2pManager.Channel, 773 * WifiP2pManager.ActionListener)} 774 * @hide 775 */ 776 @SystemApi 777 public static final int API_P2P_STOP_PEER_DISCOVERY = 24; 778 779 /** 780 * A constant used in 781 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 782 * Tracks usage of 783 * {@link WifiP2pManager#connect(WifiP2pManager.Channel, WifiP2pConfig, 784 * WifiP2pManager.ActionListener)} 785 * @hide 786 */ 787 @SystemApi 788 public static final int API_P2P_CONNECT = 25; 789 790 /** 791 * A constant used in 792 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 793 * Tracks usage of 794 * {@link WifiP2pManager#cancelConnect(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 795 * @hide 796 */ 797 @SystemApi 798 public static final int API_P2P_CANCEL_CONNECT = 26; 799 800 /** 801 * A constant used in 802 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 803 * Tracks usage of 804 * {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 805 * @hide 806 */ 807 @SystemApi 808 public static final int API_P2P_CREATE_GROUP = 27; 809 810 /** 811 * A constant used in 812 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 813 * Tracks usage of 814 * {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pConfig, 815 * WifiP2pManager.ActionListener)} 816 * @hide 817 */ 818 @SystemApi 819 public static final int API_P2P_CREATE_GROUP_P2P_CONFIG = 28; 820 821 /** 822 * A constant used in 823 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 824 * Tracks usage of 825 * {@link WifiP2pManager#removeGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 826 * @hide 827 */ 828 @SystemApi 829 public static final int API_P2P_REMOVE_GROUP = 29; 830 831 /** 832 * A constant used in 833 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 834 * Tracks usage of 835 * {@link WifiP2pManager#startListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 836 * @hide 837 */ 838 @SystemApi 839 public static final int API_P2P_START_LISTENING = 30; 840 841 /** 842 * A constant used in 843 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 844 * Tracks usage of 845 * {@link WifiP2pManager#stopListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 846 * @hide 847 */ 848 @SystemApi 849 public static final int API_P2P_STOP_LISTENING = 31; 850 851 /** 852 * A constant used in 853 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 854 * Tracks usage of 855 * {@link WifiP2pManager#setWifiP2pChannels(WifiP2pManager.Channel, int, int, 856 * WifiP2pManager.ActionListener)} 857 * @hide 858 */ 859 @SystemApi 860 public static final int API_P2P_SET_CHANNELS = 32; 861 862 /** 863 * A constant used in 864 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 865 * Tracks usage of 866 * {@link WifiScanner#startScan(WifiScanner.ScanSettings, WifiScanner.ScanListener)} 867 * @hide 868 */ 869 @SystemApi 870 public static final int API_WIFI_SCANNER_START_SCAN = 33; 871 872 /** 873 * A constant used in 874 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 875 * Tracks usage of 876 * {@link WifiManager#setTdlsEnabled(InetAddress, boolean)} and 877 * {@link WifiManager#setTdlsEnabled(InetAddress, boolean, Executor, Consumer)} 878 * @hide 879 */ 880 @SystemApi 881 public static final int API_SET_TDLS_ENABLED = 34; 882 883 /** 884 * A constant used in 885 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 886 * Tracks usage of 887 * {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean)} and 888 * {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)} 889 * @hide 890 */ 891 @SystemApi 892 public static final int API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS = 35; 893 894 /** 895 * A constant used in {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 896 * Tracks usage of {@link WifiManager#setPnoScanState(int)} 897 * 898 * @hide 899 */ 900 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 901 @SystemApi 902 public static final int API_SET_PNO_SCAN_ENABLED = 36; 903 904 /** 905 * A constant used in {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 906 * Tracks usage of {@link WifiP2pManager#discoverPeersWithConfigParams( 907 * WifiP2pManager.Channel, WifiP2pDiscoveryConfig, WifiP2pManager.ActionListener)} 908 * 909 * @hide 910 */ 911 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 912 @SystemApi 913 public static final int API_P2P_DISCOVER_PEERS_WITH_CONFIG_PARAMS = 37; 914 915 /** 916 * Used internally to keep track of boundary. 917 * @hide 918 */ 919 public static final int API_MAX = 38; 920 921 /** 922 * Broadcast intent action indicating that a Passpoint provider icon has been received. 923 * 924 * Included extras: 925 * {@link #EXTRA_BSSID_LONG} 926 * {@link #EXTRA_FILENAME} 927 * {@link #EXTRA_ICON} 928 * 929 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 930 * 931 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 932 * components will be launched. 933 * 934 * @hide 935 */ 936 public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; 937 /** 938 * BSSID of an AP in long representation. The {@link #EXTRA_BSSID} contains BSSID in 939 * String representation. 940 * 941 * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}. 942 * 943 * @hide 944 */ 945 public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; 946 /** 947 * Icon data. 948 * 949 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into 950 * {@link android.graphics.drawable.Icon}. 951 * 952 * @hide 953 */ 954 public static final String EXTRA_ICON = "android.net.wifi.extra.ICON"; 955 /** 956 * Name of a file. 957 * 958 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 959 * 960 * @hide 961 */ 962 public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; 963 964 /** 965 * Broadcast intent action indicating a Passpoint OSU Providers List element has been received. 966 * 967 * Included extras: 968 * {@link #EXTRA_BSSID_LONG} 969 * {@link #EXTRA_ANQP_ELEMENT_DATA} 970 * 971 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 972 * 973 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 974 * components will be launched. 975 * 976 * @hide 977 */ 978 public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = 979 "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; 980 /** 981 * Raw binary data of an ANQP (Access Network Query Protocol) element. 982 * 983 * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}. 984 * 985 * @hide 986 */ 987 public static final String EXTRA_ANQP_ELEMENT_DATA = 988 "android.net.wifi.extra.ANQP_ELEMENT_DATA"; 989 990 /** 991 * Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received. 992 * 993 * Included extras: 994 * {@link #EXTRA_BSSID_LONG} 995 * {@link #EXTRA_ESS} 996 * {@link #EXTRA_DELAY} 997 * {@link #EXTRA_URL} 998 * 999 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 1000 * 1001 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 1002 * components will be launched. 1003 * 1004 * @hide 1005 */ 1006 public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT = 1007 "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; 1008 /** 1009 * Flag indicating BSS (Basic Service Set) or ESS (Extended Service Set). This will be set to 1010 * {@code true} for ESS. 1011 * 1012 * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}. 1013 * 1014 * @hide 1015 */ 1016 public static final String EXTRA_ESS = "android.net.wifi.extra.ESS"; 1017 /** 1018 * Delay in seconds. 1019 * 1020 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 1021 * 1022 * @hide 1023 */ 1024 public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; 1025 1026 /** 1027 * Broadcast intent action indicating a Passpoint subscription remediation frame has been 1028 * received. 1029 * 1030 * Included extras: 1031 * {@link #EXTRA_BSSID_LONG} 1032 * {@link #EXTRA_SUBSCRIPTION_REMEDIATION_METHOD} 1033 * {@link #EXTRA_URL} 1034 * 1035 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 1036 * 1037 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 1038 * components will be launched. 1039 * 1040 * @hide 1041 */ 1042 public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = 1043 "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; 1044 /** 1045 * The protocol supported by the subscription remediation server. The possible values are: 1046 * 0 - OMA DM 1047 * 1 - SOAP XML SPP 1048 * 1049 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 1050 * 1051 * @hide 1052 */ 1053 public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = 1054 "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; 1055 1056 /** 1057 * Activity Action: Receiver should launch Passpoint OSU (Online Sign Up) view. 1058 * Included extras: 1059 * 1060 * {@link #EXTRA_OSU_NETWORK}: {@link Network} instance associated with OSU AP. 1061 * {@link #EXTRA_URL}: String representation of a server URL used for OSU process. 1062 * 1063 * @hide 1064 */ 1065 @SystemApi 1066 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1067 public static final String ACTION_PASSPOINT_LAUNCH_OSU_VIEW = 1068 "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW"; 1069 1070 /** 1071 * The lookup key for a {@link android.net.Network} associated with a Passpoint OSU server. 1072 * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast. 1073 * 1074 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 1075 * 1076 * @hide 1077 */ 1078 @SystemApi 1079 public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK"; 1080 1081 /** 1082 * String representation of an URL for Passpoint OSU. 1083 * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast. 1084 * 1085 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 1086 * 1087 * @hide 1088 */ 1089 @SystemApi 1090 public static final String EXTRA_URL = "android.net.wifi.extra.URL"; 1091 1092 /** 1093 * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, 1094 * enabling, disabling, or unknown. One extra provides this state as an int. 1095 * Another extra provides the previous state, if available. No network-related 1096 * permissions are required to subscribe to this broadcast. 1097 * 1098 * <p class="note">This broadcast is not delivered to manifest receivers in 1099 * applications that target API version 26 or later. 1100 * 1101 * @see #EXTRA_WIFI_STATE 1102 * @see #EXTRA_PREVIOUS_WIFI_STATE 1103 */ 1104 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1105 public static final String WIFI_STATE_CHANGED_ACTION = 1106 "android.net.wifi.WIFI_STATE_CHANGED"; 1107 /** 1108 * The lookup key for an int that indicates whether Wi-Fi is enabled, 1109 * disabled, enabling, disabling, or unknown. Retrieve it with 1110 * {@link android.content.Intent#getIntExtra(String,int)}. 1111 * 1112 * @see #WIFI_STATE_DISABLED 1113 * @see #WIFI_STATE_DISABLING 1114 * @see #WIFI_STATE_ENABLED 1115 * @see #WIFI_STATE_ENABLING 1116 * @see #WIFI_STATE_UNKNOWN 1117 */ 1118 public static final String EXTRA_WIFI_STATE = "wifi_state"; 1119 /** 1120 * The previous Wi-Fi state. 1121 * 1122 * @see #EXTRA_WIFI_STATE 1123 */ 1124 public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; 1125 1126 /** 1127 * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if 1128 * it finishes successfully. 1129 * 1130 * @see #WIFI_STATE_CHANGED_ACTION 1131 * @see #getWifiState() 1132 */ 1133 public static final int WIFI_STATE_DISABLING = 0; 1134 /** 1135 * Wi-Fi is disabled. 1136 * 1137 * @see #WIFI_STATE_CHANGED_ACTION 1138 * @see #getWifiState() 1139 */ 1140 public static final int WIFI_STATE_DISABLED = 1; 1141 /** 1142 * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if 1143 * it finishes successfully. 1144 * 1145 * @see #WIFI_STATE_CHANGED_ACTION 1146 * @see #getWifiState() 1147 */ 1148 public static final int WIFI_STATE_ENABLING = 2; 1149 /** 1150 * Wi-Fi is enabled. 1151 * 1152 * @see #WIFI_STATE_CHANGED_ACTION 1153 * @see #getWifiState() 1154 */ 1155 public static final int WIFI_STATE_ENABLED = 3; 1156 /** 1157 * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling 1158 * or disabling. 1159 * 1160 * @see #WIFI_STATE_CHANGED_ACTION 1161 * @see #getWifiState() 1162 */ 1163 public static final int WIFI_STATE_UNKNOWN = 4; 1164 1165 /** 1166 * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled, 1167 * enabling, disabling, or failed. 1168 * 1169 * @hide 1170 */ 1171 @SystemApi 1172 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 1173 public static final String WIFI_AP_STATE_CHANGED_ACTION = 1174 "android.net.wifi.WIFI_AP_STATE_CHANGED"; 1175 1176 /** 1177 * The lookup key for an int that indicates whether Wi-Fi AP is enabled, 1178 * disabled, enabling, disabling, or failed. Retrieve it with 1179 * {@link android.content.Intent#getIntExtra(String,int)}. 1180 * 1181 * @see #WIFI_AP_STATE_DISABLED 1182 * @see #WIFI_AP_STATE_DISABLING 1183 * @see #WIFI_AP_STATE_ENABLED 1184 * @see #WIFI_AP_STATE_ENABLING 1185 * @see #WIFI_AP_STATE_FAILED 1186 * 1187 * @hide 1188 */ 1189 @SystemApi 1190 public static final String EXTRA_WIFI_AP_STATE = "wifi_state"; 1191 1192 /** 1193 * An extra containing the int error code for Soft AP start failure. 1194 * Can be obtained from the {@link #WIFI_AP_STATE_CHANGED_ACTION} using 1195 * {@link android.content.Intent#getIntExtra}. 1196 * This extra will only be attached if {@link #EXTRA_WIFI_AP_STATE} is 1197 * attached and is equal to {@link #WIFI_AP_STATE_FAILED}. 1198 * 1199 * The error code will be one of: 1200 * {@link #SAP_START_FAILURE_GENERAL}, 1201 * {@link #SAP_START_FAILURE_NO_CHANNEL}, 1202 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION} 1203 * {@link #SAP_START_FAILURE_USER_REJECTED} 1204 * 1205 * @hide 1206 */ 1207 @SystemApi 1208 public static final String EXTRA_WIFI_AP_FAILURE_REASON = 1209 "android.net.wifi.extra.WIFI_AP_FAILURE_REASON"; 1210 /** 1211 * The previous Wi-Fi state. 1212 * 1213 * @see #EXTRA_WIFI_AP_STATE 1214 * 1215 * @hide 1216 */ 1217 @SystemApi 1218 public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; 1219 /** 1220 * The lookup key for a String extra that stores the interface name used for the Soft AP. 1221 * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. 1222 * Retrieve its value with {@link android.content.Intent#getStringExtra(String)}. 1223 * 1224 * @hide 1225 */ 1226 @SystemApi 1227 public static final String EXTRA_WIFI_AP_INTERFACE_NAME = 1228 "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME"; 1229 /** 1230 * The lookup key for an int extra that stores the intended IP mode for this Soft AP. 1231 * One of {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}. 1232 * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. 1233 * Retrieve its value with {@link android.content.Intent#getIntExtra(String, int)}. 1234 * 1235 * @hide 1236 */ 1237 @SystemApi 1238 public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE"; 1239 1240 /** @hide */ 1241 @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = { 1242 WIFI_AP_STATE_DISABLING, 1243 WIFI_AP_STATE_DISABLED, 1244 WIFI_AP_STATE_ENABLING, 1245 WIFI_AP_STATE_ENABLED, 1246 WIFI_AP_STATE_FAILED, 1247 }) 1248 @Retention(RetentionPolicy.SOURCE) 1249 public @interface WifiApState {} 1250 1251 /** 1252 * Wi-Fi AP is currently being disabled. The state will change to 1253 * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully. 1254 * 1255 * @see #WIFI_AP_STATE_CHANGED_ACTION 1256 * @see #getWifiApState() 1257 * 1258 * @hide 1259 */ 1260 @SystemApi 1261 public static final int WIFI_AP_STATE_DISABLING = 10; 1262 /** 1263 * Wi-Fi AP is disabled. 1264 * 1265 * @see #WIFI_AP_STATE_CHANGED_ACTION 1266 * @see #getWifiState() 1267 * 1268 * @hide 1269 */ 1270 @SystemApi 1271 public static final int WIFI_AP_STATE_DISABLED = 11; 1272 /** 1273 * Wi-Fi AP is currently being enabled. The state will change to 1274 * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully. 1275 * 1276 * @see #WIFI_AP_STATE_CHANGED_ACTION 1277 * @see #getWifiApState() 1278 * 1279 * @hide 1280 */ 1281 @SystemApi 1282 public static final int WIFI_AP_STATE_ENABLING = 12; 1283 /** 1284 * Wi-Fi AP is enabled. 1285 * 1286 * @see #WIFI_AP_STATE_CHANGED_ACTION 1287 * @see #getWifiApState() 1288 * 1289 * @hide 1290 */ 1291 @SystemApi 1292 public static final int WIFI_AP_STATE_ENABLED = 13; 1293 /** 1294 * Wi-Fi AP is in a failed state. This state will occur when an error occurs during 1295 * enabling or disabling 1296 * 1297 * @see #WIFI_AP_STATE_CHANGED_ACTION 1298 * @see #getWifiApState() 1299 * 1300 * @hide 1301 */ 1302 @SystemApi 1303 public static final int WIFI_AP_STATE_FAILED = 14; 1304 1305 /** @hide */ 1306 @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = { 1307 SAP_START_FAILURE_GENERAL, 1308 SAP_START_FAILURE_NO_CHANNEL, 1309 SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION, 1310 SAP_START_FAILURE_USER_REJECTED, 1311 }) 1312 @Retention(RetentionPolicy.SOURCE) 1313 public @interface SapStartFailure {} 1314 1315 /** 1316 * All other reasons for AP start failure besides {@link #SAP_START_FAILURE_NO_CHANNEL}, 1317 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}, and 1318 * {@link #SAP_START_FAILURE_USER_REJECTED}. 1319 * 1320 * @hide 1321 */ 1322 @SystemApi 1323 public static final int SAP_START_FAILURE_GENERAL= 0; 1324 1325 /** 1326 * If Wi-Fi AP start failed, this reason code means that no legal channel exists on user 1327 * selected band due to regulatory constraints. 1328 * 1329 * @hide 1330 */ 1331 @SystemApi 1332 public static final int SAP_START_FAILURE_NO_CHANNEL = 1; 1333 1334 /** 1335 * If Wi-Fi AP start failed, this reason code means that the specified configuration 1336 * is not supported by the current HAL version. 1337 * 1338 * @hide 1339 */ 1340 @SystemApi 1341 public static final int SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION = 2; 1342 1343 /** 1344 * If Wi-Fi AP start failed, this reason code means that the user was asked for confirmation to 1345 * create the AP and the user declined. 1346 * 1347 * @hide 1348 */ 1349 @SystemApi 1350 public static final int SAP_START_FAILURE_USER_REJECTED = 3; 1351 1352 /** @hide */ 1353 @IntDef(flag = false, prefix = { "SAP_CLIENT_BLOCKED_REASON_" }, value = { 1354 SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER, 1355 SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS, 1356 }) 1357 @Retention(RetentionPolicy.SOURCE) 1358 public @interface SapClientBlockedReason {} 1359 1360 /** 1361 * If Soft Ap client is blocked, this reason code means that client doesn't exist in the 1362 * specified configuration {@link SoftApConfiguration.Builder#setBlockedClientList(List)} 1363 * and {@link SoftApConfiguration.Builder#setAllowedClientList(List)} 1364 * and the {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)} 1365 * is configured as well. 1366 * @hide 1367 */ 1368 @SystemApi 1369 public static final int SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER = 0; 1370 1371 /** 1372 * If Soft Ap client is blocked, this reason code means that no more clients can be 1373 * associated to this AP since it reached maximum capacity. The maximum capacity is 1374 * the minimum of {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} and 1375 * {@link SoftApCapability#getMaxSupportedClients} which get from 1376 * {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)}. 1377 * 1378 * @hide 1379 */ 1380 @SystemApi 1381 public static final int SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS = 1; 1382 1383 /** 1384 * Client disconnected for unspecified reason. This could for example be because the AP is being 1385 * shut down. 1386 * @hide 1387 */ 1388 public static final int SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED = 2; 1389 1390 /** @hide */ 1391 @Retention(RetentionPolicy.SOURCE) 1392 @IntDef(prefix = {"IFACE_IP_MODE_"}, value = { 1393 IFACE_IP_MODE_UNSPECIFIED, 1394 IFACE_IP_MODE_CONFIGURATION_ERROR, 1395 IFACE_IP_MODE_TETHERED, 1396 IFACE_IP_MODE_LOCAL_ONLY}) 1397 public @interface IfaceIpMode {} 1398 1399 /** 1400 * Interface IP mode unspecified. 1401 * 1402 * @see #updateInterfaceIpState(String, int) 1403 * 1404 * @hide 1405 */ 1406 @SystemApi 1407 public static final int IFACE_IP_MODE_UNSPECIFIED = -1; 1408 1409 /** 1410 * Interface IP mode for configuration error. 1411 * 1412 * @see #updateInterfaceIpState(String, int) 1413 * 1414 * @hide 1415 */ 1416 @SystemApi 1417 public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; 1418 1419 /** 1420 * Interface IP mode for tethering. 1421 * 1422 * @see #updateInterfaceIpState(String, int) 1423 * 1424 * @hide 1425 */ 1426 @SystemApi 1427 public static final int IFACE_IP_MODE_TETHERED = 1; 1428 1429 /** 1430 * Interface IP mode for Local Only Hotspot. 1431 * 1432 * @see #updateInterfaceIpState(String, int) 1433 * 1434 * @hide 1435 */ 1436 @SystemApi 1437 public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; 1438 1439 /** 1440 * Broadcast intent action indicating that the wifi network settings 1441 * had been reset. 1442 * 1443 * Note: This intent is sent as a directed broadcast to each manifest registered receiver. 1444 * Intent will not be received by dynamically registered receivers. 1445 * @hide 1446 */ 1447 @SystemApi 1448 @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) 1449 public static final String ACTION_NETWORK_SETTINGS_RESET = 1450 "android.net.wifi.action.NETWORK_SETTINGS_RESET"; 1451 1452 /** 1453 * Broadcast intent action indicating that the wifi network profiles provisioned 1454 * may need refresh. 1455 * 1456 * Note: This intent is sent as a directed broadcast to each manifest registered receiver; 1457 * And restricted to those apps which have the NETWORK_CARRIER_PROVISIONING permission. 1458 * Intent will not be received by dynamically registered receivers. 1459 * @hide 1460 */ 1461 @SystemApi 1462 @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) 1463 public static final String ACTION_REFRESH_USER_PROVISIONING = 1464 "android.net.wifi.action.REFRESH_USER_PROVISIONING"; 1465 1466 /** 1467 * Broadcast intent action indicating that a connection to the supplicant has 1468 * been established (and it is now possible 1469 * to perform Wi-Fi operations) or the connection to the supplicant has been 1470 * lost. One extra provides the connection state as a boolean, where {@code true} 1471 * means CONNECTED. 1472 * @deprecated This is no longer supported. 1473 * @see #EXTRA_SUPPLICANT_CONNECTED 1474 */ 1475 @Deprecated 1476 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1477 public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = 1478 "android.net.wifi.supplicant.CONNECTION_CHANGE"; 1479 /** 1480 * The lookup key for a boolean that indicates whether a connection to 1481 * the supplicant daemon has been gained or lost. {@code true} means 1482 * a connection now exists. 1483 * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. 1484 * @deprecated This is no longer supported. 1485 */ 1486 @Deprecated 1487 public static final String EXTRA_SUPPLICANT_CONNECTED = "connected"; 1488 /** 1489 * Broadcast intent action indicating that the state of Wi-Fi connectivity 1490 * has changed. An extra provides the new state 1491 * in the form of a {@link android.net.NetworkInfo} object. No network-related 1492 * permissions are required to subscribe to this broadcast. 1493 * 1494 * <p class="note">This broadcast is not delivered to manifest receivers in 1495 * applications that target API version 26 or later. 1496 * @see #EXTRA_NETWORK_INFO 1497 */ 1498 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1499 public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"; 1500 /** 1501 * The lookup key for a {@link android.net.NetworkInfo} object associated with the 1502 * Wi-Fi network. Retrieve with 1503 * {@link android.content.Intent#getParcelableExtra(String)}. 1504 */ 1505 public static final String EXTRA_NETWORK_INFO = "networkInfo"; 1506 /** 1507 * The lookup key for a String giving the BSSID of the access point to which 1508 * we are connected. No longer used. 1509 */ 1510 @Deprecated 1511 public static final String EXTRA_BSSID = "bssid"; 1512 /** 1513 * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the 1514 * information about the access point to which we are connected. 1515 * No longer used. 1516 */ 1517 @Deprecated 1518 public static final String EXTRA_WIFI_INFO = "wifiInfo"; 1519 /** 1520 * Broadcast intent action indicating that the state of establishing a connection to 1521 * an access point has changed.One extra provides the new 1522 * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and 1523 * is not generally the most useful thing to look at if you are just interested in 1524 * the overall state of connectivity. 1525 * @see #EXTRA_NEW_STATE 1526 * @see #EXTRA_SUPPLICANT_ERROR 1527 * @deprecated This is no longer supported. 1528 */ 1529 @Deprecated 1530 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1531 public static final String SUPPLICANT_STATE_CHANGED_ACTION = 1532 "android.net.wifi.supplicant.STATE_CHANGE"; 1533 /** 1534 * The lookup key for a {@link SupplicantState} describing the new state 1535 * Retrieve with 1536 * {@link android.content.Intent#getParcelableExtra(String)}. 1537 * @deprecated This is no longer supported. 1538 */ 1539 @Deprecated 1540 public static final String EXTRA_NEW_STATE = "newState"; 1541 1542 /** 1543 * The lookup key for a {@link SupplicantState} describing the supplicant 1544 * error code if any 1545 * Retrieve with 1546 * {@link android.content.Intent#getIntExtra(String, int)}. 1547 * @see #ERROR_AUTHENTICATING 1548 * @deprecated This is no longer supported. 1549 */ 1550 @Deprecated 1551 public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; 1552 1553 /** 1554 * The lookup key for a {@link SupplicantState} describing the supplicant 1555 * error reason if any 1556 * Retrieve with 1557 * {@link android.content.Intent#getIntExtra(String, int)}. 1558 * @see #ERROR_AUTH_FAILURE_#REASON_CODE 1559 * @deprecated This is no longer supported. 1560 * @hide 1561 */ 1562 @Deprecated 1563 public static final String EXTRA_SUPPLICANT_ERROR_REASON = "supplicantErrorReason"; 1564 1565 /** 1566 * Broadcast intent action indicating that the configured networks changed. 1567 * This can be as a result of adding/updating/deleting a network. 1568 * <br /> 1569 * {@link #EXTRA_CHANGE_REASON} contains whether the configuration was added/changed/removed. 1570 * {@link #EXTRA_WIFI_CONFIGURATION} is never set beginning in 1571 * {@link android.os.Build.VERSION_CODES#R}. 1572 * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set for backwards compatibility reasons, but 1573 * its value is always true beginning in {@link android.os.Build.VERSION_CODES#R}, even if only 1574 * a single network changed. 1575 * <br /> 1576 * The {@link android.Manifest.permission#ACCESS_WIFI_STATE ACCESS_WIFI_STATE} permission is 1577 * required to receive this broadcast. 1578 * 1579 * @hide 1580 */ 1581 @SystemApi 1582 public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = 1583 "android.net.wifi.CONFIGURED_NETWORKS_CHANGE"; 1584 /** 1585 * The lookup key for a {@link android.net.wifi.WifiConfiguration} object representing 1586 * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION} 1587 * broadcast is sent. 1588 * @deprecated This extra is never set beginning in {@link android.os.Build.VERSION_CODES#R}, 1589 * regardless of the target SDK version. Use {@link #getConfiguredNetworks} to get the full list 1590 * of configured networks. 1591 * @hide 1592 */ 1593 @Deprecated 1594 @SystemApi 1595 public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; 1596 /** 1597 * Multiple network configurations have changed. 1598 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 1599 * @deprecated This extra's value is always true beginning in 1600 * {@link android.os.Build.VERSION_CODES#R}, regardless of the target SDK version. 1601 * @hide 1602 */ 1603 @Deprecated 1604 @SystemApi 1605 public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges"; 1606 /** 1607 * The lookup key for an integer indicating the reason a Wi-Fi network configuration 1608 * has changed. One of {@link #CHANGE_REASON_ADDED}, {@link #CHANGE_REASON_REMOVED}, 1609 * {@link #CHANGE_REASON_CONFIG_CHANGE}. 1610 * 1611 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 1612 * @hide 1613 */ 1614 @SystemApi 1615 public static final String EXTRA_CHANGE_REASON = "changeReason"; 1616 /** 1617 * The configuration is new and was added. 1618 * @hide 1619 */ 1620 @SystemApi 1621 public static final int CHANGE_REASON_ADDED = 0; 1622 /** 1623 * The configuration was removed and is no longer present in the system's list of 1624 * configured networks. 1625 * @hide 1626 */ 1627 @SystemApi 1628 public static final int CHANGE_REASON_REMOVED = 1; 1629 /** 1630 * The configuration has changed as a result of explicit action or because the system 1631 * took an automated action such as disabling a malfunctioning configuration. 1632 * @hide 1633 */ 1634 @SystemApi 1635 public static final int CHANGE_REASON_CONFIG_CHANGE = 2; 1636 /** 1637 * An access point scan has completed, and results are available. 1638 * Call {@link #getScanResults()} to obtain the results. 1639 * The broadcast intent may contain an extra field with the key {@link #EXTRA_RESULTS_UPDATED} 1640 * and a {@code boolean} value indicating if the scan was successful. 1641 */ 1642 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1643 public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; 1644 1645 /** 1646 * Lookup key for a {@code boolean} extra in intent {@link #SCAN_RESULTS_AVAILABLE_ACTION} 1647 * representing if the scan was successful or not. 1648 * Scans may fail for multiple reasons, these may include: 1649 * <ol> 1650 * <li>An app requested too many scans in a certain period of time. 1651 * This may lead to additional scan request rejections via "scan throttling" for both 1652 * foreground and background apps. 1653 * Note: Apps holding android.Manifest.permission.NETWORK_SETTINGS permission are 1654 * exempted from scan throttling. 1655 * </li> 1656 * <li>The device is idle and scanning is disabled.</li> 1657 * <li>Wifi hardware reported a scan failure.</li> 1658 * </ol> 1659 * @return true scan was successful, results are updated 1660 * @return false scan was not successful, results haven't been updated since previous scan 1661 */ 1662 public static final String EXTRA_RESULTS_UPDATED = "resultsUpdated"; 1663 1664 /** 1665 * A batch of access point scans has been completed and the results areavailable. 1666 * Call {@link #getBatchedScanResults()} to obtain the results. 1667 * @deprecated This API is nolonger supported. 1668 * Use {@link WifiScanner} API 1669 * @hide 1670 */ 1671 @Deprecated 1672 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1673 public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION = 1674 "android.net.wifi.BATCHED_RESULTS"; 1675 1676 /** 1677 * The RSSI (signal strength) has changed. 1678 * 1679 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 1680 * @see #EXTRA_NEW_RSSI 1681 */ 1682 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1683 public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; 1684 /** 1685 * The lookup key for an {@code int} giving the new RSSI in dBm. 1686 */ 1687 public static final String EXTRA_NEW_RSSI = "newRssi"; 1688 1689 /** 1690 * @see #ACTION_LINK_CONFIGURATION_CHANGED 1691 * @hide 1692 */ 1693 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1694 public static final String LINK_CONFIGURATION_CHANGED_ACTION = 1695 "android.net.wifi.LINK_CONFIGURATION_CHANGED"; 1696 1697 /** 1698 * Broadcast intent action indicating that the link configuration changed on wifi. 1699 * <br /> No permissions are required to listen to this broadcast. 1700 * @hide 1701 */ 1702 @SystemApi 1703 public static final String ACTION_LINK_CONFIGURATION_CHANGED = 1704 // should be android.net.wifi.action.LINK_CONFIGURATION_CHANGED, but due to 1705 // @UnsupportedAppUsage leaving it as android.net.wifi.LINK_CONFIGURATION_CHANGED. 1706 LINK_CONFIGURATION_CHANGED_ACTION; 1707 1708 /** 1709 * The lookup key for a {@link android.net.LinkProperties} object associated with the 1710 * Wi-Fi network. 1711 * Included in the {@link #ACTION_LINK_CONFIGURATION_CHANGED} broadcast. 1712 * 1713 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 1714 * 1715 * @deprecated this extra is no longer populated. 1716 * 1717 * @hide 1718 */ 1719 @Deprecated 1720 @SystemApi 1721 public static final String EXTRA_LINK_PROPERTIES = "android.net.wifi.extra.LINK_PROPERTIES"; 1722 1723 /** 1724 * The lookup key for a {@link android.net.NetworkCapabilities} object associated with the 1725 * Wi-Fi network. Retrieve with 1726 * {@link android.content.Intent#getParcelableExtra(String)}. 1727 * @hide 1728 */ 1729 public static final String EXTRA_NETWORK_CAPABILITIES = "networkCapabilities"; 1730 1731 /** 1732 * The network IDs of the configured networks could have changed. 1733 */ 1734 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1735 public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; 1736 1737 /** 1738 * Activity Action: Show a system activity that allows the user to enable 1739 * scans to be available even with Wi-Fi turned off. 1740 * 1741 * <p>Notification of the result of this activity is posted using the 1742 * {@link android.app.Activity#onActivityResult} callback. The 1743 * <code>resultCode</code> 1744 * will be {@link android.app.Activity#RESULT_OK} if scan always mode has 1745 * been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user 1746 * has rejected the request or an error has occurred. 1747 */ 1748 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1749 public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = 1750 "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; 1751 1752 /** 1753 * Activity Action: Pick a Wi-Fi network to connect to. 1754 * <p>Input: Nothing. 1755 * <p>Output: Nothing. 1756 */ 1757 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1758 public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; 1759 1760 /** 1761 * Activity Action: Receiver should show UI to get user approval to enable WiFi. 1762 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 1763 * the name of the app requesting the action. 1764 * <p>Output: Nothing. 1765 * <p>No permissions are required to send this action. 1766 * @hide 1767 */ 1768 @SystemApi 1769 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1770 public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE"; 1771 1772 /** 1773 * Activity Action: Receiver should show UI to get user approval to disable WiFi. 1774 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 1775 * the name of the app requesting the action. 1776 * <p>Output: Nothing. 1777 * <p>No permissions are required to send this action. 1778 * @hide 1779 */ 1780 @SystemApi 1781 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1782 public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; 1783 1784 /** 1785 * Directed broadcast intent action indicating that the device has connected to one of the 1786 * network suggestions provided by the app. This will be sent post connection to a network 1787 * which was created with {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired( 1788 * boolean)} 1789 * flag set. 1790 * <p> 1791 * Note: The broadcast is sent to the app only if it holds 1792 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission. 1793 * 1794 * @see #EXTRA_NETWORK_SUGGESTION 1795 */ 1796 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1797 public static final String ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION = 1798 "android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION"; 1799 /** 1800 * Sent as as a part of {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} that holds 1801 * an instance of {@link WifiNetworkSuggestion} corresponding to the connected network. 1802 */ 1803 public static final String EXTRA_NETWORK_SUGGESTION = 1804 "android.net.wifi.extra.NETWORK_SUGGESTION"; 1805 1806 /** 1807 * Internally used Wi-Fi lock mode representing the case were no locks are held. 1808 * @hide 1809 */ 1810 public static final int WIFI_MODE_NO_LOCKS_HELD = 0; 1811 1812 /** 1813 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 1814 * and will behave normally, i.e., it will attempt to automatically 1815 * establish a connection to a remembered access point that is 1816 * within range, and will do periodic scans if there are remembered 1817 * access points but none are in range. 1818 * 1819 * @deprecated This API is non-functional and will have no impact. 1820 */ 1821 @Deprecated 1822 public static final int WIFI_MODE_FULL = 1; 1823 1824 /** 1825 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 1826 * but the only operation that will be supported is initiation of 1827 * scans, and the subsequent reporting of scan results. No attempts 1828 * will be made to automatically connect to remembered access points, 1829 * nor will periodic scans be automatically performed looking for 1830 * remembered access points. Scans must be explicitly requested by 1831 * an application in this mode. 1832 * 1833 * @deprecated This API is non-functional and will have no impact. 1834 */ 1835 @Deprecated 1836 public static final int WIFI_MODE_SCAN_ONLY = 2; 1837 1838 /** 1839 * In this Wi-Fi lock mode, Wi-Fi will not go to power save. 1840 * This results in operating with low packet latency. 1841 * The lock is only active when the device is connected to an access point. 1842 * The lock is active even when the device screen is off or the acquiring application is 1843 * running in the background. 1844 * This mode will consume more power and hence should be used only 1845 * when there is a need for this tradeoff. 1846 * <p> 1847 * An example use case is when a voice connection needs to be 1848 * kept active even after the device screen goes off. 1849 * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the 1850 * duration of the voice call may improve the call quality. 1851 * <p> 1852 * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_HIGH_PERF} 1853 * lock will have no impact. 1854 * 1855 * @deprecated The {@code WIFI_MODE_FULL_HIGH_PERF} is deprecated and is automatically replaced 1856 * with {@link #WIFI_MODE_FULL_LOW_LATENCY} with all the restrictions documented on that lock. 1857 * I.e. any request to the {@code WIFI_MODE_FULL_HIGH_PERF} will now obtain a 1858 * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock instead. 1859 * Deprecation is due to the impact of {@code WIFI_MODE_FULL_HIGH_PERF} on power dissipation. 1860 * The {@link #WIFI_MODE_FULL_LOW_LATENCY} provides much of the same desired functionality with 1861 * less impact on power dissipation. 1862 */ 1863 @Deprecated 1864 public static final int WIFI_MODE_FULL_HIGH_PERF = 3; 1865 1866 /** 1867 * In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency. 1868 * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock has the following limitations: 1869 * <ol> 1870 * <li>The lock is only active when the device is connected to an access point.</li> 1871 * <li>The lock is only active when the screen is on.</li> 1872 * <li>The lock is only active when the acquiring app is running in the foreground.</li> 1873 * </ol> 1874 * Low latency mode optimizes for reduced packet latency, 1875 * and as a result other performance measures may suffer when there are trade-offs to make: 1876 * <ol> 1877 * <li>Battery life may be reduced.</li> 1878 * <li>Throughput may be reduced.</li> 1879 * <li>Frequency of Wi-Fi scanning may be reduced. This may result in: </li> 1880 * <ul> 1881 * <li>The device may not roam or switch to the AP with highest signal quality.</li> 1882 * <li>Location accuracy may be reduced.</li> 1883 * </ul> 1884 * </ol> 1885 * <p> 1886 * Example use cases are real time gaming or virtual reality applications where 1887 * low latency is a key factor for user experience. 1888 * <p> 1889 * Note: For an app which acquires both {@link #WIFI_MODE_FULL_LOW_LATENCY} and 1890 * {@link #WIFI_MODE_FULL_HIGH_PERF} locks, {@link #WIFI_MODE_FULL_LOW_LATENCY} 1891 * lock will be effective when app is running in foreground and screen is on, 1892 * while the {@link #WIFI_MODE_FULL_HIGH_PERF} lock will take effect otherwise. 1893 */ 1894 public static final int WIFI_MODE_FULL_LOW_LATENCY = 4; 1895 1896 1897 /** Anything worse than or equal to this will show 0 bars. */ 1898 @UnsupportedAppUsage 1899 private static final int MIN_RSSI = -100; 1900 1901 /** Anything better than or equal to this will show the max bars. */ 1902 @UnsupportedAppUsage 1903 private static final int MAX_RSSI = -55; 1904 1905 /** 1906 * Number of RSSI levels used in the framework to initiate {@link #RSSI_CHANGED_ACTION} 1907 * broadcast, where each level corresponds to a range of RSSI values. 1908 * The {@link #RSSI_CHANGED_ACTION} broadcast will only fire if the RSSI 1909 * change is significant enough to change the RSSI signal level. 1910 * @hide 1911 */ 1912 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1913 public static final int RSSI_LEVELS = 5; 1914 1915 //TODO (b/146346676): This needs to be removed, not used in the code. 1916 /** 1917 * Auto settings in the driver. The driver could choose to operate on both 1918 * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band. 1919 * @hide 1920 */ 1921 @UnsupportedAppUsage 1922 public static final int WIFI_FREQUENCY_BAND_AUTO = 0; 1923 1924 /** 1925 * Operation on 5 GHz alone 1926 * @hide 1927 */ 1928 @UnsupportedAppUsage 1929 public static final int WIFI_FREQUENCY_BAND_5GHZ = 1; 1930 1931 /** 1932 * Operation on 2.4 GHz alone 1933 * @hide 1934 */ 1935 @UnsupportedAppUsage 1936 public static final int WIFI_FREQUENCY_BAND_2GHZ = 2; 1937 1938 /** @hide */ 1939 public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false; 1940 1941 /** 1942 * Maximum number of active locks we allow. 1943 * This limit was added to prevent apps from creating a ridiculous number 1944 * of locks and crashing the system by overflowing the global ref table. 1945 */ 1946 private static final int MAX_ACTIVE_LOCKS = 50; 1947 1948 /** Indicates an invalid SSID. */ 1949 public static final String UNKNOWN_SSID = "<unknown ssid>"; 1950 1951 /** @hide */ 1952 public static final MacAddress ALL_ZEROS_MAC_ADDRESS = 1953 MacAddress.fromString("00:00:00:00:00:00"); 1954 1955 /** @hide */ 1956 @IntDef(flag = false, prefix = { "WIFI_MULTI_INTERNET_MODE_" }, value = { 1957 WIFI_MULTI_INTERNET_MODE_DISABLED, 1958 WIFI_MULTI_INTERNET_MODE_DBS_AP, 1959 WIFI_MULTI_INTERNET_MODE_MULTI_AP, 1960 }) 1961 @Retention(RetentionPolicy.SOURCE) 1962 public @interface WifiMultiInternetMode {} 1963 1964 /** 1965 * Wi-Fi simultaneous connection to multiple internet-providing Wi-Fi networks (APs) is 1966 * disabled. 1967 * 1968 * @see #getStaConcurrencyForMultiInternetMode() 1969 * 1970 */ 1971 public static final int WIFI_MULTI_INTERNET_MODE_DISABLED = 0; 1972 /** 1973 * Wi-Fi simultaneous connection to multiple internet-providing Wi-FI networks (APs) is enabled 1974 * and restricted to a single network on different bands (e.g. a DBS AP). 1975 * 1976 * @see #getStaConcurrencyForMultiInternetMode() 1977 * 1978 */ 1979 public static final int WIFI_MULTI_INTERNET_MODE_DBS_AP = 1; 1980 /** 1981 * Wi-Fi simultaneous connection to multiple internet-providing Wi-Fi networks (APs) is enabled. 1982 * The device can connect to any networks/APs - it is just restricted to using different bands 1983 * for individual connections. 1984 * 1985 * @see #getStaConcurrencyForMultiInternetMode() 1986 * 1987 */ 1988 public static final int WIFI_MULTI_INTERNET_MODE_MULTI_AP = 2; 1989 1990 /** 1991 * The bundle key string for the channel frequency in MHz. 1992 * See {@link #getChannelData(Executor, Consumer)} 1993 */ 1994 public static final String CHANNEL_DATA_KEY_FREQUENCY_MHZ = "CHANNEL_DATA_KEY_FREQUENCY_MHZ"; 1995 /** 1996 * The bundle key for the number of APs found on the corresponding channel specified by 1997 * {@link WifiManager#CHANNEL_DATA_KEY_FREQUENCY_MHZ}. 1998 * See {@link #getChannelData(Executor, Consumer)} 1999 */ 2000 public static final String CHANNEL_DATA_KEY_NUM_AP = "CHANNEL_DATA_KEY_NUM_AP"; 2001 2002 /** 2003 * This policy is being tracked by the Wifi service. 2004 * Indicates success for {@link #addQosPolicies(List, Executor, Consumer)}. 2005 * @hide 2006 */ 2007 @SystemApi 2008 public static final int QOS_REQUEST_STATUS_TRACKING = 0; 2009 2010 /** 2011 * A policy with the same policy ID is already being tracked. 2012 * @hide 2013 */ 2014 @SystemApi 2015 public static final int QOS_REQUEST_STATUS_ALREADY_ACTIVE = 1; 2016 2017 /** 2018 * There are insufficient resources to handle this request at this time. 2019 * @hide 2020 */ 2021 @SystemApi 2022 public static final int QOS_REQUEST_STATUS_INSUFFICIENT_RESOURCES = 2; 2023 2024 /** 2025 * The parameters in the policy request are invalid. 2026 * @hide 2027 */ 2028 @SystemApi 2029 public static final int QOS_REQUEST_STATUS_INVALID_PARAMETERS = 3; 2030 2031 /** 2032 * An unspecified failure occurred while processing this request. 2033 * @hide 2034 */ 2035 @SystemApi 2036 public static final int QOS_REQUEST_STATUS_FAILURE_UNKNOWN = 4; 2037 2038 /** @hide */ 2039 @Retention(RetentionPolicy.SOURCE) 2040 @IntDef(prefix = {"QOS_REQUEST_STATUS_"}, value = { 2041 QOS_REQUEST_STATUS_TRACKING, 2042 QOS_REQUEST_STATUS_ALREADY_ACTIVE, 2043 QOS_REQUEST_STATUS_INSUFFICIENT_RESOURCES, 2044 QOS_REQUEST_STATUS_INVALID_PARAMETERS, 2045 QOS_REQUEST_STATUS_FAILURE_UNKNOWN}) 2046 public @interface QosRequestStatus {} 2047 2048 /** 2049 * Maximum number of policies that can be included in a QoS add/remove request. 2050 */ 2051 private static final int MAX_POLICIES_PER_QOS_REQUEST = 16; 2052 2053 /** 2054 * Get the maximum number of policies that can be included in a request to 2055 * {@link #addQosPolicies(List, Executor, Consumer)} or {@link #removeQosPolicies(int[])}. 2056 * @hide 2057 */ 2058 @SystemApi getMaxNumberOfPoliciesPerQosRequest()2059 public static int getMaxNumberOfPoliciesPerQosRequest() { 2060 return MAX_POLICIES_PER_QOS_REQUEST; 2061 } 2062 2063 /* Number of currently active WifiLocks and MulticastLocks */ 2064 @UnsupportedAppUsage 2065 private int mActiveLockCount; 2066 2067 private Context mContext; 2068 @UnsupportedAppUsage 2069 IWifiManager mService; 2070 private final int mTargetSdkVersion; 2071 2072 private Looper mLooper; 2073 private boolean mVerboseLoggingEnabled = false; 2074 2075 private final Object mLock = new Object(); // lock guarding access to the following vars 2076 @GuardedBy("mLock") 2077 private LocalOnlyHotspotCallbackProxy mLOHSCallbackProxy; 2078 @GuardedBy("mLock") 2079 private LocalOnlyHotspotObserverProxy mLOHSObserverProxy; 2080 2081 private static final SparseArray<IOnWifiUsabilityStatsListener> 2082 sOnWifiUsabilityStatsListenerMap = new SparseArray(); 2083 private static final SparseArray<ISuggestionConnectionStatusListener> 2084 sSuggestionConnectionStatusListenerMap = new SparseArray(); 2085 private static final SparseArray<ISuggestionUserApprovalStatusListener> 2086 sSuggestionUserApprovalStatusListenerMap = new SparseArray(); 2087 private static final SparseArray<IWifiVerboseLoggingStatusChangedListener> 2088 sWifiVerboseLoggingStatusChangedListenerMap = new SparseArray(); 2089 private static final SparseArray<INetworkRequestMatchCallback> 2090 sNetworkRequestMatchCallbackMap = new SparseArray(); 2091 private static final SparseArray<ITrafficStateCallback> 2092 sTrafficStateCallbackMap = new SparseArray(); 2093 private static final SparseArray<ISoftApCallback> sSoftApCallbackMap = new SparseArray(); 2094 private static final SparseArray<IOnWifiDriverCountryCodeChangedListener> 2095 sActiveCountryCodeChangedCallbackMap = new SparseArray(); 2096 private static final SparseArray<ISoftApCallback> 2097 sLocalOnlyHotspotSoftApCallbackMap = new SparseArray(); 2098 private static final SparseArray<ILocalOnlyConnectionStatusListener> 2099 sLocalOnlyConnectionStatusListenerMap = new SparseArray(); 2100 private static final SparseArray<IWifiNetworkStateChangedListener> 2101 sOnWifiNetworkStateChangedListenerMap = new SparseArray<>(); 2102 private static final SparseArray<IWifiLowLatencyLockListener> 2103 sWifiLowLatencyLockListenerMap = new SparseArray<>(); 2104 2105 /** 2106 * Multi-link operation (MLO) will allow Wi-Fi devices to operate on multiple links at the same 2107 * time through a single connection, aiming to support applications that require lower latency, 2108 * and higher capacity. Chip vendors have algorithms that run on the chip to use available links 2109 * based on incoming traffic and various inputs. Below is a list of Multi-Link Operation modes 2110 * that applications can suggest to be accommodated in the algorithm. 2111 * 2112 * The default MLO mode is for chip vendors to use algorithms to select the optimum links to 2113 * operate on, without any guidance from the calling app. 2114 * 2115 * @hide 2116 */ 2117 @SystemApi 2118 public static final int MLO_MODE_DEFAULT = 0; 2119 2120 /** 2121 * Low latency mode for Multi-link operation. In this mode, the chip vendor's algorithm 2122 * should select MLO links that will achieve low latency. 2123 * 2124 * @hide 2125 */ 2126 @SystemApi 2127 public static final int MLO_MODE_LOW_LATENCY = 1; 2128 2129 /** 2130 * High throughput mode for Multi-link operation. In this mode, the chip vendor's algorithm 2131 * should select MLO links that will achieve higher throughput. 2132 * 2133 * @hide 2134 */ 2135 @SystemApi 2136 public static final int MLO_MODE_HIGH_THROUGHPUT = 2; 2137 2138 /** 2139 * Low power mode for Multi-link operation. In this mode, the chip vendor's algorithm 2140 * should select MLO links that will achieve low power. 2141 * 2142 * @hide 2143 */ 2144 @SystemApi 2145 public static final int MLO_MODE_LOW_POWER = 3; 2146 2147 /** @hide */ 2148 @Retention(RetentionPolicy.SOURCE) 2149 @IntDef(prefix = {"MLO_MODE_"}, value = { 2150 MLO_MODE_DEFAULT, 2151 MLO_MODE_LOW_LATENCY, 2152 MLO_MODE_HIGH_THROUGHPUT, 2153 MLO_MODE_LOW_POWER}) 2154 public @interface MloMode { 2155 } 2156 2157 /** 2158 * Roaming is disabled. 2159 */ 2160 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 2161 public static final int ROAMING_MODE_NONE = 0; 2162 2163 /** 2164 * Chipset has roaming trigger capability based on the score calculated 2165 * using multiple parameters. If device is configured to this mode then it 2166 * will be using chipset's normal (default) roaming. 2167 */ 2168 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 2169 public static final int ROAMING_MODE_NORMAL = 1; 2170 2171 /** 2172 * Allows the device to roam more quickly than the normal roaming mode. 2173 * Used in cases such as where APs are installed in a high density. 2174 */ 2175 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 2176 public static final int ROAMING_MODE_AGGRESSIVE = 2; 2177 2178 /** 2179 * @hide 2180 */ 2181 @Retention(RetentionPolicy.SOURCE) 2182 @IntDef(prefix = {"ROAMING_MODE_"}, value = { 2183 ROAMING_MODE_NONE, 2184 ROAMING_MODE_NORMAL, 2185 ROAMING_MODE_AGGRESSIVE}) 2186 public @interface RoamingMode { 2187 } 2188 2189 /** 2190 * Create a new WifiManager instance. 2191 * Applications will almost always want to use 2192 * {@link android.content.Context#getSystemService Context.getSystemService} to retrieve 2193 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. 2194 * 2195 * @param context the application context 2196 * @param service the Binder interface 2197 * @param looper the Looper used to deliver callbacks 2198 * @hide - hide this because it takes in a parameter of type IWifiManager, which 2199 * is a system private class. 2200 */ WifiManager(@onNull Context context, @NonNull IWifiManager service, @NonNull Looper looper)2201 public WifiManager(@NonNull Context context, @NonNull IWifiManager service, 2202 @NonNull Looper looper) { 2203 mContext = context; 2204 mService = service; 2205 mLooper = looper; 2206 mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; 2207 updateVerboseLoggingEnabledFromService(); 2208 } 2209 2210 /** 2211 * Return a list of all the networks configured for the current foreground 2212 * user. 2213 * 2214 * Not all fields of WifiConfiguration are returned. Only the following 2215 * fields are filled in: 2216 * <ul> 2217 * <li>networkId</li> 2218 * <li>SSID</li> 2219 * <li>BSSID</li> 2220 * <li>priority</li> 2221 * <li>allowedProtocols</li> 2222 * <li>allowedKeyManagement</li> 2223 * <li>allowedAuthAlgorithms</li> 2224 * <li>allowedPairwiseCiphers</li> 2225 * <li>allowedGroupCiphers</li> 2226 * <li>status</li> 2227 * </ul> 2228 * @return a list of network configurations in the form of a list 2229 * of {@link WifiConfiguration} objects. 2230 * 2231 * @deprecated 2232 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2233 * mechanism to trigger connection to a Wi-Fi network. 2234 * b) See {@link #addNetworkSuggestions(List)}, 2235 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2236 * when auto-connecting to wifi. 2237 * <b>Compatibility Note:</b> For applications targeting 2238 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return an 2239 * empty list. 2240 * <p> 2241 * Deprecation Exemptions: 2242 * <ul> 2243 * <li>Device Owner (DO), Profile Owner (PO) and system apps will have access to the full list. 2244 * <li>Callers with Carrier privilege will receive a restricted list only containing 2245 * configurations which they created. 2246 * </ul> 2247 */ 2248 @Deprecated 2249 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) getConfiguredNetworks()2250 public List<WifiConfiguration> getConfiguredNetworks() { 2251 try { 2252 ParceledListSlice<WifiConfiguration> parceledList = 2253 mService.getConfiguredNetworks(mContext.getOpPackageName(), 2254 mContext.getAttributionTag(), false); 2255 if (parceledList == null) { 2256 return Collections.emptyList(); 2257 } 2258 return parceledList.getList(); 2259 } catch (RemoteException e) { 2260 throw e.rethrowFromSystemServer(); 2261 } 2262 } 2263 2264 /** 2265 * Return a list of all the networks previously configured by the calling app. Can 2266 * be called by Device Owner (DO), Profile Owner (PO), Callers with Carrier privilege and 2267 * system apps. 2268 * 2269 * @return a list of network configurations in the form of a list 2270 * of {@link WifiConfiguration} objects. 2271 * @throws SecurityException if the caller is not allowed to call this API 2272 */ 2273 @RequiresPermission(ACCESS_WIFI_STATE) 2274 @NonNull getCallerConfiguredNetworks()2275 public List<WifiConfiguration> getCallerConfiguredNetworks() { 2276 try { 2277 ParceledListSlice<WifiConfiguration> parceledList = 2278 mService.getConfiguredNetworks(mContext.getOpPackageName(), 2279 mContext.getAttributionTag(), true); 2280 if (parceledList == null) { 2281 return Collections.emptyList(); 2282 } 2283 return parceledList.getList(); 2284 } catch (RemoteException e) { 2285 throw e.rethrowFromSystemServer(); 2286 } 2287 } 2288 2289 2290 /** 2291 * Applications targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later need to have 2292 * the following permissions: {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}, 2293 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and 2294 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. 2295 * Applications targeting {@link Build.VERSION_CODES#S} or prior SDK levels need to have the 2296 * following permissions: {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, 2297 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 2298 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. 2299 * <p> See {@link #getPrivilegedConnectedNetwork()} to get the WifiConfiguration for only the 2300 * connected network that's providing internet by default. 2301 * 2302 * @hide 2303 **/ 2304 @SystemApi 2305 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, NEARBY_WIFI_DEVICES, ACCESS_WIFI_STATE, 2306 READ_WIFI_CREDENTIAL}, 2307 conditional = true) getPrivilegedConfiguredNetworks()2308 public List<WifiConfiguration> getPrivilegedConfiguredNetworks() { 2309 try { 2310 Bundle extras = new Bundle(); 2311 if (SdkLevel.isAtLeastS()) { 2312 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 2313 mContext.getAttributionSource()); 2314 } 2315 ParceledListSlice<WifiConfiguration> parceledList = 2316 mService.getPrivilegedConfiguredNetworks(mContext.getOpPackageName(), 2317 mContext.getAttributionTag(), extras); 2318 if (parceledList == null) { 2319 return Collections.emptyList(); 2320 } 2321 return parceledList.getList(); 2322 } catch (RemoteException e) { 2323 throw e.rethrowFromSystemServer(); 2324 } 2325 } 2326 2327 /** 2328 * Gets the {@link WifiConfiguration} with credentials of the connected wifi network 2329 * that's providing internet by default. 2330 * <p> 2331 * On {@link android.os.Build.VERSION_CODES#TIRAMISU} or later SDKs, the caller need to have 2332 * the following permissions: {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with 2333 * android:usesPermissionFlags="neverForLocation", 2334 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and 2335 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. If the app does not have 2336 * android:usesPermissionFlags="neverForLocation", then it must also have 2337 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}. 2338 * <p> 2339 * On {@link Build.VERSION_CODES#S} or prior SDKs, the caller need to have the 2340 * following permissions: {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, 2341 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 2342 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. 2343 * 2344 * @return The WifiConfiguration representation of the connected wifi network providing 2345 * internet, or null if wifi is not connected. 2346 * 2347 * @throws SecurityException if caller does not have the required permissions 2348 * @hide 2349 **/ 2350 @SystemApi 2351 @RequiresPermission(allOf = {NEARBY_WIFI_DEVICES, ACCESS_WIFI_STATE, READ_WIFI_CREDENTIAL}, 2352 conditional = true) 2353 @Nullable getPrivilegedConnectedNetwork()2354 public WifiConfiguration getPrivilegedConnectedNetwork() { 2355 try { 2356 Bundle extras = new Bundle(); 2357 if (SdkLevel.isAtLeastS()) { 2358 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 2359 mContext.getAttributionSource()); 2360 } 2361 return mService.getPrivilegedConnectedNetwork(mContext.getOpPackageName(), 2362 mContext.getAttributionTag(), extras); 2363 } catch (RemoteException e) { 2364 throw e.rethrowFromSystemServer(); 2365 } 2366 } 2367 2368 /** 2369 * Returns a list of all matching WifiConfigurations of PasspointConfiguration for a given list 2370 * of ScanResult. 2371 * 2372 * An empty list will be returned when no PasspointConfiguration are installed or if no 2373 * PasspointConfiguration match the ScanResult. 2374 * 2375 * @param scanResults a list of scanResult that represents the BSSID 2376 * @return List that consists of {@link WifiConfiguration} and corresponding scanResults per 2377 * network type({@link #PASSPOINT_HOME_NETWORK} and {@link #PASSPOINT_ROAMING_NETWORK}). 2378 * @hide 2379 */ 2380 @SystemApi 2381 @RequiresPermission(anyOf = { 2382 android.Manifest.permission.NETWORK_SETTINGS, 2383 android.Manifest.permission.NETWORK_SETUP_WIZARD 2384 }) 2385 @NonNull getAllMatchingWifiConfigs( @onNull List<ScanResult> scanResults)2386 public List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> getAllMatchingWifiConfigs( 2387 @NonNull List<ScanResult> scanResults) { 2388 List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>(); 2389 try { 2390 Map<String, Map<Integer, List<ScanResult>>> results = 2391 mService.getAllMatchingPasspointProfilesForScanResults(scanResults); 2392 if (results.isEmpty()) { 2393 return configs; 2394 } 2395 List<WifiConfiguration> wifiConfigurations = 2396 mService.getWifiConfigsForPasspointProfiles( 2397 new ArrayList<>(results.keySet())); 2398 for (WifiConfiguration configuration : wifiConfigurations) { 2399 Map<Integer, List<ScanResult>> scanResultsPerNetworkType = 2400 results.get(configuration.getProfileKey()); 2401 if (scanResultsPerNetworkType != null) { 2402 configs.add(Pair.create(configuration, scanResultsPerNetworkType)); 2403 } 2404 } 2405 } catch (RemoteException e) { 2406 throw e.rethrowFromSystemServer(); 2407 } 2408 2409 return configs; 2410 } 2411 2412 /** 2413 * To be used with setScreenOnScanSchedule. 2414 * @hide 2415 */ 2416 @SystemApi 2417 public static class ScreenOnScanSchedule { 2418 private final Duration mScanInterval; 2419 private final int mScanType; 2420 2421 /** 2422 * Creates a ScreenOnScanSchedule. 2423 * @param scanInterval Interval between framework-initiated connectivity scans. 2424 * @param scanType One of the {@code WifiScanner.SCAN_TYPE_} values. 2425 */ ScreenOnScanSchedule(@onNull Duration scanInterval, @WifiAnnotations.ScanType int scanType)2426 public ScreenOnScanSchedule(@NonNull Duration scanInterval, 2427 @WifiAnnotations.ScanType int scanType) { 2428 if (scanInterval == null) { 2429 throw new IllegalArgumentException("scanInterval can't be null"); 2430 } 2431 mScanInterval = scanInterval; 2432 mScanType = scanType; 2433 } 2434 2435 /** 2436 * Gets the interval between framework-initiated connectivity scans. 2437 */ getScanInterval()2438 public @NonNull Duration getScanInterval() { 2439 return mScanInterval; 2440 } 2441 2442 /** 2443 * Gets the type of scan to be used. One of the {@code WifiScanner.SCAN_TYPE_} values. 2444 */ getScanType()2445 public @WifiAnnotations.ScanType int getScanType() { 2446 return mScanType; 2447 } 2448 } 2449 2450 /** 2451 * This API allows a privileged app to customize the wifi framework's network selection logic. 2452 * To revert to default behavior, call this API with a {@link WifiNetworkSelectionConfig} 2453 * created from a default {@link WifiNetworkSelectionConfig.Builder}. 2454 * 2455 * Use {@link WifiManager#getNetworkSelectionConfig(Executor, Consumer)} to get the current 2456 * network selection configuration. 2457 * <P> 2458 * @param nsConfig an Object representing the network selection configuration being programmed. 2459 * This should be created with a {@link WifiNetworkSelectionConfig.Builder}. 2460 * 2461 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2462 * @throws IllegalArgumentException if input is invalid. 2463 * @throws SecurityException if the caller does not have permission. 2464 * @hide 2465 */ 2466 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2467 @RequiresPermission(anyOf = { 2468 android.Manifest.permission.NETWORK_SETTINGS, 2469 MANAGE_WIFI_NETWORK_SELECTION 2470 }) 2471 @SystemApi setNetworkSelectionConfig(@onNull WifiNetworkSelectionConfig nsConfig)2472 public void setNetworkSelectionConfig(@NonNull WifiNetworkSelectionConfig nsConfig) { 2473 try { 2474 if (nsConfig == null) { 2475 throw new IllegalArgumentException("nsConfig can not be null"); 2476 } 2477 mService.setNetworkSelectionConfig(nsConfig); 2478 } catch (RemoteException e) { 2479 throw e.rethrowFromSystemServer(); 2480 } 2481 } 2482 2483 /** 2484 * This API allows a privileged app to retrieve the {@link WifiNetworkSelectionConfig} 2485 * currently being used by the network selector. 2486 * 2487 * Use {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)} to set a 2488 * new network selection configuration. 2489 * <P> 2490 * @param executor The executor on which callback will be invoked. 2491 * @param resultsCallback An asynchronous callback that will return 2492 * {@link WifiNetworkSelectionConfig} 2493 * 2494 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2495 * @throws SecurityException if the caller does not have permission. 2496 * @throws NullPointerException if the caller provided invalid inputs. 2497 * @hide 2498 */ 2499 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2500 @RequiresPermission(anyOf = { 2501 android.Manifest.permission.NETWORK_SETTINGS, 2502 MANAGE_WIFI_NETWORK_SELECTION 2503 }) 2504 @SystemApi getNetworkSelectionConfig(@onNull @allbackExecutor Executor executor, @NonNull Consumer<WifiNetworkSelectionConfig> resultsCallback)2505 public void getNetworkSelectionConfig(@NonNull @CallbackExecutor Executor executor, 2506 @NonNull Consumer<WifiNetworkSelectionConfig> resultsCallback) { 2507 Objects.requireNonNull(executor, "executor cannot be null"); 2508 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 2509 try { 2510 mService.getNetworkSelectionConfig( 2511 new IWifiNetworkSelectionConfigListener.Stub() { 2512 @Override 2513 public void onResult(WifiNetworkSelectionConfig value) { 2514 Binder.clearCallingIdentity(); 2515 executor.execute(() -> { 2516 resultsCallback.accept(value); 2517 }); 2518 } 2519 }); 2520 } catch (RemoteException e) { 2521 throw e.rethrowFromSystemServer(); 2522 } 2523 } 2524 2525 /** 2526 * Allows a privileged app to enable/disable whether a confirmation dialog should be displayed 2527 * when third-party apps attempt to turn on WiFi. 2528 * 2529 * Use {@link #isThirdPartyAppEnablingWifiConfirmationDialogEnabled()} to get the 2530 * currently configured value. 2531 * 2532 * Note: Only affects behavior for apps with targetSDK < Q, since third party apps are not 2533 * allowed to enable wifi on targetSDK >= Q. 2534 * 2535 * This overrides the overlay value |config_showConfirmationDialogForThirdPartyAppsEnablingWifi| 2536 * <P> 2537 * @param enable true to enable the confirmation dialog, false otherwise 2538 * 2539 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2540 * @throws SecurityException if the caller does not have permission. 2541 * @hide 2542 */ 2543 @RequiresPermission(anyOf = { 2544 android.Manifest.permission.NETWORK_SETTINGS, 2545 android.Manifest.permission.NETWORK_SETUP_WIZARD 2546 }) 2547 @SystemApi setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable)2548 public void setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable) { 2549 try { 2550 mService.setThirdPartyAppEnablingWifiConfirmationDialogEnabled(enable); 2551 } catch (RemoteException e) { 2552 throw e.rethrowFromSystemServer(); 2553 } 2554 } 2555 2556 /** 2557 * Check whether the wifi configuration indicates that a confirmation dialog should be displayed 2558 * when third-party apps attempt to turn on WiFi. 2559 * 2560 * Use {@link #setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} to set this 2561 * value. 2562 * 2563 * Note: This setting only affects behavior for apps with targetSDK < Q, since third party apps 2564 * are not allowed to enable wifi on targetSDK >= Q. 2565 * 2566 * <P> 2567 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2568 * @throws SecurityException if the caller does not have permission. 2569 * @return true if dialog should be displayed, false otherwise. 2570 * @hide 2571 */ 2572 @RequiresPermission(anyOf = { 2573 android.Manifest.permission.NETWORK_SETTINGS, 2574 android.Manifest.permission.NETWORK_SETUP_WIZARD 2575 }) 2576 @SystemApi isThirdPartyAppEnablingWifiConfirmationDialogEnabled()2577 public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled() { 2578 try { 2579 return mService.isThirdPartyAppEnablingWifiConfirmationDialogEnabled(); 2580 } catch (RemoteException e) { 2581 throw e.rethrowFromSystemServer(); 2582 } 2583 } 2584 2585 /** 2586 * Allows a privileged app to customize the screen-on scan behavior. When a non-null schedule 2587 * is set via this API, it will always get used instead of the scan schedules defined in the 2588 * overlay. When a null schedule is set via this API, the wifi subsystem will go back to using 2589 * the scan schedules defined in the overlay. Also note, the scan schedule will be truncated 2590 * (rounded down) to the nearest whole second. 2591 * <p> 2592 * Example usage: 2593 * The following call specifies that first scheduled scan should be in 20 seconds using 2594 * {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}, and all 2595 * scheduled scans later should happen every 40 seconds using 2596 * {@link WifiScanner#SCAN_TYPE_LOW_POWER}. 2597 * <pre> 2598 * List<ScreenOnScanSchedule> schedule = new ArrayList<>(); 2599 * schedule.add(new ScreenOnScanSchedule(Duration.ofSeconds(20), 2600 * WifiScanner.SCAN_TYPE_HIGH_ACCURACY)); 2601 * schedule.add(new ScreenOnScanSchedule(Duration.ofSeconds(40), 2602 * WifiScanner.SCAN_TYPE_LOW_POWER)); 2603 * wifiManager.setScreenOnScanSchedule(schedule); 2604 * </pre> 2605 * @param screenOnScanSchedule defines the screen-on scan schedule and the corresponding 2606 * scan type. Set to null to clear any previously set value. 2607 * 2608 * @throws IllegalStateException if input is invalid 2609 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2610 * @throws SecurityException if the caller does not have permission. 2611 * @hide 2612 */ 2613 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2614 @RequiresPermission(anyOf = { 2615 android.Manifest.permission.NETWORK_SETTINGS, 2616 MANAGE_WIFI_NETWORK_SELECTION 2617 }) 2618 @SystemApi setScreenOnScanSchedule(@ullable List<ScreenOnScanSchedule> screenOnScanSchedule)2619 public void setScreenOnScanSchedule(@Nullable List<ScreenOnScanSchedule> screenOnScanSchedule) { 2620 try { 2621 if (screenOnScanSchedule == null) { 2622 mService.setScreenOnScanSchedule(null, null); 2623 return; 2624 } 2625 if (screenOnScanSchedule.isEmpty()) { 2626 throw new IllegalArgumentException("The input should either be null or a non-empty" 2627 + " list"); 2628 } 2629 int[] scanSchedule = new int[screenOnScanSchedule.size()]; 2630 int[] scanType = new int[screenOnScanSchedule.size()]; 2631 for (int i = 0; i < screenOnScanSchedule.size(); i++) { 2632 scanSchedule[i] = (int) screenOnScanSchedule.get(i).getScanInterval().toSeconds(); 2633 scanType[i] = screenOnScanSchedule.get(i).getScanType(); 2634 } 2635 mService.setScreenOnScanSchedule(scanSchedule, scanType); 2636 } catch (RemoteException e) { 2637 throw e.rethrowFromSystemServer(); 2638 } 2639 } 2640 2641 /** 2642 * The Wi-Fi framework may trigger connectivity scans in response to the screen turning on for 2643 * network selection purposes. This API allows a privileged app to set a delay to the next 2644 * connectivity scan triggered by the Wi-Fi framework in response to the next screen-on event. 2645 * This gives a window for the privileged app to issue their own custom scans to influence Wi-Fi 2646 * network selection. The expected usage is the privileged app monitor for the screen turning 2647 * off, and then call this API if it believes delaying the next screen-on connectivity scan is 2648 * needed. 2649 * <p> 2650 * Note that this API will only delay screen-on connectivity scans once. This API will need to 2651 * be called again if further screen-on scan delays are needed after it resolves. 2652 * @param delayMs defines the time in milliseconds to delay the next screen-on connectivity 2653 * scan. Setting this to 0 will remove the delay. 2654 * 2655 * @throws IllegalStateException if input is invalid 2656 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2657 * @throws SecurityException if the caller does not have permission. 2658 * @hide 2659 */ 2660 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2661 @RequiresPermission(anyOf = { 2662 android.Manifest.permission.NETWORK_SETTINGS, 2663 MANAGE_WIFI_NETWORK_SELECTION 2664 }) 2665 @SystemApi setOneShotScreenOnConnectivityScanDelayMillis(@ntRangefrom = 0) int delayMs)2666 public void setOneShotScreenOnConnectivityScanDelayMillis(@IntRange(from = 0) int delayMs) { 2667 try { 2668 mService.setOneShotScreenOnConnectivityScanDelayMillis(delayMs); 2669 } catch (RemoteException e) { 2670 throw e.rethrowFromSystemServer(); 2671 } 2672 } 2673 2674 /** 2675 * Retrieve a list of {@link WifiConfiguration} for available {@link WifiNetworkSuggestion} 2676 * matching the given list of {@link ScanResult}. 2677 * 2678 * An available {@link WifiNetworkSuggestion} must satisfy: 2679 * <ul> 2680 * <li> Matching one of the {@link ScanResult} from the given list. 2681 * <li> and {@link WifiNetworkSuggestion.Builder#setIsUserAllowedToManuallyConnect(boolean)} set 2682 * to true. 2683 * </ul> 2684 * 2685 * @param scanResults a list of scanResult. 2686 * @return a list of @link WifiConfiguration} for available {@link WifiNetworkSuggestion} 2687 * @hide 2688 */ 2689 @SystemApi 2690 @RequiresPermission(anyOf = { 2691 android.Manifest.permission.NETWORK_SETTINGS, 2692 android.Manifest.permission.NETWORK_SETUP_WIZARD 2693 }) 2694 @NonNull getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( @onNull List<ScanResult> scanResults)2695 public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( 2696 @NonNull List<ScanResult> scanResults) { 2697 try { 2698 return mService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults); 2699 } catch (RemoteException e) { 2700 throw e.rethrowAsRuntimeException(); 2701 } 2702 } 2703 2704 /** 2705 * Specify a set of SSIDs that will not get disabled internally by the Wi-Fi subsystem when 2706 * connection issues occur. To clear the list, call this API with an empty Set. 2707 * <p> 2708 * {@link #getSsidsAllowlist()} can be used to check the SSIDs that have been set. 2709 * @param ssids - list of WifiSsid that will not get disabled internally 2710 * @throws SecurityException if the calling app is not a Device Owner (DO), Profile Owner (PO), 2711 * or a privileged app that has one of the permissions required by 2712 * this API. 2713 * @throws IllegalArgumentException if the input is null. 2714 * @hide 2715 */ 2716 @SystemApi 2717 @RequiresPermission(anyOf = { 2718 android.Manifest.permission.NETWORK_SETTINGS, 2719 android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional = true) setSsidsAllowlist(@onNull Set<WifiSsid> ssids)2720 public void setSsidsAllowlist(@NonNull Set<WifiSsid> ssids) { 2721 if (ssids == null) { 2722 throw new IllegalArgumentException(TAG + ": ssids can not be null"); 2723 } 2724 try { 2725 mService.setSsidsAllowlist(mContext.getOpPackageName(), new ArrayList<>(ssids)); 2726 } catch (RemoteException e) { 2727 throw e.rethrowFromSystemServer(); 2728 } 2729 } 2730 2731 /** 2732 * Get the Set of SSIDs that will not get disabled internally by the Wi-Fi subsystem when 2733 * connection issues occur. 2734 * @throws SecurityException if the calling app is not a Device Owner (DO), Profile Owner (PO), 2735 * or a privileged app that has one of the permissions required by 2736 * this API. 2737 * @hide 2738 */ 2739 @SystemApi 2740 @RequiresPermission(anyOf = { 2741 android.Manifest.permission.NETWORK_SETTINGS, 2742 android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional = true) getSsidsAllowlist()2743 public @NonNull Set<WifiSsid> getSsidsAllowlist() { 2744 try { 2745 return new ArraySet<WifiSsid>( 2746 mService.getSsidsAllowlist(mContext.getOpPackageName())); 2747 } catch (RemoteException e) { 2748 throw e.rethrowFromSystemServer(); 2749 } 2750 } 2751 2752 /** 2753 * Returns a list of unique Hotspot 2.0 OSU (Online Sign-Up) providers associated with a given 2754 * list of ScanResult. 2755 * 2756 * An empty list will be returned if no match is found. 2757 * 2758 * @param scanResults a list of ScanResult 2759 * @return Map that consists {@link OsuProvider} and a list of matching {@link ScanResult} 2760 * @hide 2761 */ 2762 @SystemApi 2763 @RequiresPermission(anyOf = { 2764 android.Manifest.permission.NETWORK_SETTINGS, 2765 android.Manifest.permission.NETWORK_SETUP_WIZARD 2766 }) 2767 @NonNull getMatchingOsuProviders( @ullable List<ScanResult> scanResults)2768 public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( 2769 @Nullable List<ScanResult> scanResults) { 2770 if (scanResults == null) { 2771 return new HashMap<>(); 2772 } 2773 try { 2774 return mService.getMatchingOsuProviders(scanResults); 2775 } catch (RemoteException e) { 2776 throw e.rethrowFromSystemServer(); 2777 } 2778 } 2779 2780 /** 2781 * Returns the matching Passpoint R2 configurations for given OSU (Online Sign-Up) providers. 2782 * 2783 * Given a list of OSU providers, this only returns OSU providers that already have Passpoint R2 2784 * configurations in the device. 2785 * An empty map will be returned when there is no matching Passpoint R2 configuration for the 2786 * given OsuProviders. 2787 * 2788 * @param osuProviders a set of {@link OsuProvider} 2789 * @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}. 2790 * @hide 2791 */ 2792 @SystemApi 2793 @RequiresPermission(anyOf = { 2794 android.Manifest.permission.NETWORK_SETTINGS, 2795 android.Manifest.permission.NETWORK_SETUP_WIZARD 2796 }) 2797 @NonNull getMatchingPasspointConfigsForOsuProviders( @onNull Set<OsuProvider> osuProviders)2798 public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( 2799 @NonNull Set<OsuProvider> osuProviders) { 2800 try { 2801 return mService.getMatchingPasspointConfigsForOsuProviders( 2802 new ArrayList<>(osuProviders)); 2803 } catch (RemoteException e) { 2804 throw e.rethrowFromSystemServer(); 2805 } 2806 } 2807 2808 /** 2809 * Add a new network description to the set of configured networks. 2810 * The {@code networkId} field of the supplied configuration object 2811 * is ignored. 2812 * <p/> 2813 * The new network will be marked DISABLED by default. To enable it, 2814 * called {@link #enableNetwork}. 2815 * 2816 * @param config the set of variables that describe the configuration, 2817 * contained in a {@link WifiConfiguration} object. 2818 * If the {@link WifiConfiguration} has an Http Proxy set 2819 * the calling app must be System, or be provisioned as the Profile or Device Owner. 2820 * @return the ID of the newly created network description. This is used in 2821 * other operations to specified the network to be acted upon. 2822 * Returns {@code -1} on failure. 2823 * 2824 * @deprecated 2825 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2826 * mechanism to trigger connection to a Wi-Fi network. 2827 * b) See {@link #addNetworkSuggestions(List)}, 2828 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2829 * when auto-connecting to wifi. 2830 * <b>Compatibility Note:</b> For applications targeting 2831 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 2832 * {@code -1}. 2833 * <p> 2834 * Deprecation Exemptions: 2835 * <ul> 2836 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2837 * </ul> 2838 */ 2839 @Deprecated addNetwork(WifiConfiguration config)2840 public int addNetwork(WifiConfiguration config) { 2841 if (config == null) { 2842 return -1; 2843 } 2844 config.networkId = -1; 2845 return addOrUpdateNetwork(config); 2846 } 2847 2848 /** 2849 * This is a new version of {@link #addNetwork(WifiConfiguration)} which returns more detailed 2850 * failure codes. The usage of this API is limited to Device Owner (DO), Profile Owner (PO), 2851 * system app, and privileged apps. 2852 * <p> 2853 * Add a new network description to the set of configured networks. The {@code networkId} 2854 * field of the supplied configuration object is ignored. The new network will be marked 2855 * DISABLED by default. To enable it, call {@link #enableNetwork}. 2856 * <p> 2857 * @param config the set of variables that describe the configuration, 2858 * contained in a {@link WifiConfiguration} object. 2859 * If the {@link WifiConfiguration} has an Http Proxy set 2860 * the calling app must be System, or be provisioned as the Profile or Device Owner. 2861 * @return A {@link AddNetworkResult} Object. 2862 * @throws SecurityException if the calling app is not a Device Owner (DO), 2863 * Profile Owner (PO), system app, or a privileged app that has one of 2864 * the permissions required by this API. 2865 * @throws IllegalArgumentException if the input configuration is null or if the 2866 * security type in input configuration is not supported. 2867 */ 2868 @RequiresPermission(anyOf = { 2869 android.Manifest.permission.NETWORK_SETTINGS, 2870 android.Manifest.permission.NETWORK_STACK, 2871 android.Manifest.permission.NETWORK_SETUP_WIZARD, 2872 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING 2873 }, conditional = true) 2874 @NonNull addNetworkPrivileged(@onNull WifiConfiguration config)2875 public AddNetworkResult addNetworkPrivileged(@NonNull WifiConfiguration config) { 2876 if (config == null) throw new IllegalArgumentException("config cannot be null"); 2877 if (config.isSecurityType(WifiInfo.SECURITY_TYPE_DPP) 2878 && !isFeatureSupported(WIFI_FEATURE_DPP_AKM)) { 2879 throw new IllegalArgumentException("dpp akm is not supported"); 2880 } 2881 config.networkId = -1; 2882 try { 2883 return mService.addOrUpdateNetworkPrivileged(config, mContext.getOpPackageName()); 2884 } catch (RemoteException e) { 2885 throw e.rethrowFromSystemServer(); 2886 } 2887 } 2888 2889 /** 2890 * Provides the results of a call to {@link #addNetworkPrivileged(WifiConfiguration)} 2891 */ 2892 public static final class AddNetworkResult implements Parcelable { 2893 /** 2894 * The operation has completed successfully. 2895 */ 2896 public static final int STATUS_SUCCESS = 0; 2897 /** 2898 * The operation has failed due to an unknown reason. 2899 */ 2900 public static final int STATUS_FAILURE_UNKNOWN = 1; 2901 /** 2902 * The calling app does not have permission to call this API. 2903 */ 2904 public static final int STATUS_NO_PERMISSION = 2; 2905 /** 2906 * Generic failure code for adding a passpoint network. 2907 */ 2908 public static final int STATUS_ADD_PASSPOINT_FAILURE = 3; 2909 /** 2910 * Generic failure code for adding a non-passpoint network. 2911 */ 2912 public static final int STATUS_ADD_WIFI_CONFIG_FAILURE = 4; 2913 /** 2914 * The network configuration is invalid. 2915 */ 2916 public static final int STATUS_INVALID_CONFIGURATION = 5; 2917 /** 2918 * The calling app has no permission to modify the configuration. 2919 */ 2920 public static final int STATUS_NO_PERMISSION_MODIFY_CONFIG = 6; 2921 /** 2922 * The calling app has no permission to modify the proxy setting. 2923 */ 2924 public static final int STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING = 7; 2925 /** 2926 * The calling app has no permission to modify the MAC randomization setting. 2927 */ 2928 public static final int STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION = 8; 2929 /** 2930 * Internal failure in updating network keys.. 2931 */ 2932 public static final int STATUS_FAILURE_UPDATE_NETWORK_KEYS = 9; 2933 /** 2934 * The enterprise network is missing either the root CA or domain name. 2935 */ 2936 public static final int STATUS_INVALID_CONFIGURATION_ENTERPRISE = 10; 2937 2938 /** @hide */ 2939 @IntDef(prefix = { "STATUS_" }, value = { 2940 STATUS_SUCCESS, 2941 STATUS_FAILURE_UNKNOWN, 2942 STATUS_NO_PERMISSION, 2943 STATUS_ADD_PASSPOINT_FAILURE, 2944 STATUS_ADD_WIFI_CONFIG_FAILURE, 2945 STATUS_INVALID_CONFIGURATION, 2946 STATUS_NO_PERMISSION_MODIFY_CONFIG, 2947 STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING, 2948 STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION, 2949 STATUS_FAILURE_UPDATE_NETWORK_KEYS, 2950 STATUS_INVALID_CONFIGURATION_ENTERPRISE, 2951 }) 2952 @Retention(RetentionPolicy.SOURCE) 2953 public @interface AddNetworkStatusCode {} 2954 2955 @Override describeContents()2956 public int describeContents() { 2957 return 0; 2958 } 2959 2960 @Override writeToParcel(@onNull Parcel dest, int flags)2961 public void writeToParcel(@NonNull Parcel dest, int flags) { 2962 dest.writeInt(statusCode); 2963 dest.writeInt(networkId); 2964 } 2965 2966 /** Implement the Parcelable interface */ 2967 public static final @android.annotation.NonNull Creator<AddNetworkResult> CREATOR = 2968 new Creator<AddNetworkResult>() { 2969 public AddNetworkResult createFromParcel(Parcel in) { 2970 return new AddNetworkResult(in.readInt(), in.readInt()); 2971 } 2972 2973 public AddNetworkResult[] newArray(int size) { 2974 return new AddNetworkResult[size]; 2975 } 2976 }; 2977 2978 /** 2979 * One of the {@code STATUS_} values. If the operation is successful this field 2980 * will be set to {@code STATUS_SUCCESS}. 2981 */ 2982 public final @AddNetworkStatusCode int statusCode; 2983 /** 2984 * The identifier of the added network, which could be used in other operations. This field 2985 * will be set to {@code -1} if the operation failed. 2986 */ 2987 public final int networkId; 2988 AddNetworkResult(@ddNetworkStatusCode int statusCode, int networkId)2989 public AddNetworkResult(@AddNetworkStatusCode int statusCode, int networkId) { 2990 this.statusCode = statusCode; 2991 this.networkId = networkId; 2992 } 2993 } 2994 2995 /** 2996 * Update the network description of an existing configured network. 2997 * 2998 * @param config the set of variables that describe the configuration, 2999 * contained in a {@link WifiConfiguration} object. It may 3000 * be sparse, so that only the items that are being changed 3001 * are non-<code>null</code>. The {@code networkId} field 3002 * must be set to the ID of the existing network being updated. 3003 * If the {@link WifiConfiguration} has an Http Proxy set 3004 * the calling app must be System, or be provisioned as the Profile or Device Owner. 3005 * @return Returns the {@code networkId} of the supplied 3006 * {@code WifiConfiguration} on success. 3007 * <br/> 3008 * Returns {@code -1} on failure, including when the {@code networkId} 3009 * field of the {@code WifiConfiguration} does not refer to an 3010 * existing network. 3011 * 3012 * @deprecated 3013 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3014 * mechanism to trigger connection to a Wi-Fi network. 3015 * b) See {@link #addNetworkSuggestions(List)}, 3016 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3017 * when auto-connecting to wifi. 3018 * <b>Compatibility Note:</b> For applications targeting 3019 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3020 * {@code -1}. 3021 * <p> 3022 * Deprecation Exemptions: 3023 * <ul> 3024 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3025 * </ul> 3026 */ 3027 @Deprecated updateNetwork(WifiConfiguration config)3028 public int updateNetwork(WifiConfiguration config) { 3029 if (config == null || config.networkId < 0) { 3030 return -1; 3031 } 3032 return addOrUpdateNetwork(config); 3033 } 3034 3035 /** 3036 * Internal method for doing the RPC that creates a new network description 3037 * or updates an existing one. 3038 * 3039 * @param config The possibly sparse object containing the variables that 3040 * are to set or updated in the network description. 3041 * @return the ID of the network on success, {@code -1} on failure. 3042 */ addOrUpdateNetwork(WifiConfiguration config)3043 private int addOrUpdateNetwork(WifiConfiguration config) { 3044 Bundle extras = new Bundle(); 3045 if (SdkLevel.isAtLeastS()) { 3046 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 3047 mContext.getAttributionSource()); 3048 } 3049 3050 try { 3051 return mService.addOrUpdateNetwork(config, mContext.getOpPackageName(), extras); 3052 } catch (RemoteException e) { 3053 throw e.rethrowFromSystemServer(); 3054 } 3055 } 3056 3057 /** 3058 * Interface for indicating user selection from the list of networks presented in the 3059 * {@link NetworkRequestMatchCallback#onMatch(List)}. 3060 * 3061 * The platform will implement this callback and pass it along with the 3062 * {@link NetworkRequestMatchCallback#onUserSelectionCallbackRegistration( 3063 * NetworkRequestUserSelectionCallback)}. The UI component handling 3064 * {@link NetworkRequestMatchCallback} will invoke {@link #select(WifiConfiguration)} or 3065 * {@link #reject()} to return the user's selection back to the platform via this callback. 3066 * @hide 3067 */ 3068 @SystemApi 3069 public interface NetworkRequestUserSelectionCallback { 3070 /** 3071 * User selected this network to connect to. 3072 * @param wifiConfiguration WifiConfiguration object corresponding to the network 3073 * user selected. 3074 */ 3075 @SuppressLint("CallbackMethodName") select(@onNull WifiConfiguration wifiConfiguration)3076 default void select(@NonNull WifiConfiguration wifiConfiguration) {} 3077 3078 /** 3079 * User rejected the app's request. 3080 */ 3081 @SuppressLint("CallbackMethodName") reject()3082 default void reject() {} 3083 } 3084 3085 /** 3086 * Interface for network request callback. Should be implemented by applications and passed when 3087 * calling {@link #registerNetworkRequestMatchCallback(Executor, 3088 * WifiManager.NetworkRequestMatchCallback)}. 3089 * 3090 * This is meant to be implemented by a UI component to present the user with a list of networks 3091 * matching the app's request. The user is allowed to pick one of these networks to connect to 3092 * or reject the request by the app. 3093 * @hide 3094 */ 3095 @SystemApi 3096 public interface NetworkRequestMatchCallback { 3097 /** 3098 * Invoked to register a callback to be invoked to convey user selection. The callback 3099 * object passed in this method is to be invoked by the UI component after the service sends 3100 * a list of matching scan networks using {@link #onMatch(List)} and user picks a network 3101 * from that list. 3102 * 3103 * @param userSelectionCallback Callback object to send back the user selection. 3104 */ onUserSelectionCallbackRegistration( @onNull NetworkRequestUserSelectionCallback userSelectionCallback)3105 default void onUserSelectionCallbackRegistration( 3106 @NonNull NetworkRequestUserSelectionCallback userSelectionCallback) {} 3107 3108 /** 3109 * Invoked when the active network request is aborted, either because 3110 * <li> The app released the request, OR</li> 3111 * <li> Request was overridden by a new request</li> 3112 * This signals the end of processing for the current request and should stop the UI 3113 * component. No subsequent calls from the UI component will be handled by the platform. 3114 */ onAbort()3115 default void onAbort() {} 3116 3117 /** 3118 * Invoked when a network request initiated by an app matches some networks in scan results. 3119 * This may be invoked multiple times for a single network request as the platform finds new 3120 * matching networks in scan results. 3121 * 3122 * @param scanResults List of {@link ScanResult} objects corresponding to the networks 3123 * matching the request. 3124 */ onMatch(@onNull List<ScanResult> scanResults)3125 default void onMatch(@NonNull List<ScanResult> scanResults) {} 3126 3127 /** 3128 * Invoked on a successful connection with the network that the user selected 3129 * via {@link NetworkRequestUserSelectionCallback}. 3130 * 3131 * @param wifiConfiguration WifiConfiguration object corresponding to the network that the 3132 * user selected. 3133 */ onUserSelectionConnectSuccess(@onNull WifiConfiguration wifiConfiguration)3134 default void onUserSelectionConnectSuccess(@NonNull WifiConfiguration wifiConfiguration) {} 3135 3136 /** 3137 * Invoked on failure to establish connection with the network that the user selected 3138 * via {@link NetworkRequestUserSelectionCallback}. 3139 * 3140 * @param wifiConfiguration WifiConfiguration object corresponding to the network 3141 * user selected. 3142 */ onUserSelectionConnectFailure(@onNull WifiConfiguration wifiConfiguration)3143 default void onUserSelectionConnectFailure(@NonNull WifiConfiguration wifiConfiguration) {} 3144 } 3145 3146 /** 3147 * Callback proxy for NetworkRequestUserSelectionCallback objects. 3148 * @hide 3149 */ 3150 private class NetworkRequestUserSelectionCallbackProxy implements 3151 NetworkRequestUserSelectionCallback { 3152 private final INetworkRequestUserSelectionCallback mCallback; 3153 NetworkRequestUserSelectionCallbackProxy( INetworkRequestUserSelectionCallback callback)3154 NetworkRequestUserSelectionCallbackProxy( 3155 INetworkRequestUserSelectionCallback callback) { 3156 mCallback = callback; 3157 } 3158 3159 @Override select(@onNull WifiConfiguration wifiConfiguration)3160 public void select(@NonNull WifiConfiguration wifiConfiguration) { 3161 if (mVerboseLoggingEnabled) { 3162 Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: select " 3163 + "wificonfiguration: " + wifiConfiguration); 3164 } 3165 try { 3166 mCallback.select(wifiConfiguration); 3167 } catch (RemoteException e) { 3168 Log.e(TAG, "Failed to invoke onSelected", e); 3169 throw e.rethrowFromSystemServer(); 3170 } 3171 } 3172 3173 @Override reject()3174 public void reject() { 3175 if (mVerboseLoggingEnabled) { 3176 Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: reject"); 3177 } 3178 try { 3179 mCallback.reject(); 3180 } catch (RemoteException e) { 3181 Log.e(TAG, "Failed to invoke onRejected", e); 3182 throw e.rethrowFromSystemServer(); 3183 } 3184 } 3185 } 3186 3187 /** 3188 * Callback proxy for NetworkRequestMatchCallback objects. 3189 * @hide 3190 */ 3191 private class NetworkRequestMatchCallbackProxy extends INetworkRequestMatchCallback.Stub { 3192 private final Executor mExecutor; 3193 private final NetworkRequestMatchCallback mCallback; 3194 NetworkRequestMatchCallbackProxy(Executor executor, NetworkRequestMatchCallback callback)3195 NetworkRequestMatchCallbackProxy(Executor executor, NetworkRequestMatchCallback callback) { 3196 mExecutor = executor; 3197 mCallback = callback; 3198 } 3199 3200 @Override onUserSelectionCallbackRegistration( INetworkRequestUserSelectionCallback userSelectionCallback)3201 public void onUserSelectionCallbackRegistration( 3202 INetworkRequestUserSelectionCallback userSelectionCallback) { 3203 if (mVerboseLoggingEnabled) { 3204 Log.v(TAG, "NetworkRequestMatchCallbackProxy: " 3205 + "onUserSelectionCallbackRegistration callback: " + userSelectionCallback); 3206 } 3207 Binder.clearCallingIdentity(); 3208 mExecutor.execute(() -> { 3209 mCallback.onUserSelectionCallbackRegistration( 3210 new NetworkRequestUserSelectionCallbackProxy(userSelectionCallback)); 3211 }); 3212 } 3213 3214 @Override onAbort()3215 public void onAbort() { 3216 if (mVerboseLoggingEnabled) { 3217 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onAbort"); 3218 } 3219 Binder.clearCallingIdentity(); 3220 mExecutor.execute(() -> { 3221 mCallback.onAbort(); 3222 }); 3223 } 3224 3225 @Override onMatch(List<ScanResult> scanResults)3226 public void onMatch(List<ScanResult> scanResults) { 3227 if (mVerboseLoggingEnabled) { 3228 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onMatch scanResults: " 3229 + scanResults); 3230 } 3231 Binder.clearCallingIdentity(); 3232 mExecutor.execute(() -> { 3233 mCallback.onMatch(scanResults); 3234 }); 3235 } 3236 3237 @Override onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration)3238 public void onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration) { 3239 if (mVerboseLoggingEnabled) { 3240 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectSuccess " 3241 + " wificonfiguration: " + wifiConfiguration); 3242 } 3243 Binder.clearCallingIdentity(); 3244 mExecutor.execute(() -> { 3245 mCallback.onUserSelectionConnectSuccess(wifiConfiguration); 3246 }); 3247 } 3248 3249 @Override onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration)3250 public void onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration) { 3251 if (mVerboseLoggingEnabled) { 3252 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectFailure" 3253 + " wificonfiguration: " + wifiConfiguration); 3254 } 3255 Binder.clearCallingIdentity(); 3256 mExecutor.execute(() -> { 3257 mCallback.onUserSelectionConnectFailure(wifiConfiguration); 3258 }); 3259 } 3260 } 3261 3262 /** 3263 * Registers a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. 3264 * Caller can unregister a previously registered callback using 3265 * {@link #unregisterNetworkRequestMatchCallback(NetworkRequestMatchCallback)} 3266 * <p> 3267 * Applications should have the 3268 * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers 3269 * without the permission will trigger a {@link java.lang.SecurityException}. 3270 * <p> 3271 * 3272 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 3273 * object. 3274 * @param callback Callback for network match events to register. 3275 * @hide 3276 */ 3277 @SystemApi 3278 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) registerNetworkRequestMatchCallback(@onNull @allbackExecutor Executor executor, @NonNull NetworkRequestMatchCallback callback)3279 public void registerNetworkRequestMatchCallback(@NonNull @CallbackExecutor Executor executor, 3280 @NonNull NetworkRequestMatchCallback callback) { 3281 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 3282 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 3283 Log.v(TAG, "registerNetworkRequestMatchCallback: callback=" + callback 3284 + ", executor=" + executor); 3285 3286 try { 3287 synchronized (sNetworkRequestMatchCallbackMap) { 3288 INetworkRequestMatchCallback.Stub binderCallback = 3289 new NetworkRequestMatchCallbackProxy(executor, callback); 3290 sNetworkRequestMatchCallbackMap.put(System.identityHashCode(callback), 3291 binderCallback); 3292 mService.registerNetworkRequestMatchCallback(binderCallback); 3293 } 3294 } catch (RemoteException e) { 3295 throw e.rethrowFromSystemServer(); 3296 } 3297 } 3298 3299 /** 3300 * Unregisters a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. 3301 * <p> 3302 * Applications should have the 3303 * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers 3304 * without the permission will trigger a {@link java.lang.SecurityException}. 3305 * <p> 3306 * 3307 * @param callback Callback for network match events to unregister. 3308 * @hide 3309 */ 3310 @SystemApi 3311 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) unregisterNetworkRequestMatchCallback( @onNull NetworkRequestMatchCallback callback)3312 public void unregisterNetworkRequestMatchCallback( 3313 @NonNull NetworkRequestMatchCallback callback) { 3314 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 3315 Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback); 3316 3317 try { 3318 synchronized (sNetworkRequestMatchCallbackMap) { 3319 int callbackIdentifier = System.identityHashCode(callback); 3320 if (!sNetworkRequestMatchCallbackMap.contains(callbackIdentifier)) { 3321 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 3322 return; 3323 } 3324 mService.unregisterNetworkRequestMatchCallback( 3325 sNetworkRequestMatchCallbackMap.get(callbackIdentifier)); 3326 sNetworkRequestMatchCallbackMap.remove(callbackIdentifier); 3327 } 3328 } catch (RemoteException e) { 3329 throw e.rethrowFromSystemServer(); 3330 } 3331 } 3332 3333 /** 3334 * Privileged API to revoke all app state from wifi stack (equivalent to operations that the 3335 * wifi stack performs to clear state for an app that was uninstalled. 3336 * This removes: 3337 * <li> All saved networks or passpoint profiles added by the app </li> 3338 * <li> All previously approved peer to peer connection to access points initiated by the app 3339 * using {@link WifiNetworkSpecifier}</li> 3340 * <li> All network suggestions and approvals provided using {@link WifiNetworkSuggestion}</li> 3341 * <p> 3342 * @param targetAppUid UID of the app. 3343 * @param targetAppPackageName Package name of the app. 3344 * @hide 3345 */ 3346 @SystemApi 3347 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) removeAppState(int targetAppUid, @NonNull String targetAppPackageName)3348 public void removeAppState(int targetAppUid, @NonNull String targetAppPackageName) { 3349 try { 3350 mService.removeAppState(targetAppUid, targetAppPackageName); 3351 } catch (RemoteException e) { 3352 throw e.rethrowAsRuntimeException(); 3353 } 3354 } 3355 3356 /** 3357 * Provide a list of network suggestions to the device. See {@link WifiNetworkSuggestion} 3358 * for a detailed explanation of the parameters. 3359 * When the device decides to connect to one of the provided network suggestions, platform sends 3360 * a directed broadcast {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} to the app if 3361 * the network was created with 3362 * {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired(boolean)} flag set and the 3363 * app holds {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} 3364 * permission. 3365 *<p> 3366 * NOTE: 3367 * <ul> 3368 * <li> These networks are just a suggestion to the platform. The platform will ultimately 3369 * decide on which network the device connects to. </li> 3370 * <li> When an app is uninstalled or disabled, all its suggested networks are discarded. 3371 * If the device is currently connected to a suggested network which is being removed then the 3372 * device will disconnect from that network.</li> 3373 * <li> If user reset network settings, all added suggestions will be discarded. Apps can use 3374 * {@link #getNetworkSuggestions()} to check if their suggestions are in the device.</li> 3375 * <li> In-place modification of existing suggestions are allowed.</li> 3376 * <ul> 3377 * <li> If the provided suggestions include any previously provided suggestions by the app, 3378 * previous suggestions will be updated.</li> 3379 * <li>If one of the provided suggestions marks a previously unmetered suggestion as metered and 3380 * the device is currently connected to that suggested network, then the device will disconnect 3381 * from that network. The system will immediately re-evaluate all the network candidates 3382 * and possibly reconnect back to the same suggestion. This disconnect is to make sure that any 3383 * traffic flowing over unmetered networks isn't accidentally continued over a metered network. 3384 * </li> 3385 * <li> 3386 * On {@link android.os.Build.VERSION_CODES#TIRAMISU} or above If one of the provided 3387 * suggestions marks a previously trusted suggestion as untrusted and the device is currently 3388 * connected to that suggested network, then the device will disconnect from that network. The 3389 * system will immediately re-evaluate all the network candidates. This disconnect is to make 3390 * sure device will not remain connected to an untrusted network without a related 3391 * {@link android.net.NetworkRequest}. 3392 * </li> 3393 * </ul> 3394 * </ul> 3395 * 3396 * @param networkSuggestions List of network suggestions provided by the app. 3397 * @return Status code for the operation. One of the STATUS_NETWORK_SUGGESTIONS_ values. 3398 * @throws SecurityException if the caller is missing required permissions. 3399 * @see WifiNetworkSuggestion#equals(Object) 3400 */ 3401 @RequiresPermission(CHANGE_WIFI_STATE) addNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions)3402 public @NetworkSuggestionsStatusCode int addNetworkSuggestions( 3403 @NonNull List<WifiNetworkSuggestion> networkSuggestions) { 3404 try { 3405 return mService.addNetworkSuggestions( 3406 networkSuggestions, mContext.getOpPackageName(), mContext.getAttributionTag()); 3407 } catch (RemoteException e) { 3408 throw e.rethrowFromSystemServer(); 3409 } 3410 } 3411 3412 /** 3413 * Remove some or all of the network suggestions that were previously provided by the app. 3414 * If one of the suggestions being removed was used to establish connection to the current 3415 * network, then the device will immediately disconnect from that network. This method is same 3416 * as {@link #removeNetworkSuggestions(List, int)} with 3417 * {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT} 3418 * 3419 * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters. 3420 * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used. 3421 * <p></ 3422 * Note: Use {@link #removeNetworkSuggestions(List, int)}. An {@code action} of 3423 * {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT} is equivalent to the current behavior. 3424 * 3425 * @param networkSuggestions List of network suggestions to be removed. Pass an empty list 3426 * to remove all the previous suggestions provided by the app. 3427 * @return Status code for the operation. One of the {@code STATUS_NETWORK_SUGGESTIONS_*} 3428 * values. Any matching suggestions are removed from the device and will not be considered for 3429 * any further connection attempts. 3430 */ 3431 @RequiresPermission(CHANGE_WIFI_STATE) removeNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions)3432 public @NetworkSuggestionsStatusCode int removeNetworkSuggestions( 3433 @NonNull List<WifiNetworkSuggestion> networkSuggestions) { 3434 return removeNetworkSuggestions(networkSuggestions, ACTION_REMOVE_SUGGESTION_DISCONNECT); 3435 } 3436 3437 /** 3438 * Remove some or all of the network suggestions that were previously provided by the app. 3439 * If one of the suggestions being removed was used to establish connection to the current 3440 * network, then the specified action will be executed. 3441 * 3442 * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters. 3443 * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used. 3444 * 3445 * @param networkSuggestions List of network suggestions to be removed. Pass an empty list 3446 * to remove all the previous suggestions provided by the app. 3447 * @param action Desired action to execute after removing the suggestion. One of 3448 * {@code ACTION_REMOVE_SUGGESTION_*} 3449 * @return Status code for the operation. One of the {@code STATUS_NETWORK_SUGGESTIONS_*} 3450 * values. Any matching suggestions are removed from the device and will not be considered for 3451 * further connection attempts. 3452 */ 3453 @RequiresPermission(CHANGE_WIFI_STATE) removeNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions, @ActionAfterRemovingSuggestion int action)3454 public @NetworkSuggestionsStatusCode int removeNetworkSuggestions( 3455 @NonNull List<WifiNetworkSuggestion> networkSuggestions, 3456 @ActionAfterRemovingSuggestion int action) { 3457 try { 3458 return mService.removeNetworkSuggestions(networkSuggestions, 3459 mContext.getOpPackageName(), action); 3460 } catch (RemoteException e) { 3461 throw e.rethrowFromSystemServer(); 3462 } 3463 } 3464 3465 /** 3466 * Get all network suggestions provided by the calling app. 3467 * See {@link #addNetworkSuggestions(List)} 3468 * See {@link #removeNetworkSuggestions(List)} 3469 * @return a list of {@link WifiNetworkSuggestion} 3470 */ 3471 @RequiresPermission(ACCESS_WIFI_STATE) getNetworkSuggestions()3472 public @NonNull List<WifiNetworkSuggestion> getNetworkSuggestions() { 3473 try { 3474 return mService.getNetworkSuggestions(mContext.getOpPackageName()); 3475 } catch (RemoteException e) { 3476 throw e.rethrowAsRuntimeException(); 3477 } 3478 } 3479 3480 /** 3481 * Returns the max number of network suggestions that are allowed per app on the device. 3482 * @see #addNetworkSuggestions(List) 3483 * @see #removeNetworkSuggestions(List) 3484 */ getMaxNumberOfNetworkSuggestionsPerApp()3485 public int getMaxNumberOfNetworkSuggestionsPerApp() { 3486 return getMaxNumberOfNetworkSuggestionsPerApp( 3487 mContext.getSystemService(ActivityManager.class).isLowRamDevice()); 3488 } 3489 3490 /** @hide */ getMaxNumberOfNetworkSuggestionsPerApp(boolean isLowRamDevice)3491 public static int getMaxNumberOfNetworkSuggestionsPerApp(boolean isLowRamDevice) { 3492 return isLowRamDevice 3493 ? NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM 3494 : NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM; 3495 } 3496 3497 /** 3498 * Add or update a Passpoint configuration. The configuration provides a credential 3499 * for connecting to Passpoint networks that are operated by the Passpoint 3500 * service provider specified in the configuration. 3501 * 3502 * Each configuration is uniquely identified by a unique key which depends on the contents of 3503 * the configuration. This allows the caller to install multiple profiles with the same FQDN 3504 * (Fully qualified domain name). Therefore, in order to update an existing profile, it is 3505 * first required to remove it using {@link WifiManager#removePasspointConfiguration(String)}. 3506 * Otherwise, a new profile will be added with both configuration. 3507 * 3508 * Deprecated for general app usage - except DO/PO apps. 3509 * See {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} to 3510 * create a passpoint suggestion. 3511 * See {@link #addNetworkSuggestions(List)}, {@link #removeNetworkSuggestions(List)} for new 3512 * API to add Wi-Fi networks for consideration when auto-connecting to wifi. 3513 * <b>Compatibility Note:</b> For applications targeting 3514 * {@link android.os.Build.VERSION_CODES#R} or above, this API will always fail and throw 3515 * {@link IllegalArgumentException}. 3516 * <p> 3517 * Deprecation Exemptions: 3518 * <ul> 3519 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3520 * </ul> 3521 * 3522 * @param config The Passpoint configuration to be added 3523 * @throws IllegalArgumentException if configuration is invalid or Passpoint is not enabled on 3524 * the device. 3525 */ addOrUpdatePasspointConfiguration(PasspointConfiguration config)3526 public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) { 3527 try { 3528 if (!mService.addOrUpdatePasspointConfiguration(config, mContext.getOpPackageName())) { 3529 throw new IllegalArgumentException(); 3530 } 3531 } catch (RemoteException e) { 3532 throw e.rethrowFromSystemServer(); 3533 } 3534 } 3535 3536 /** 3537 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name) added 3538 * by the caller. 3539 * 3540 * @param fqdn The FQDN of the Passpoint configuration added by the caller to be removed 3541 * @throws IllegalArgumentException if no configuration is associated with the given FQDN or 3542 * Passpoint is not enabled on the device. 3543 * @deprecated This will be non-functional in a future release. 3544 * <br> 3545 * Requires {@code android.Manifest.permission.NETWORK_SETTINGS} or 3546 * {@code android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}. 3547 */ 3548 @Deprecated removePasspointConfiguration(String fqdn)3549 public void removePasspointConfiguration(String fqdn) { 3550 try { 3551 if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) { 3552 throw new IllegalArgumentException(); 3553 } 3554 } catch (RemoteException e) { 3555 throw e.rethrowFromSystemServer(); 3556 } 3557 } 3558 3559 /** 3560 * Return the list of installed Passpoint configurations added by the caller. 3561 * 3562 * An empty list will be returned when no configurations are installed. 3563 * 3564 * @return A list of {@link PasspointConfiguration} added by the caller 3565 * @deprecated This will be non-functional in a future release. 3566 * <br> 3567 * Requires {@code android.Manifest.permission.NETWORK_SETTINGS} or 3568 * {@code android.Manifest.permission.NETWORK_SETUP_WIZARD}. 3569 */ 3570 @Deprecated getPasspointConfigurations()3571 public List<PasspointConfiguration> getPasspointConfigurations() { 3572 try { 3573 return mService.getPasspointConfigurations(mContext.getOpPackageName()); 3574 } catch (RemoteException e) { 3575 throw e.rethrowFromSystemServer(); 3576 } 3577 } 3578 3579 /** 3580 * Query for a Hotspot 2.0 release 2 OSU icon file. An {@link #ACTION_PASSPOINT_ICON} intent 3581 * will be broadcasted once the request is completed. The presence of the intent extra 3582 * {@link #EXTRA_ICON} will indicate the result of the request. 3583 * A missing intent extra {@link #EXTRA_ICON} will indicate a failure. 3584 * 3585 * @param bssid The BSSID of the AP 3586 * @param fileName Name of the icon file (remote file) to query from the AP 3587 * 3588 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 3589 * @hide 3590 */ queryPasspointIcon(long bssid, String fileName)3591 public void queryPasspointIcon(long bssid, String fileName) { 3592 try { 3593 mService.queryPasspointIcon(bssid, fileName); 3594 } catch (RemoteException e) { 3595 throw e.rethrowFromSystemServer(); 3596 } 3597 } 3598 3599 /** 3600 * Match the currently associated network against the SP matching the given FQDN 3601 * @param fqdn FQDN of the SP 3602 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 3603 * @hide 3604 */ matchProviderWithCurrentNetwork(String fqdn)3605 public int matchProviderWithCurrentNetwork(String fqdn) { 3606 try { 3607 return mService.matchProviderWithCurrentNetwork(fqdn); 3608 } catch (RemoteException e) { 3609 throw e.rethrowFromSystemServer(); 3610 } 3611 } 3612 3613 /** 3614 * Remove the specified network from the list of configured networks. 3615 * This may result in the asynchronous delivery of state change 3616 * events. 3617 * 3618 * Applications are not allowed to remove networks created by other 3619 * applications. 3620 * 3621 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 3622 * #getConfiguredNetworks}. 3623 * @return {@code true} if the operation succeeded 3624 * 3625 * @deprecated 3626 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3627 * mechanism to trigger connection to a Wi-Fi network. 3628 * b) See {@link #addNetworkSuggestions(List)}, 3629 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3630 * when auto-connecting to wifi. 3631 * <b>Compatibility Note:</b> For applications targeting 3632 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3633 * {@code false}. 3634 * <p> 3635 * Deprecation Exemptions: 3636 * <ul> 3637 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3638 * </ul> 3639 */ 3640 @Deprecated removeNetwork(int netId)3641 public boolean removeNetwork(int netId) { 3642 try { 3643 return mService.removeNetwork(netId, mContext.getOpPackageName()); 3644 } catch (RemoteException e) { 3645 throw e.rethrowFromSystemServer(); 3646 } 3647 } 3648 3649 /** 3650 * Remove all configured networks that were not created by the calling app. Can only 3651 * be called by a Device Owner (DO) app. 3652 * 3653 * @return {@code true} if at least one network is removed, {@code false} otherwise 3654 * @throws SecurityException if the caller is not a Device Owner app 3655 */ 3656 @RequiresPermission(CHANGE_WIFI_STATE) removeNonCallerConfiguredNetworks()3657 public boolean removeNonCallerConfiguredNetworks() { 3658 try { 3659 return mService.removeNonCallerConfiguredNetworks(mContext.getOpPackageName()); 3660 } catch (RemoteException e) { 3661 throw e.rethrowFromSystemServer(); 3662 } 3663 } 3664 /** 3665 * Allow a previously configured network to be associated with. If 3666 * <code>attemptConnect</code> is true, an attempt to connect to the selected 3667 * network is initiated. This may result in the asynchronous delivery 3668 * of state change events. 3669 * <p> 3670 * <b>Note:</b> Network communication may not use Wi-Fi even if Wi-Fi is connected; 3671 * traffic may instead be sent through another network, such as cellular data, 3672 * Bluetooth tethering, or Ethernet. For example, traffic will never use a 3673 * Wi-Fi network that does not provide Internet access (e.g. a wireless 3674 * printer), if another network that does offer Internet access (e.g. 3675 * cellular data) is available. Applications that need to ensure that their 3676 * network traffic uses Wi-Fi should use APIs such as 3677 * {@link Network#bindSocket(java.net.Socket)}, 3678 * {@link Network#openConnection(java.net.URL)}, or 3679 * {@link ConnectivityManager#bindProcessToNetwork} to do so. 3680 * 3681 * Applications are not allowed to enable networks created by other 3682 * applications. 3683 * 3684 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 3685 * #getConfiguredNetworks}. 3686 * @param attemptConnect The way to select a particular network to connect to is specify 3687 * {@code true} for this parameter. 3688 * @return {@code true} if the operation succeeded 3689 * 3690 * @deprecated 3691 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3692 * mechanism to trigger connection to a Wi-Fi network. 3693 * b) See {@link #addNetworkSuggestions(List)}, 3694 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3695 * when auto-connecting to wifi. 3696 * <b>Compatibility Note:</b> For applications targeting 3697 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3698 * {@code false}. 3699 * Deprecation Exemptions: 3700 * <ul> 3701 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3702 * </ul> 3703 */ 3704 @Deprecated enableNetwork(int netId, boolean attemptConnect)3705 public boolean enableNetwork(int netId, boolean attemptConnect) { 3706 try { 3707 return mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName()); 3708 } catch (RemoteException e) { 3709 throw e.rethrowFromSystemServer(); 3710 } 3711 } 3712 3713 /** 3714 * Disable a configured network. The specified network will not be 3715 * a candidate for associating. This may result in the asynchronous 3716 * delivery of state change events. 3717 * 3718 * Applications are not allowed to disable networks created by other 3719 * applications. 3720 * 3721 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 3722 * #getConfiguredNetworks}. 3723 * @return {@code true} if the operation succeeded 3724 * 3725 * @deprecated 3726 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3727 * mechanism to trigger connection to a Wi-Fi network. 3728 * b) See {@link #addNetworkSuggestions(List)}, 3729 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3730 * when auto-connecting to wifi. 3731 * <b>Compatibility Note:</b> For applications targeting 3732 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3733 * {@code false}. 3734 * <p> 3735 * Deprecation Exemptions: 3736 * <ul> 3737 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3738 * </ul> 3739 */ 3740 @Deprecated disableNetwork(int netId)3741 public boolean disableNetwork(int netId) { 3742 try { 3743 return mService.disableNetwork(netId, mContext.getOpPackageName()); 3744 } catch (RemoteException e) { 3745 throw e.rethrowFromSystemServer(); 3746 } 3747 } 3748 3749 /** 3750 * Disassociate from the currently active access point. This may result 3751 * in the asynchronous delivery of state change events. 3752 * @return {@code true} if the operation succeeded 3753 * 3754 * @deprecated 3755 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3756 * mechanism to trigger connection to a Wi-Fi network. 3757 * b) See {@link #addNetworkSuggestions(List)}, 3758 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3759 * when auto-connecting to wifi. 3760 * <b>Compatibility Note:</b> For applications targeting 3761 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3762 * {@code false}. 3763 * <p> 3764 * Deprecation Exemptions: 3765 * <ul> 3766 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3767 * </ul> 3768 */ 3769 @Deprecated disconnect()3770 public boolean disconnect() { 3771 try { 3772 return mService.disconnect(mContext.getOpPackageName()); 3773 } catch (RemoteException e) { 3774 throw e.rethrowFromSystemServer(); 3775 } 3776 } 3777 3778 /** 3779 * Reconnect to the currently active access point, if we are currently 3780 * disconnected. This may result in the asynchronous delivery of state 3781 * change events. 3782 * @return {@code true} if the operation succeeded 3783 * 3784 * @deprecated 3785 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3786 * mechanism to trigger connection to a Wi-Fi network. 3787 * b) See {@link #addNetworkSuggestions(List)}, 3788 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3789 * when auto-connecting to wifi. 3790 * <b>Compatibility Note:</b> For applications targeting 3791 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3792 * {@code false}. 3793 * <p> 3794 * Deprecation Exemptions: 3795 * <ul> 3796 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3797 * </ul> 3798 */ 3799 @Deprecated reconnect()3800 public boolean reconnect() { 3801 try { 3802 return mService.reconnect(mContext.getOpPackageName()); 3803 } catch (RemoteException e) { 3804 throw e.rethrowFromSystemServer(); 3805 } 3806 } 3807 3808 /** 3809 * Reconnect to the currently active access point, even if we are already 3810 * connected. This may result in the asynchronous delivery of state 3811 * change events. 3812 * @return {@code true} if the operation succeeded 3813 * 3814 * @deprecated 3815 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3816 * mechanism to trigger connection to a Wi-Fi network. 3817 * b) See {@link #addNetworkSuggestions(List)}, 3818 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3819 * when auto-connecting to wifi. 3820 * <b>Compatibility Note:</b> For applications targeting 3821 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. 3822 */ 3823 @Deprecated reassociate()3824 public boolean reassociate() { 3825 try { 3826 return mService.reassociate(mContext.getOpPackageName()); 3827 } catch (RemoteException e) { 3828 throw e.rethrowFromSystemServer(); 3829 } 3830 } 3831 3832 /** 3833 * Check that the supplicant daemon is responding to requests. 3834 * @return {@code true} if we were able to communicate with the supplicant and 3835 * it returned the expected response to the PING message. 3836 * @deprecated Will return the output of {@link #isWifiEnabled()} instead. 3837 */ 3838 @Deprecated pingSupplicant()3839 public boolean pingSupplicant() { 3840 return isWifiEnabled(); 3841 } 3842 3843 /** @hide */ 3844 public static final long WIFI_FEATURE_INFRA = 1L << 0; // Basic infrastructure mode 3845 /** @hide */ 3846 public static final long WIFI_FEATURE_PASSPOINT = 1L << 2; // Support for GAS/ANQP 3847 /** @hide */ 3848 public static final long WIFI_FEATURE_P2P = 1L << 3; // Wifi-Direct 3849 /** @hide */ 3850 public static final long WIFI_FEATURE_MOBILE_HOTSPOT = 1L << 4; // Soft AP 3851 /** @hide */ 3852 public static final long WIFI_FEATURE_SCANNER = 1L << 5; // WifiScanner APIs 3853 /** @hide */ 3854 public static final long WIFI_FEATURE_AWARE = 1L << 6; // Wi-Fi Aware networking 3855 /** @hide */ 3856 public static final long WIFI_FEATURE_D2D_RTT = 1L << 7; // Device-to-device RTT 3857 /** @hide */ 3858 public static final long WIFI_FEATURE_D2AP_RTT = 1L << 8; // Device-to-AP RTT 3859 /** @hide */ 3860 public static final long WIFI_FEATURE_PNO = 1L << 10; // Preferred network offload 3861 /** @hide */ 3862 public static final long WIFI_FEATURE_TDLS = 1L << 12; // Tunnel directed link setup 3863 /** @hide */ 3864 public static final long WIFI_FEATURE_TDLS_OFFCHANNEL = 1L << 13; // TDLS off channel 3865 /** @hide */ 3866 public static final long WIFI_FEATURE_AP_STA = 1L << 15; // AP STA Concurrency 3867 /** @hide */ 3868 public static final long WIFI_FEATURE_LINK_LAYER_STATS = 1L << 16; // Link layer stats 3869 /** @hide */ 3870 public static final long WIFI_FEATURE_LOGGER = 1L << 17; // WiFi Logger 3871 /** @hide */ 3872 public static final long WIFI_FEATURE_RSSI_MONITOR = 1L << 19; // RSSI Monitor 3873 /** @hide */ 3874 public static final long WIFI_FEATURE_MKEEP_ALIVE = 1L << 20; // mkeep_alive 3875 /** @hide */ 3876 public static final long WIFI_FEATURE_CONFIG_NDO = 1L << 21; // ND offload 3877 /** @hide */ 3878 public static final long WIFI_FEATURE_CONTROL_ROAMING = 1L << 23; // Control firmware roaming 3879 /** @hide */ 3880 public static final long WIFI_FEATURE_IE_WHITELIST = 1L << 24; // Probe IE white listing 3881 /** @hide */ 3882 public static final long WIFI_FEATURE_SCAN_RAND = 1L << 25; // Random MAC & Probe seq 3883 /** @hide */ 3884 public static final long WIFI_FEATURE_TX_POWER_LIMIT = 1L << 26; // Set Tx power limit 3885 /** @hide */ 3886 public static final long WIFI_FEATURE_WPA3_SAE = 1L << 27; // WPA3-Personal SAE 3887 /** @hide */ 3888 public static final long WIFI_FEATURE_WPA3_SUITE_B = 1L << 28; // WPA3-Enterprise Suite-B 3889 /** @hide */ 3890 public static final long WIFI_FEATURE_OWE = 1L << 29; // Enhanced Open 3891 /** @hide */ 3892 public static final long WIFI_FEATURE_LOW_LATENCY = 1L << 30; // Low Latency modes 3893 /** @hide */ 3894 public static final long WIFI_FEATURE_DPP = 1L << 31; // DPP (Easy-Connect) 3895 /** @hide */ 3896 public static final long WIFI_FEATURE_P2P_RAND_MAC = 1L << 32; // Random P2P MAC 3897 /** @hide */ 3898 public static final long WIFI_FEATURE_CONNECTED_RAND_MAC = 1L << 33; // Random STA MAC 3899 /** @hide */ 3900 public static final long WIFI_FEATURE_AP_RAND_MAC = 1L << 34; // Random AP MAC 3901 /** @hide */ 3902 public static final long WIFI_FEATURE_MBO = 1L << 35; // MBO Support 3903 /** @hide */ 3904 public static final long WIFI_FEATURE_OCE = 1L << 36; // OCE Support 3905 /** @hide */ 3906 public static final long WIFI_FEATURE_WAPI = 1L << 37; // WAPI 3907 3908 /** @hide */ 3909 public static final long WIFI_FEATURE_FILS_SHA256 = 1L << 38; // FILS-SHA256 3910 3911 /** @hide */ 3912 public static final long WIFI_FEATURE_FILS_SHA384 = 1L << 39; // FILS-SHA384 3913 3914 /** @hide */ 3915 public static final long WIFI_FEATURE_SAE_PK = 1L << 40; // SAE-PK 3916 3917 /** @hide */ 3918 public static final long WIFI_FEATURE_STA_BRIDGED_AP = 1L << 41; // STA + Bridged AP 3919 3920 /** @hide */ 3921 public static final long WIFI_FEATURE_BRIDGED_AP = 1L << 42; // Bridged AP 3922 3923 /** @hide */ 3924 public static final long WIFI_FEATURE_INFRA_60G = 1L << 43; // 60 GHz Band Support 3925 3926 /** 3927 * Support for 2 STA's for the local-only (peer to peer) connection + internet connection 3928 * concurrency. 3929 * @hide 3930 */ 3931 public static final long WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 1L << 44; 3932 3933 /** 3934 * Support for 2 STA's for the make before break concurrency. 3935 * @hide 3936 */ 3937 public static final long WIFI_FEATURE_ADDITIONAL_STA_MBB = 1L << 45; 3938 3939 /** 3940 * Support for 2 STA's for the restricted connection + internet connection concurrency. 3941 * @hide 3942 */ 3943 public static final long WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 1L << 46; 3944 3945 /** 3946 * DPP (Easy-Connect) Enrollee Responder mode support 3947 * @hide 3948 */ 3949 public static final long WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 1L << 47; 3950 3951 /** 3952 * Passpoint Terms and Conditions feature support 3953 * @hide 3954 */ 3955 public static final long WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 1L << 48; 3956 3957 /** @hide */ 3958 public static final long WIFI_FEATURE_SAE_H2E = 1L << 49; // Hash-to-Element 3959 3960 /** @hide */ 3961 public static final long WIFI_FEATURE_WFD_R2 = 1L << 50; // Wi-Fi Display R2 3962 3963 /** 3964 * RFC 7542 decorated identity support 3965 * @hide */ 3966 public static final long WIFI_FEATURE_DECORATED_IDENTITY = 1L << 51; 3967 3968 /** 3969 * Trust On First Use support for WPA Enterprise network 3970 * @hide 3971 */ 3972 public static final long WIFI_FEATURE_TRUST_ON_FIRST_USE = 1L << 52; 3973 3974 /** 3975 * Support for 2 STA's multi internet concurrency. 3976 * @hide 3977 */ 3978 public static final long WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 1L << 53; 3979 3980 /** 3981 * Support for DPP (Easy-Connect) AKM. 3982 * @hide 3983 */ 3984 public static final long WIFI_FEATURE_DPP_AKM = 1L << 54; 3985 3986 /** 3987 * Support for setting TLS minimum version. 3988 * @hide 3989 */ 3990 public static final long WIFI_FEATURE_SET_TLS_MINIMUM_VERSION = 1L << 55; 3991 3992 /** 3993 * Support for TLS v.13. 3994 * @hide 3995 */ 3996 public static final long WIFI_FEATURE_TLS_V1_3 = 1L << 56; 3997 3998 /** 3999 * Support for Dual Band Simultaneous (DBS) operation. 4000 * @hide 4001 */ 4002 public static final long WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS = 1L << 57; 4003 4004 /** 4005 * Support for TID-To-Link Mapping negotiation. 4006 * @hide 4007 */ 4008 public static final long WIFI_FEATURE_T2LM_NEGOTIATION = 1L << 58; 4009 4010 /** 4011 * Support for WEP Wi-Fi Network 4012 * @hide 4013 */ 4014 public static final long WIFI_FEATURE_WEP = 1L << 59; 4015 4016 /** 4017 * Support for WPA PERSONAL Wi-Fi Network 4018 * @hide 4019 */ 4020 public static final long WIFI_FEATURE_WPA_PERSONAL = 1L << 60; 4021 4022 /** 4023 * Support for Roaming Mode 4024 * @hide 4025 */ 4026 public static final long WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT = 1L << 61; 4027 4028 /** 4029 * Supports device-to-device connections when infra STA is disabled. 4030 * @hide 4031 */ 4032 public static final long WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED = 1L << 62; 4033 getSupportedFeatures()4034 private long getSupportedFeatures() { 4035 try { 4036 return mService.getSupportedFeatures(); 4037 } catch (RemoteException e) { 4038 throw e.rethrowFromSystemServer(); 4039 } 4040 } 4041 isFeatureSupported(long feature)4042 private boolean isFeatureSupported(long feature) { 4043 return (getSupportedFeatures() & feature) == feature; 4044 } 4045 4046 /** 4047 * @return true if this adapter supports Passpoint 4048 * @hide 4049 */ isPasspointSupported()4050 public boolean isPasspointSupported() { 4051 return isFeatureSupported(WIFI_FEATURE_PASSPOINT); 4052 } 4053 4054 /** 4055 * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct) 4056 */ isP2pSupported()4057 public boolean isP2pSupported() { 4058 return isFeatureSupported(WIFI_FEATURE_P2P); 4059 } 4060 4061 /** 4062 * @return true if this adapter supports portable Wi-Fi hotspot 4063 * @hide 4064 */ 4065 @SystemApi isPortableHotspotSupported()4066 public boolean isPortableHotspotSupported() { 4067 return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT); 4068 } 4069 4070 /** 4071 * @return true if this adapter supports WifiScanner APIs 4072 * @hide 4073 */ 4074 @SystemApi isWifiScannerSupported()4075 public boolean isWifiScannerSupported() { 4076 return isFeatureSupported(WIFI_FEATURE_SCANNER); 4077 } 4078 4079 /** 4080 * @return true if this adapter supports Neighbour Awareness Network APIs 4081 * @hide 4082 */ isWifiAwareSupported()4083 public boolean isWifiAwareSupported() { 4084 return isFeatureSupported(WIFI_FEATURE_AWARE); 4085 } 4086 4087 /** 4088 * Query whether or not the device supports Station (STA) + Access point (AP) concurrency. 4089 * 4090 * @return true if this device supports STA + AP concurrency, false otherwise. 4091 */ isStaApConcurrencySupported()4092 public boolean isStaApConcurrencySupported() { 4093 return isFeatureSupported(WIFI_FEATURE_AP_STA); 4094 } 4095 4096 /** 4097 * Query whether or not the device supports concurrent station (STA) connections for local-only 4098 * connections using {@link WifiNetworkSpecifier}. 4099 * 4100 * @return true if this device supports multiple STA concurrency for this use-case, false 4101 * otherwise. 4102 */ isStaConcurrencyForLocalOnlyConnectionsSupported()4103 public boolean isStaConcurrencyForLocalOnlyConnectionsSupported() { 4104 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY); 4105 } 4106 4107 /** 4108 * Query whether or not the device supports concurrent station (STA) connections for 4109 * make-before-break wifi to wifi switching. 4110 * 4111 * Note: This is an internal feature which is not available to apps. 4112 * 4113 * @return true if this device supports multiple STA concurrency for this use-case, false 4114 * otherwise. 4115 */ isMakeBeforeBreakWifiSwitchingSupported()4116 public boolean isMakeBeforeBreakWifiSwitchingSupported() { 4117 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_MBB); 4118 } 4119 4120 /** 4121 * Query whether or not the device supports concurrent station (STA) connections for multi 4122 * internet connections. 4123 * 4124 * @return true if this device supports multiple STA concurrency for this use-case, false 4125 * otherwise. 4126 */ 4127 @RequiresApi(Build.VERSION_CODES.TIRAMISU) isStaConcurrencyForMultiInternetSupported()4128 public boolean isStaConcurrencyForMultiInternetSupported() { 4129 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET); 4130 } 4131 4132 /** 4133 * Query whether or not the device supports concurrent station (STA) connections for restricted 4134 * connections using {@link WifiNetworkSuggestion.Builder#setOemPaid(boolean)} / 4135 * {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)}. 4136 * 4137 * @return true if this device supports multiple STA concurrency for this use-case, false 4138 * otherwise. 4139 * @hide 4140 */ 4141 @SystemApi isStaConcurrencyForRestrictedConnectionsSupported()4142 public boolean isStaConcurrencyForRestrictedConnectionsSupported() { 4143 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED); 4144 } 4145 4146 /** 4147 * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)} 4148 * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT} and 4149 * {@link android.content.pm.PackageManager#FEATURE_WIFI_AWARE}. 4150 * 4151 * @return true if this adapter supports Device-to-device RTT 4152 * @hide 4153 */ 4154 @Deprecated 4155 @SystemApi isDeviceToDeviceRttSupported()4156 public boolean isDeviceToDeviceRttSupported() { 4157 return isFeatureSupported(WIFI_FEATURE_D2D_RTT); 4158 } 4159 4160 /** 4161 * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)} 4162 * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT}. 4163 * 4164 * @return true if this adapter supports Device-to-AP RTT 4165 */ 4166 @Deprecated isDeviceToApRttSupported()4167 public boolean isDeviceToApRttSupported() { 4168 return isFeatureSupported(WIFI_FEATURE_D2AP_RTT); 4169 } 4170 4171 /** 4172 * @return true if this adapter supports offloaded connectivity scan 4173 */ isPreferredNetworkOffloadSupported()4174 public boolean isPreferredNetworkOffloadSupported() { 4175 try { 4176 return mService.isPnoSupported(); 4177 } catch (RemoteException e) { 4178 throw e.rethrowFromSystemServer(); 4179 } 4180 } 4181 4182 /** 4183 * @return true if this adapter supports Tunnel Directed Link Setup 4184 */ isTdlsSupported()4185 public boolean isTdlsSupported() { 4186 return isFeatureSupported(WIFI_FEATURE_TDLS); 4187 } 4188 4189 /** 4190 * @return true if this adapter supports Off Channel Tunnel Directed Link Setup 4191 * @hide 4192 */ isOffChannelTdlsSupported()4193 public boolean isOffChannelTdlsSupported() { 4194 return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL); 4195 } 4196 4197 /** 4198 * @return true if this adapter supports advanced power/performance counters 4199 */ isEnhancedPowerReportingSupported()4200 public boolean isEnhancedPowerReportingSupported() { 4201 return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS); 4202 } 4203 4204 /** 4205 * @return true if this device supports connected MAC randomization. 4206 * @hide 4207 */ 4208 @SystemApi isConnectedMacRandomizationSupported()4209 public boolean isConnectedMacRandomizationSupported() { 4210 return isFeatureSupported(WIFI_FEATURE_CONNECTED_RAND_MAC); 4211 } 4212 4213 /** 4214 * @return true if this device supports AP MAC randomization. 4215 * @hide 4216 */ 4217 @SystemApi isApMacRandomizationSupported()4218 public boolean isApMacRandomizationSupported() { 4219 return isFeatureSupported(WIFI_FEATURE_AP_RAND_MAC); 4220 } 4221 4222 /** 4223 * @return true if this device supports Low latency mode. 4224 * @hide 4225 */ 4226 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 4227 @SystemApi isLowLatencyModeSupported()4228 public boolean isLowLatencyModeSupported() { 4229 return isFeatureSupported(WIFI_FEATURE_LOW_LATENCY); 4230 } 4231 4232 /** 4233 * Check if the chipset supports 2.4GHz band. 4234 * @return {@code true} if supported, {@code false} otherwise. 4235 */ is24GHzBandSupported()4236 public boolean is24GHzBandSupported() { 4237 try { 4238 return mService.is24GHzBandSupported(); 4239 } catch (RemoteException e) { 4240 throw e.rethrowFromSystemServer(); 4241 } 4242 } 4243 4244 /** 4245 * Check if the chipset supports 5GHz band. 4246 * @return {@code true} if supported, {@code false} otherwise. 4247 */ is5GHzBandSupported()4248 public boolean is5GHzBandSupported() { 4249 try { 4250 return mService.is5GHzBandSupported(); 4251 } catch (RemoteException e) { 4252 throw e.rethrowFromSystemServer(); 4253 } 4254 } 4255 4256 /** 4257 * Check if the chipset supports the 60GHz frequency band. 4258 * 4259 * @return {@code true} if supported, {@code false} otherwise. 4260 */ 4261 @RequiresApi(Build.VERSION_CODES.S) is60GHzBandSupported()4262 public boolean is60GHzBandSupported() { 4263 try { 4264 return mService.is60GHzBandSupported(); 4265 } catch (RemoteException e) { 4266 throw e.rethrowFromSystemServer(); 4267 } 4268 } 4269 4270 /** 4271 * Check if the chipset supports 6GHz band. 4272 * @return {@code true} if supported, {@code false} otherwise. 4273 */ is6GHzBandSupported()4274 public boolean is6GHzBandSupported() { 4275 try { 4276 return mService.is6GHzBandSupported(); 4277 } catch (RemoteException e) { 4278 throw e.rethrowFromSystemServer(); 4279 } 4280 } 4281 4282 /** 4283 * Check if the chipset supports a certain Wi-Fi standard. 4284 * @param standard the IEEE 802.11 standard to check on. 4285 * valid values from {@link ScanResult}'s {@code WIFI_STANDARD_} 4286 * @return {@code true} if supported, {@code false} otherwise. 4287 */ isWifiStandardSupported(@ifiAnnotations.WifiStandard int standard)4288 public boolean isWifiStandardSupported(@WifiAnnotations.WifiStandard int standard) { 4289 try { 4290 return mService.isWifiStandardSupported(standard); 4291 } catch (RemoteException e) { 4292 throw e.rethrowFromSystemServer(); 4293 } 4294 } 4295 4296 /** 4297 * Query whether or not the device supports concurrency of Station (STA) + multiple access 4298 * points (AP) (where the APs bridged together). 4299 * 4300 * @return true if this device supports concurrency of STA + multiple APs which are bridged 4301 * together, false otherwise. 4302 */ isStaBridgedApConcurrencySupported()4303 public boolean isStaBridgedApConcurrencySupported() { 4304 return isFeatureSupported(WIFI_FEATURE_STA_BRIDGED_AP); 4305 } 4306 4307 /** 4308 * Query whether or not the device supports multiple Access point (AP) which are bridged 4309 * together. 4310 * 4311 * @return true if this device supports concurrency of multiple AP which bridged together, 4312 * false otherwise. 4313 */ isBridgedApConcurrencySupported()4314 public boolean isBridgedApConcurrencySupported() { 4315 return isFeatureSupported(WIFI_FEATURE_BRIDGED_AP); 4316 } 4317 4318 /** 4319 * @return true if this devices supports device-to-device (D2d) Wi-Fi use-cases 4320 * such as Wi-Fi Direct when infra station (STA) is disabled. 4321 */ 4322 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) isD2dSupportedWhenInfraStaDisabled()4323 public boolean isD2dSupportedWhenInfraStaDisabled() { 4324 return isFeatureSupported(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED); 4325 } 4326 4327 /** 4328 * Interface for Wi-Fi activity energy info listener. Should be implemented by applications and 4329 * set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}. 4330 * 4331 * @hide 4332 */ 4333 @SystemApi 4334 public interface OnWifiActivityEnergyInfoListener { 4335 /** 4336 * Called when Wi-Fi activity energy info is available. 4337 * Note: this listener is triggered at most once for each call to 4338 * {@link #getWifiActivityEnergyInfoAsync}. 4339 * 4340 * @param info the latest {@link WifiActivityEnergyInfo}, or null if unavailable. 4341 */ onWifiActivityEnergyInfo(@ullable WifiActivityEnergyInfo info)4342 void onWifiActivityEnergyInfo(@Nullable WifiActivityEnergyInfo info); 4343 } 4344 4345 private static class OnWifiActivityEnergyInfoProxy 4346 extends IOnWifiActivityEnergyInfoListener.Stub { 4347 private final Object mLock = new Object(); 4348 @Nullable @GuardedBy("mLock") private Executor mExecutor; 4349 @Nullable @GuardedBy("mLock") private OnWifiActivityEnergyInfoListener mListener; 4350 OnWifiActivityEnergyInfoProxy(Executor executor, OnWifiActivityEnergyInfoListener listener)4351 OnWifiActivityEnergyInfoProxy(Executor executor, 4352 OnWifiActivityEnergyInfoListener listener) { 4353 mExecutor = executor; 4354 mListener = listener; 4355 } 4356 4357 @Override onWifiActivityEnergyInfo(WifiActivityEnergyInfo info)4358 public void onWifiActivityEnergyInfo(WifiActivityEnergyInfo info) { 4359 Executor executor; 4360 OnWifiActivityEnergyInfoListener listener; 4361 synchronized (mLock) { 4362 if (mExecutor == null || mListener == null) { 4363 return; 4364 } 4365 executor = mExecutor; 4366 listener = mListener; 4367 // null out to allow garbage collection, prevent triggering listener more than once 4368 mExecutor = null; 4369 mListener = null; 4370 } 4371 Binder.clearCallingIdentity(); 4372 executor.execute(() -> listener.onWifiActivityEnergyInfo(info)); 4373 } 4374 } 4375 4376 /** 4377 * Request to get the current {@link WifiActivityEnergyInfo} asynchronously. 4378 * Note: This method will return null if {@link #isEnhancedPowerReportingSupported()} returns 4379 * false. 4380 * 4381 * @param executor the executor that the listener will be invoked on 4382 * @param listener the listener that will receive the {@link WifiActivityEnergyInfo} object 4383 * when it becomes available. The listener will be triggered at most once for 4384 * each call to this method. 4385 * 4386 * @hide 4387 */ 4388 @SystemApi 4389 @RequiresPermission(ACCESS_WIFI_STATE) getWifiActivityEnergyInfoAsync( @onNull @allbackExecutor Executor executor, @NonNull OnWifiActivityEnergyInfoListener listener)4390 public void getWifiActivityEnergyInfoAsync( 4391 @NonNull @CallbackExecutor Executor executor, 4392 @NonNull OnWifiActivityEnergyInfoListener listener) { 4393 Objects.requireNonNull(executor, "executor cannot be null"); 4394 Objects.requireNonNull(listener, "listener cannot be null"); 4395 try { 4396 mService.getWifiActivityEnergyInfoAsync( 4397 new OnWifiActivityEnergyInfoProxy(executor, listener)); 4398 } catch (RemoteException e) { 4399 throw e.rethrowFromSystemServer(); 4400 } 4401 } 4402 4403 /** 4404 * Request a scan for access points. Returns immediately. The availability 4405 * of the results is made known later by means of an asynchronous event sent 4406 * on completion of the scan. 4407 * <p> 4408 * To initiate a Wi-Fi scan, declare the 4409 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} 4410 * permission in the manifest, and perform these steps: 4411 * </p> 4412 * <ol style="1"> 4413 * <li>Invoke the following method: 4414 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).startScan()}</li> 4415 * <li> 4416 * Register a BroadcastReceiver to listen to 4417 * {@code SCAN_RESULTS_AVAILABLE_ACTION}.</li> 4418 * <li>When a broadcast is received, call: 4419 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).getScanResults()}</li> 4420 * </ol> 4421 * @return {@code true} if the operation succeeded, i.e., the scan was initiated. 4422 * @deprecated The ability for apps to trigger scan requests will be removed in a future 4423 * release. 4424 */ 4425 @Deprecated startScan()4426 public boolean startScan() { 4427 return startScan(null); 4428 } 4429 4430 /** @hide */ 4431 @SystemApi 4432 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) startScan(WorkSource workSource)4433 public boolean startScan(WorkSource workSource) { 4434 try { 4435 String packageName = mContext.getOpPackageName(); 4436 String attributionTag = mContext.getAttributionTag(); 4437 return mService.startScan(packageName, attributionTag); 4438 } catch (RemoteException e) { 4439 throw e.rethrowFromSystemServer(); 4440 } 4441 } 4442 4443 /** 4444 * WPS has been deprecated from Client mode operation. 4445 * 4446 * @return null 4447 * @hide 4448 * @deprecated This API is deprecated 4449 */ getCurrentNetworkWpsNfcConfigurationToken()4450 public String getCurrentNetworkWpsNfcConfigurationToken() { 4451 return null; 4452 } 4453 4454 /** 4455 * Return dynamic information about the current Wi-Fi connection, if any is active. 4456 * <p> 4457 * 4458 * @return the Wi-Fi information, contained in {@link WifiInfo}. 4459 * 4460 * @deprecated Starting with {@link Build.VERSION_CODES#S}, WifiInfo retrieval is moved to 4461 * {@link ConnectivityManager} API surface. WifiInfo is attached in 4462 * {@link NetworkCapabilities#getTransportInfo()} which is available via callback in 4463 * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} or on-demand from 4464 * {@link ConnectivityManager#getNetworkCapabilities(Network)}. 4465 * 4466 *</p> 4467 * Usage example: 4468 * <pre> 4469 * final NetworkRequest request = 4470 * new NetworkRequest.Builder() 4471 * .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 4472 * .build(); 4473 * final ConnectivityManager connectivityManager = 4474 * context.getSystemService(ConnectivityManager.class); 4475 * final NetworkCallback networkCallback = new NetworkCallback() { 4476 * ... 4477 * @Override 4478 * void onAvailable(Network network) {} 4479 * 4480 * @Override 4481 * void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { 4482 * WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo(); 4483 * } 4484 * // etc. 4485 * }; 4486 * connectivityManager.requestNetwork(request, networkCallback); // For request 4487 * connectivityManager.registerNetworkCallback(request, networkCallback); // For listen 4488 * </pre> 4489 * <p> 4490 * <b>Compatibility Notes:</b> 4491 * <li>Apps can continue using this API, however newer features 4492 * such as ability to mask out location sensitive data in WifiInfo will not be supported 4493 * via this API. </li> 4494 * <li>On devices supporting concurrent connections (indicated via 4495 * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc) this API will return 4496 * the details of the internet providing connection (if any) to all apps, except for the apps 4497 * that triggered the creation of the concurrent connection. For such apps, this API will return 4498 * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will 4499 * trigger a concurrent connection on supported devices and hence this API will provide 4500 * details of their peer to peer connection (not the internet providing connection). This 4501 * is to maintain backwards compatibility with behavior on single STA devices.</li> 4502 * </p> 4503 */ 4504 @Deprecated 4505 @RequiresPermission(allOf = {ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION}, conditional = true) getConnectionInfo()4506 public WifiInfo getConnectionInfo() { 4507 try { 4508 return mService.getConnectionInfo(mContext.getOpPackageName(), 4509 mContext.getAttributionTag()); 4510 } catch (RemoteException e) { 4511 throw e.rethrowFromSystemServer(); 4512 } 4513 } 4514 4515 /** 4516 * Return the results of the latest access point scan. 4517 * @return the list of access points found in the most recent scan. An app must hold 4518 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission 4519 * and {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission 4520 * in order to get valid results. 4521 * 4522 * <p> 4523 * When an Access Point’s beacon or probe response includes a Multi-BSSID Element, the 4524 * returned scan results should include separate scan result for each BSSID within the 4525 * Multi-BSSID Information Element. This includes both transmitted and non-transmitted BSSIDs. 4526 * Original Multi-BSSID Element will be included in the Information Elements attached to 4527 * each of the scan results. 4528 * Note: This is the expected behavior for devices supporting 11ax (WiFi-6) and above, and an 4529 * optional requirement for devices running with older WiFi generations. 4530 * </p> 4531 */ 4532 @RequiresPermission(allOf = {ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION}) getScanResults()4533 public List<ScanResult> getScanResults() { 4534 try { 4535 ParceledListSlice<ScanResult> parceledList = mService 4536 .getScanResults(mContext.getOpPackageName(), mContext.getAttributionTag()); 4537 if (parceledList == null) { 4538 return Collections.emptyList(); 4539 } 4540 return parceledList.getList(); 4541 } catch (RemoteException e) { 4542 throw e.rethrowFromSystemServer(); 4543 } 4544 } 4545 4546 /** 4547 * Get the filtered ScanResults which match the network configurations specified by the 4548 * {@code networkSuggestionsToMatch}. Suggestions which use {@link WifiConfiguration} use 4549 * SSID and the security type to match. Suggestions which use {@link PasspointConfigration} 4550 * use the matching rules of Hotspot 2.0. 4551 * @param networkSuggestionsToMatch The list of {@link WifiNetworkSuggestion} to match against. 4552 * These may or may not be suggestions which are installed on the device. 4553 * @param scanResults The scan results to be filtered. Optional - if not provided(empty list), 4554 * the Wi-Fi service will use the most recent scan results which the system has. 4555 * @return The map of {@link WifiNetworkSuggestion} to the list of {@link ScanResult} 4556 * corresponding to networks which match them. 4557 * @hide 4558 */ 4559 @SystemApi 4560 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) 4561 @NonNull getMatchingScanResults( @onNull List<WifiNetworkSuggestion> networkSuggestionsToMatch, @Nullable List<ScanResult> scanResults)4562 public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( 4563 @NonNull List<WifiNetworkSuggestion> networkSuggestionsToMatch, 4564 @Nullable List<ScanResult> scanResults) { 4565 if (networkSuggestionsToMatch == null) { 4566 throw new IllegalArgumentException("networkSuggestions must not be null."); 4567 } 4568 try { 4569 return mService.getMatchingScanResults( 4570 networkSuggestionsToMatch, scanResults, 4571 mContext.getOpPackageName(), mContext.getAttributionTag()); 4572 } catch (RemoteException e) { 4573 throw e.rethrowFromSystemServer(); 4574 } 4575 } 4576 4577 /** 4578 * Set if scanning is always available. 4579 * 4580 * If set to {@code true}, apps can issue {@link #startScan} and fetch scan results 4581 * even when Wi-Fi is turned off. 4582 * 4583 * @param isAvailable true to enable, false to disable. 4584 * @hide 4585 * @see #isScanAlwaysAvailable() 4586 */ 4587 @SystemApi 4588 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setScanAlwaysAvailable(boolean isAvailable)4589 public void setScanAlwaysAvailable(boolean isAvailable) { 4590 try { 4591 mService.setScanAlwaysAvailable(isAvailable, mContext.getOpPackageName()); 4592 } catch (RemoteException e) { 4593 throw e.rethrowFromSystemServer(); 4594 } 4595 } 4596 4597 /** 4598 * Check if scanning is always available. 4599 * 4600 * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results 4601 * even when Wi-Fi is turned off. 4602 * 4603 * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}. 4604 * @deprecated The ability for apps to trigger scan requests will be removed in a future 4605 * release. 4606 */ 4607 @Deprecated isScanAlwaysAvailable()4608 public boolean isScanAlwaysAvailable() { 4609 try { 4610 return mService.isScanAlwaysAvailable(); 4611 } catch (RemoteException e) { 4612 throw e.rethrowFromSystemServer(); 4613 } 4614 } 4615 4616 /** 4617 * Get channel data such as the number of APs found on each channel from the most recent scan. 4618 * App requires {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} 4619 * 4620 * @param executor The executor on which callback will be invoked. 4621 * @param resultsCallback A callback that will return {@code List<Bundle>} containing channel 4622 * data such as the number of APs found on each channel. 4623 * {@link WifiManager#CHANNEL_DATA_KEY_FREQUENCY_MHZ} and 4624 * {@link WifiManager#CHANNEL_DATA_KEY_NUM_AP} are used to get 4625 * the frequency (Mhz) and number of APs. 4626 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 4627 * @throws SecurityException if the caller does not have permission. 4628 * @throws NullPointerException if the caller provided invalid inputs. 4629 */ 4630 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 4631 @RequiresPermission(NEARBY_WIFI_DEVICES) getChannelData(@onNull @allbackExecutor Executor executor, @NonNull Consumer<List<Bundle>> resultsCallback)4632 public void getChannelData(@NonNull @CallbackExecutor Executor executor, 4633 @NonNull Consumer<List<Bundle>> resultsCallback) { 4634 Objects.requireNonNull(executor, "executor cannot be null"); 4635 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 4636 try { 4637 Bundle extras = new Bundle(); 4638 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 4639 mContext.getAttributionSource()); 4640 mService.getChannelData(new IListListener.Stub() { 4641 @Override 4642 public void onResult(List value) { 4643 Binder.clearCallingIdentity(); 4644 executor.execute(() -> { 4645 resultsCallback.accept(value); 4646 }); 4647 } 4648 }, mContext.getOpPackageName(), extras); 4649 } catch (RemoteException e) { 4650 throw e.rethrowFromSystemServer(); 4651 } 4652 } 4653 4654 /** 4655 * Tell the device to persist the current list of configured networks. 4656 * <p> 4657 * Note: It is possible for this method to change the network IDs of 4658 * existing networks. You should assume the network IDs can be different 4659 * after calling this method. 4660 * 4661 * @return {@code false}. 4662 * @deprecated There is no need to call this method - 4663 * {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)} 4664 * and {@link #removeNetwork(int)} already persist the configurations automatically. 4665 */ 4666 @Deprecated saveConfiguration()4667 public boolean saveConfiguration() { 4668 return false; 4669 } 4670 4671 /** 4672 * Helper class to support driver country code changed listener. 4673 */ 4674 private static class OnDriverCountryCodeChangedProxy 4675 extends IOnWifiDriverCountryCodeChangedListener.Stub { 4676 4677 @NonNull private Executor mExecutor; 4678 @NonNull private ActiveCountryCodeChangedCallback mCallback; 4679 OnDriverCountryCodeChangedProxy(@onNull Executor executor, @NonNull ActiveCountryCodeChangedCallback callback)4680 OnDriverCountryCodeChangedProxy(@NonNull Executor executor, 4681 @NonNull ActiveCountryCodeChangedCallback callback) { 4682 Objects.requireNonNull(executor); 4683 Objects.requireNonNull(callback); 4684 mExecutor = executor; 4685 mCallback = callback; 4686 } 4687 4688 @Override onDriverCountryCodeChanged(String countryCode)4689 public void onDriverCountryCodeChanged(String countryCode) { 4690 Log.i(TAG, "OnDriverCountryCodeChangedProxy: receive onDriverCountryCodeChanged: " 4691 + countryCode); 4692 Binder.clearCallingIdentity(); 4693 if (countryCode != null) { 4694 mExecutor.execute(() -> mCallback.onActiveCountryCodeChanged(countryCode)); 4695 } else { 4696 mExecutor.execute(() -> mCallback.onCountryCodeInactive()); 4697 } 4698 } 4699 } 4700 4701 /** 4702 * Interface used to listen the active country code changed event. 4703 * @hide 4704 */ 4705 @SystemApi 4706 public interface ActiveCountryCodeChangedCallback { 4707 /** 4708 * Called when the country code used by the Wi-Fi subsystem has changed. 4709 * 4710 * @param countryCode An ISO-3166-alpha2 country code which is 2-Character alphanumeric. 4711 */ onActiveCountryCodeChanged(@onNull String countryCode)4712 void onActiveCountryCodeChanged(@NonNull String countryCode); 4713 4714 /** 4715 * Called when the Wi-Fi subsystem does not have an active country code. 4716 * This can happen when Wi-Fi is disabled. 4717 */ onCountryCodeInactive()4718 void onCountryCodeInactive(); 4719 } 4720 4721 /** 4722 * Add the provided callback for the active country code changed event. 4723 * Caller will receive either 4724 * {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)} 4725 * or {@link WifiManager.ActiveCountryCodeChangedCallback#onCountryCodeInactive()} 4726 * on registration. 4727 * 4728 * Note: When the global location setting is off or the caller does not have runtime location 4729 * permission, caller will not receive the callback even if caller register callback succeeded. 4730 * 4731 * 4732 * Caller can remove a previously registered callback using 4733 * {@link WifiManager#unregisterActiveCountryCodeChangedCallback( 4734 * ActiveCountryCodeChangedCallback)}. 4735 * 4736 * <p> 4737 * Note: 4738 * The value provided by 4739 * {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)} 4740 * may be different from the returned value from {@link WifiManager#getCountryCode()} even if 4741 * the Wi-Fi subsystem is active. See: {@link WifiManager#getCountryCode()} for details. 4742 * </p> 4743 * 4744 * @param executor The Executor on which to execute the callbacks. 4745 * @param callback callback for the driver country code changed events. 4746 * @hide 4747 */ 4748 @SystemApi 4749 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 4750 @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) registerActiveCountryCodeChangedCallback( @onNull @allbackExecutor Executor executor, @NonNull ActiveCountryCodeChangedCallback callback)4751 public void registerActiveCountryCodeChangedCallback( 4752 @NonNull @CallbackExecutor Executor executor, 4753 @NonNull ActiveCountryCodeChangedCallback callback) { 4754 if (!SdkLevel.isAtLeastT()) { 4755 throw new UnsupportedOperationException(); 4756 } 4757 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 4758 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 4759 if (mVerboseLoggingEnabled) { 4760 Log.d(TAG, "registerActiveCountryCodeChangedCallback: callback=" + callback 4761 + ", executor=" + executor); 4762 } 4763 final int callbackIdentifier = System.identityHashCode(callback); 4764 synchronized (sActiveCountryCodeChangedCallbackMap) { 4765 try { 4766 IOnWifiDriverCountryCodeChangedListener.Stub binderListener = 4767 new OnDriverCountryCodeChangedProxy(executor, callback); 4768 sActiveCountryCodeChangedCallbackMap.put(callbackIdentifier, 4769 binderListener); 4770 mService.registerDriverCountryCodeChangedListener(binderListener, 4771 mContext.getOpPackageName(), mContext.getAttributionTag()); 4772 } catch (RemoteException e) { 4773 sActiveCountryCodeChangedCallbackMap.remove(callbackIdentifier); 4774 throw e.rethrowFromSystemServer(); 4775 } 4776 } 4777 } 4778 4779 /** 4780 * Allow callers to remove a previously registered listener. After calling this method, 4781 * applications will no longer receive the active country code changed events through that 4782 * callback. 4783 * 4784 * @param callback Callback to remove the active country code changed events. 4785 * 4786 * @hide 4787 */ 4788 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 4789 @SystemApi unregisterActiveCountryCodeChangedCallback( @onNull ActiveCountryCodeChangedCallback callback)4790 public void unregisterActiveCountryCodeChangedCallback( 4791 @NonNull ActiveCountryCodeChangedCallback callback) { 4792 if (!SdkLevel.isAtLeastT()) { 4793 throw new UnsupportedOperationException(); 4794 } 4795 if (callback == null) throw new IllegalArgumentException("Callback cannot be null"); 4796 if (mVerboseLoggingEnabled) { 4797 Log.d(TAG, "unregisterActiveCountryCodeChangedCallback: callback=" + callback); 4798 } 4799 final int callbackIdentifier = System.identityHashCode(callback); 4800 synchronized (sActiveCountryCodeChangedCallbackMap) { 4801 try { 4802 if (!sActiveCountryCodeChangedCallbackMap.contains(callbackIdentifier)) { 4803 Log.w(TAG, "Unknown external listener " + callbackIdentifier); 4804 return; 4805 } 4806 mService.unregisterDriverCountryCodeChangedListener( 4807 sActiveCountryCodeChangedCallbackMap.get(callbackIdentifier)); 4808 } catch (RemoteException e) { 4809 throw e.rethrowFromSystemServer(); 4810 } finally { 4811 sActiveCountryCodeChangedCallbackMap.remove(callbackIdentifier); 4812 } 4813 } 4814 } 4815 4816 /** 4817 * Interface used to listen to changes in current network state. 4818 * @hide 4819 */ 4820 @SystemApi 4821 public interface WifiNetworkStateChangedListener { 4822 /** @hide */ 4823 @Retention(RetentionPolicy.SOURCE) 4824 @IntDef(prefix = {"WIFI_ROLE_CLIENT_"}, value = { 4825 WIFI_ROLE_CLIENT_PRIMARY, 4826 WIFI_ROLE_CLIENT_SECONDARY_INTERNET, 4827 WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY 4828 }) 4829 @interface WifiClientModeRole {} 4830 4831 /** 4832 * A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}. 4833 * Represents the primary Client Mode Manager which is mostly used for internet, but could 4834 * also be used for other use-cases such as local only connections. 4835 **/ 4836 int WIFI_ROLE_CLIENT_PRIMARY = 1; 4837 /** 4838 * A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}. 4839 * Represents a Client Mode Manager dedicated for the secondary internet use-case. 4840 **/ 4841 int WIFI_ROLE_CLIENT_SECONDARY_INTERNET = 2; 4842 /** 4843 * A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}. 4844 * Represents a Client Mode Manager dedicated for the local only connection use-case. 4845 **/ 4846 int WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY = 3; 4847 4848 /** @hide */ 4849 @Retention(RetentionPolicy.SOURCE) 4850 @IntDef(prefix = {"WIFI_NETWORK_STATUS_"}, value = { 4851 WIFI_NETWORK_STATUS_IDLE, 4852 WIFI_NETWORK_STATUS_SCANNING, 4853 WIFI_NETWORK_STATUS_CONNECTING, 4854 WIFI_NETWORK_STATUS_AUTHENTICATING, 4855 WIFI_NETWORK_STATUS_OBTAINING_IPADDR, 4856 WIFI_NETWORK_STATUS_CONNECTED, 4857 WIFI_NETWORK_STATUS_DISCONNECTED, 4858 WIFI_NETWORK_STATUS_FAILED 4859 }) 4860 @interface WifiNetworkState {} 4861 4862 /** 4863 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4864 * Supplicant is in uninitialized state. 4865 **/ 4866 int WIFI_NETWORK_STATUS_IDLE = 1; 4867 /** 4868 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4869 * Supplicant is scanning. 4870 **/ 4871 int WIFI_NETWORK_STATUS_SCANNING = 2; 4872 /** 4873 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4874 * L2 connection is in progress. 4875 **/ 4876 int WIFI_NETWORK_STATUS_CONNECTING = 3; 4877 /** 4878 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4879 * L2 connection 4 way handshake. 4880 **/ 4881 int WIFI_NETWORK_STATUS_AUTHENTICATING = 4; 4882 /** 4883 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4884 * L2 connection complete. Obtaining IP address. 4885 **/ 4886 int WIFI_NETWORK_STATUS_OBTAINING_IPADDR = 5; 4887 /** 4888 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4889 * L3 connection is complete. 4890 **/ 4891 int WIFI_NETWORK_STATUS_CONNECTED = 6; 4892 /** 4893 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4894 * Network disconnected. 4895 **/ 4896 int WIFI_NETWORK_STATUS_DISCONNECTED = 7; 4897 /** 4898 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4899 * A pseudo-state that should normally never be seen. 4900 **/ 4901 int WIFI_NETWORK_STATUS_FAILED = 8; 4902 4903 4904 /** 4905 * Provides network state changes per client mode role. 4906 * @param cmmRole the role of the wifi client mode manager having the state change. 4907 * One of {@link WifiClientModeRole}. 4908 * @param state the wifi network state specified by one of {@link WifiNetworkState}. 4909 */ onWifiNetworkStateChanged(@ifiClientModeRole int cmmRole, @WifiNetworkState int state)4910 void onWifiNetworkStateChanged(@WifiClientModeRole int cmmRole, 4911 @WifiNetworkState int state); 4912 } 4913 4914 /** 4915 * Helper class to support wifi network state changed listener. 4916 */ 4917 private static class OnWifiNetworkStateChangedProxy 4918 extends IWifiNetworkStateChangedListener.Stub { 4919 4920 @NonNull private Executor mExecutor; 4921 @NonNull private WifiNetworkStateChangedListener mListener; 4922 OnWifiNetworkStateChangedProxy(@onNull Executor executor, @NonNull WifiNetworkStateChangedListener listener)4923 OnWifiNetworkStateChangedProxy(@NonNull Executor executor, 4924 @NonNull WifiNetworkStateChangedListener listener) { 4925 Objects.requireNonNull(executor); 4926 Objects.requireNonNull(listener); 4927 mExecutor = executor; 4928 mListener = listener; 4929 } 4930 4931 @Override onWifiNetworkStateChanged(int cmmRole, int state)4932 public void onWifiNetworkStateChanged(int cmmRole, int state) { 4933 Log.i(TAG, "OnWifiNetworkStateChangedProxy: onWifiNetworkStateChanged: " 4934 + cmmRole + ", " + state); 4935 Binder.clearCallingIdentity(); 4936 mExecutor.execute(() -> mListener.onWifiNetworkStateChanged(cmmRole, state)); 4937 } 4938 } 4939 4940 /** 4941 * Add a listener to listen to Wi-Fi network state changes on available client mode roles 4942 * specified in {@link WifiNetworkStateChangedListener.WifiClientModeRole}. 4943 * When wifi state changes such as connected/disconnect happens, results will be delivered via 4944 * {@link WifiNetworkStateChangedListener#onWifiNetworkStateChanged(int, int)}. 4945 * 4946 * @param executor The Executor on which to execute the callbacks. 4947 * @param listener listener for the network status updates. 4948 * @throws SecurityException if the caller is missing required permissions. 4949 * @throws IllegalArgumentException if incorrect input arguments are provided. 4950 * @hide 4951 */ 4952 @SystemApi 4953 @RequiresPermission(Manifest.permission.NETWORK_SETTINGS) addWifiNetworkStateChangedListener(@onNull @allbackExecutor Executor executor, @NonNull WifiNetworkStateChangedListener listener)4954 public void addWifiNetworkStateChangedListener(@NonNull @CallbackExecutor Executor executor, 4955 @NonNull WifiNetworkStateChangedListener listener) { 4956 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 4957 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 4958 if (mVerboseLoggingEnabled) { 4959 Log.d(TAG, "addWifiNetworkStateChangedListener: listener=" + listener 4960 + ", executor=" + executor); 4961 } 4962 final int listenerIdentifier = System.identityHashCode(listener); 4963 synchronized (sOnWifiNetworkStateChangedListenerMap) { 4964 try { 4965 IWifiNetworkStateChangedListener.Stub listenerProxy = 4966 new OnWifiNetworkStateChangedProxy(executor, listener); 4967 sOnWifiNetworkStateChangedListenerMap.put(listenerIdentifier, 4968 listenerProxy); 4969 mService.addWifiNetworkStateChangedListener(listenerProxy); 4970 } catch (RemoteException e) { 4971 sOnWifiNetworkStateChangedListenerMap.remove(listenerIdentifier); 4972 throw e.rethrowFromSystemServer(); 4973 } 4974 } 4975 } 4976 4977 /** 4978 * Remove a listener added using 4979 * {@link #addWifiNetworkStateChangedListener(Executor, WifiNetworkStateChangedListener)}. 4980 * @param listener the listener to be removed. 4981 * @throws IllegalArgumentException if incorrect input arguments are provided. 4982 * @hide 4983 */ 4984 @SystemApi 4985 @RequiresApi(Build.VERSION_CODES.TIRAMISU) removeWifiNetworkStateChangedListener( @onNull WifiNetworkStateChangedListener listener)4986 public void removeWifiNetworkStateChangedListener( 4987 @NonNull WifiNetworkStateChangedListener listener) { 4988 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 4989 if (mVerboseLoggingEnabled) { 4990 Log.d(TAG, "removeWifiNetworkStateChangedListener: listener=" + listener); 4991 } 4992 final int listenerIdentifier = System.identityHashCode(listener); 4993 synchronized (sOnWifiNetworkStateChangedListenerMap) { 4994 try { 4995 if (!sOnWifiNetworkStateChangedListenerMap.contains(listenerIdentifier)) { 4996 Log.w(TAG, "Unknown external listener " + listenerIdentifier); 4997 return; 4998 } 4999 mService.removeWifiNetworkStateChangedListener( 5000 sOnWifiNetworkStateChangedListenerMap.get(listenerIdentifier)); 5001 } catch (RemoteException e) { 5002 throw e.rethrowFromSystemServer(); 5003 } finally { 5004 sOnWifiNetworkStateChangedListenerMap.remove(listenerIdentifier); 5005 } 5006 } 5007 } 5008 5009 /** 5010 * Get the country code as resolved by the Wi-Fi framework. 5011 * The Wi-Fi framework uses multiple sources to resolve a country code 5012 * - in order of priority (high to low): 5013 * 1. Override country code set by {@link WifiManager#setOverrideCountryCode(String)} 5014 * and cleared by {@link WifiManager#clearOverrideCountryCode()}. Typically only used 5015 * for testing. 5016 * 2. Country code supplied by the telephony module. Typically provided from the 5017 * current network or from emergency cell information. 5018 * 3. Country code supplied by the wifi driver module. (802.11d) 5019 * 4. Default country code set either via {@code ro.boot.wificountrycode} 5020 * or the {@link WifiManager#setDefaultCountryCode(String)}. 5021 * 5022 * <p> 5023 * Note: 5024 * This method returns the Country Code value used by the framework - even if not currently 5025 * used by the Wi-Fi subsystem. I.e. the returned value from this API may be different from the 5026 * value provided by 5027 * {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)}. 5028 * Such a difference may happen when there is an ongoing network connection (STA, AP, Direct, 5029 * or Aware) and the Wi-Fi subsystem does not support dynamic updates - at that point the 5030 * framework may defer setting the Country Code to the Wi-Fi subsystem. 5031 * </p> 5032 * @return the country code in ISO 3166 alpha-2 (2-letter) upper format, 5033 * or null if there is no country code configured. 5034 * 5035 * @hide 5036 */ 5037 @Nullable 5038 @SystemApi 5039 @RequiresPermission(anyOf = { 5040 android.Manifest.permission.NETWORK_SETTINGS, 5041 android.Manifest.permission.ACCESS_COARSE_LOCATION 5042 }) getCountryCode()5043 public String getCountryCode() { 5044 try { 5045 return mService.getCountryCode(mContext.getOpPackageName(), 5046 mContext.getAttributionTag()); 5047 } catch (RemoteException e) { 5048 throw e.rethrowFromSystemServer(); 5049 } 5050 } 5051 5052 /** 5053 * Set the override country code - may be used for testing. See the country code resolution 5054 * order and format in {@link #getCountryCode()}. 5055 * @param country A 2-Character alphanumeric country code. 5056 * @see #getCountryCode(). 5057 * 5058 * @hide 5059 */ 5060 @RequiresApi(Build.VERSION_CODES.S) 5061 @SystemApi 5062 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) setOverrideCountryCode(@onNull String country)5063 public void setOverrideCountryCode(@NonNull String country) { 5064 try { 5065 mService.setOverrideCountryCode(country); 5066 } catch (RemoteException e) { 5067 throw e.rethrowFromSystemServer(); 5068 } 5069 } 5070 5071 /** 5072 * This clears the override country code which was previously set by 5073 * {@link WifiManager#setOverrideCountryCode(String)} method. 5074 * @see #getCountryCode(). 5075 * 5076 * @hide 5077 */ 5078 @RequiresApi(Build.VERSION_CODES.S) 5079 @SystemApi 5080 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) clearOverrideCountryCode()5081 public void clearOverrideCountryCode() { 5082 try { 5083 mService.clearOverrideCountryCode(); 5084 } catch (RemoteException e) { 5085 throw e.rethrowFromSystemServer(); 5086 } 5087 } 5088 /** 5089 * Used to configure the default country code. See {@link #getCountryCode()} for resolution 5090 * method of the country code. 5091 * @param country A 2-character alphanumeric country code. 5092 * @see #getCountryCode(). 5093 * 5094 * @hide 5095 */ 5096 @RequiresApi(Build.VERSION_CODES.S) 5097 @SystemApi 5098 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) setDefaultCountryCode(@onNull String country)5099 public void setDefaultCountryCode(@NonNull String country) { 5100 try { 5101 mService.setDefaultCountryCode(country); 5102 } catch (RemoteException e) { 5103 throw e.rethrowFromSystemServer(); 5104 } 5105 } 5106 5107 /** 5108 * Return the DHCP-assigned addresses from the last successful DHCP request, 5109 * if any. 5110 * 5111 * @return the DHCP information 5112 * 5113 * @deprecated Use the methods on {@link android.net.LinkProperties} which can be obtained 5114 * either via {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)} or 5115 * {@link ConnectivityManager#getLinkProperties(Network)}. 5116 * 5117 * <p> 5118 * <b>Compatibility Notes:</b> 5119 * <li>On devices supporting concurrent connections (indicated via 5120 * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc), this API will return 5121 * the details of the internet providing connection (if any) to all apps, except for the apps 5122 * that triggered the creation of the concurrent connection. For such apps, this API will return 5123 * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will 5124 * trigger a concurrent connection on supported devices and hence this API will provide 5125 * details of their peer to peer connection (not the internet providing connection). This 5126 * is to maintain backwards compatibility with behavior on single STA devices.</li> 5127 * </p> 5128 */ 5129 @Deprecated getDhcpInfo()5130 public DhcpInfo getDhcpInfo() { 5131 try { 5132 return mService.getDhcpInfo(mContext.getOpPackageName()); 5133 } catch (RemoteException e) { 5134 throw e.rethrowFromSystemServer(); 5135 } 5136 } 5137 5138 /** 5139 * Enable or disable Wi-Fi. 5140 * <p> 5141 * Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE} 5142 * permission to toggle wifi. 5143 * 5144 * @param enabled {@code true} to enable, {@code false} to disable. 5145 * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is 5146 * either already in the requested state, or in progress toward the requested state. 5147 * @throws SecurityException if the caller is missing required permissions. 5148 * 5149 * @deprecated Starting with Build.VERSION_CODES#Q, applications are not allowed to 5150 * enable/disable Wi-Fi. 5151 * <b>Compatibility Note:</b> For applications targeting 5152 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 5153 * {@code false}. If apps are targeting an older SDK ({@link android.os.Build.VERSION_CODES#P} 5154 * or below), they can continue to use this API. 5155 * <p> 5156 * Deprecation Exemptions: 5157 * <ul> 5158 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 5159 * </ul> 5160 * 5161 * Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, DO/COPE may set 5162 * a user restriction (DISALLOW_CHANGE_WIFI_STATE) to only allow DO/PO to use this API. 5163 */ 5164 @Deprecated setWifiEnabled(boolean enabled)5165 public boolean setWifiEnabled(boolean enabled) { 5166 try { 5167 return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); 5168 } catch (RemoteException e) { 5169 throw e.rethrowFromSystemServer(); 5170 } 5171 } 5172 5173 /** 5174 * Abstract callback class for applications to receive updates about the Wi-Fi subsystem 5175 * restarting. The Wi-Fi subsystem can restart due to internal recovery mechanisms or via user 5176 * action. 5177 */ 5178 @RequiresApi(Build.VERSION_CODES.S) 5179 public abstract static class SubsystemRestartTrackingCallback { 5180 private final SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy mProxy; 5181 SubsystemRestartTrackingCallback()5182 public SubsystemRestartTrackingCallback() { 5183 mProxy = new SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy(); 5184 } 5185 5186 /*package*/ @NonNull getProxy()5187 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy getProxy() { 5188 return mProxy; 5189 } 5190 5191 /** 5192 * Indicates that the Wi-Fi subsystem is about to restart. 5193 */ onSubsystemRestarting()5194 public abstract void onSubsystemRestarting(); 5195 5196 /** 5197 * Indicates that the Wi-Fi subsystem has restarted. 5198 */ onSubsystemRestarted()5199 public abstract void onSubsystemRestarted(); 5200 5201 private static class SubsystemRestartCallbackProxy extends ISubsystemRestartCallback.Stub { 5202 private final Object mLock = new Object(); 5203 @Nullable 5204 @GuardedBy("mLock") 5205 private Executor mExecutor; 5206 @Nullable 5207 @GuardedBy("mLock") 5208 private SubsystemRestartTrackingCallback mCallback; 5209 SubsystemRestartCallbackProxy()5210 SubsystemRestartCallbackProxy() { 5211 mExecutor = null; 5212 mCallback = null; 5213 } 5214 initProxy(@onNull Executor executor, @NonNull SubsystemRestartTrackingCallback callback)5215 /*package*/ void initProxy(@NonNull Executor executor, 5216 @NonNull SubsystemRestartTrackingCallback callback) { 5217 synchronized (mLock) { 5218 mExecutor = executor; 5219 mCallback = callback; 5220 } 5221 } 5222 cleanUpProxy()5223 /*package*/ void cleanUpProxy() { 5224 synchronized (mLock) { 5225 mExecutor = null; 5226 mCallback = null; 5227 } 5228 } 5229 5230 @Override onSubsystemRestarting()5231 public void onSubsystemRestarting() { 5232 Executor executor; 5233 SubsystemRestartTrackingCallback callback; 5234 synchronized (mLock) { 5235 executor = mExecutor; 5236 callback = mCallback; 5237 } 5238 if (executor == null || callback == null) { 5239 return; 5240 } 5241 Binder.clearCallingIdentity(); 5242 executor.execute(callback::onSubsystemRestarting); 5243 } 5244 5245 @Override onSubsystemRestarted()5246 public void onSubsystemRestarted() { 5247 Executor executor; 5248 SubsystemRestartTrackingCallback callback; 5249 synchronized (mLock) { 5250 executor = mExecutor; 5251 callback = mCallback; 5252 } 5253 if (executor == null || callback == null) { 5254 return; 5255 } 5256 Binder.clearCallingIdentity(); 5257 executor.execute(callback::onSubsystemRestarted); 5258 } 5259 } 5260 } 5261 5262 /** 5263 * Registers a {@link SubsystemRestartTrackingCallback} to listen to Wi-Fi subsystem restarts. 5264 * The subsystem may restart due to internal recovery mechanisms or via user action. 5265 * 5266 * @see #unregisterSubsystemRestartTrackingCallback(SubsystemRestartTrackingCallback) 5267 * 5268 * @param executor Executor to execute callback on 5269 * @param callback {@link SubsystemRestartTrackingCallback} to register 5270 */ 5271 @RequiresApi(Build.VERSION_CODES.S) 5272 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) registerSubsystemRestartTrackingCallback( @onNull @allbackExecutor Executor executor, @NonNull SubsystemRestartTrackingCallback callback)5273 public void registerSubsystemRestartTrackingCallback( 5274 @NonNull @CallbackExecutor Executor executor, 5275 @NonNull SubsystemRestartTrackingCallback callback) { 5276 if (executor == null) throw new IllegalArgumentException("executor must not be null"); 5277 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5278 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy(); 5279 proxy.initProxy(executor, callback); 5280 try { 5281 mService.registerSubsystemRestartCallback(proxy); 5282 } catch (RemoteException e) { 5283 proxy.cleanUpProxy(); 5284 throw e.rethrowFromSystemServer(); 5285 } 5286 } 5287 5288 /** 5289 * Unregisters a {@link SubsystemRestartTrackingCallback} registered with 5290 * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)} 5291 * 5292 * @param callback {@link SubsystemRestartTrackingCallback} to unregister 5293 */ 5294 @RequiresApi(Build.VERSION_CODES.S) 5295 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) unregisterSubsystemRestartTrackingCallback( @onNull SubsystemRestartTrackingCallback callback)5296 public void unregisterSubsystemRestartTrackingCallback( 5297 @NonNull SubsystemRestartTrackingCallback callback) { 5298 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5299 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy(); 5300 try { 5301 mService.unregisterSubsystemRestartCallback(proxy); 5302 } catch (RemoteException e) { 5303 throw e.rethrowFromSystemServer(); 5304 } finally { 5305 proxy.cleanUpProxy(); 5306 } 5307 } 5308 5309 /** 5310 * Restart the Wi-Fi subsystem. 5311 * 5312 * Restarts the Wi-Fi subsystem - effectively disabling it and re-enabling it. All existing 5313 * Access Point (AP) associations are torn down, all Soft APs are disabled, Wi-Fi Direct and 5314 * Wi-Fi Aware are disabled. 5315 * 5316 * The state of the system after restart is not guaranteed to match its state before the API is 5317 * called - for instance the device may associate to a different Access Point (AP), and tethered 5318 * hotspots may or may not be restored. 5319 * 5320 * Use the 5321 * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)} 5322 * to track the operation. 5323 * 5324 * @hide 5325 */ 5326 @RequiresApi(Build.VERSION_CODES.S) 5327 @SystemApi 5328 @RequiresPermission(android.Manifest.permission.RESTART_WIFI_SUBSYSTEM) restartWifiSubsystem()5329 public void restartWifiSubsystem() { 5330 try { 5331 mService.restartWifiSubsystem(); 5332 } catch (RemoteException e) { 5333 throw e.rethrowFromSystemServer(); 5334 } 5335 } 5336 5337 /** 5338 * Gets the Wi-Fi enabled state. 5339 * @return One of {@link #WIFI_STATE_DISABLED}, 5340 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 5341 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 5342 * @see #isWifiEnabled() 5343 */ getWifiState()5344 public int getWifiState() { 5345 try { 5346 return mService.getWifiEnabledState(); 5347 } catch (RemoteException e) { 5348 throw e.rethrowFromSystemServer(); 5349 } 5350 } 5351 5352 /** 5353 * Return whether Wi-Fi is enabled or disabled. 5354 * @return {@code true} if Wi-Fi is enabled 5355 * @see #getWifiState() 5356 */ isWifiEnabled()5357 public boolean isWifiEnabled() { 5358 return getWifiState() == WIFI_STATE_ENABLED; 5359 } 5360 5361 /** 5362 * Calculates the level of the signal. This should be used any time a signal 5363 * is being shown. 5364 * 5365 * @param rssi The power of the signal measured in RSSI. 5366 * @param numLevels The number of levels to consider in the calculated level. 5367 * @return A level of the signal, given in the range of 0 to numLevels-1 (both inclusive). 5368 * @deprecated Callers should use {@link #calculateSignalLevel(int)} instead to get the 5369 * signal level using the system default RSSI thresholds, or otherwise compute the RSSI level 5370 * themselves using their own formula. 5371 */ 5372 @Deprecated calculateSignalLevel(int rssi, int numLevels)5373 public static int calculateSignalLevel(int rssi, int numLevels) { 5374 if (rssi <= MIN_RSSI) { 5375 return 0; 5376 } else if (rssi >= MAX_RSSI) { 5377 return numLevels - 1; 5378 } else { 5379 float inputRange = (MAX_RSSI - MIN_RSSI); 5380 float outputRange = (numLevels - 1); 5381 return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange); 5382 } 5383 } 5384 5385 /** 5386 * Given a raw RSSI, return the RSSI signal quality rating using the system default RSSI 5387 * quality rating thresholds. 5388 * @param rssi a raw RSSI value, in dBm, usually between -55 and -90 5389 * @return the RSSI signal quality rating, in the range 5390 * [0, {@link #getMaxSignalLevel()}], where 0 is the lowest (worst signal) RSSI 5391 * rating and {@link #getMaxSignalLevel()} is the highest (best signal) RSSI rating. 5392 */ 5393 @IntRange(from = 0) calculateSignalLevel(int rssi)5394 public int calculateSignalLevel(int rssi) { 5395 try { 5396 return mService.calculateSignalLevel(rssi); 5397 } catch (RemoteException e) { 5398 throw e.rethrowFromSystemServer(); 5399 } 5400 } 5401 5402 /** 5403 * Get the system default maximum signal level. 5404 * This is the maximum RSSI level returned by {@link #calculateSignalLevel(int)}. 5405 */ 5406 @IntRange(from = 0) getMaxSignalLevel()5407 public int getMaxSignalLevel() { 5408 return calculateSignalLevel(Integer.MAX_VALUE); 5409 } 5410 5411 /** 5412 * Compares two signal strengths. 5413 * 5414 * @param rssiA The power of the first signal measured in RSSI. 5415 * @param rssiB The power of the second signal measured in RSSI. 5416 * @return Returns <0 if the first signal is weaker than the second signal, 5417 * 0 if the two signals have the same strength, and >0 if the first 5418 * signal is stronger than the second signal. 5419 */ compareSignalLevel(int rssiA, int rssiB)5420 public static int compareSignalLevel(int rssiA, int rssiB) { 5421 return rssiA - rssiB; 5422 } 5423 5424 /** 5425 * Call allowing ConnectivityService to update WifiService with interface mode changes. 5426 * 5427 * @param ifaceName String name of the updated interface, or null to represent all interfaces 5428 * @param mode int representing the new mode, one of: 5429 * {@link #IFACE_IP_MODE_TETHERED}, 5430 * {@link #IFACE_IP_MODE_LOCAL_ONLY}, 5431 * {@link #IFACE_IP_MODE_CONFIGURATION_ERROR}, 5432 * {@link #IFACE_IP_MODE_UNSPECIFIED} 5433 * 5434 * @hide 5435 */ 5436 @SystemApi 5437 @RequiresPermission(anyOf = { 5438 android.Manifest.permission.NETWORK_STACK, 5439 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5440 }) updateInterfaceIpState(@ullable String ifaceName, @IfaceIpMode int mode)5441 public void updateInterfaceIpState(@Nullable String ifaceName, @IfaceIpMode int mode) { 5442 try { 5443 mService.updateInterfaceIpState(ifaceName, mode); 5444 } catch (RemoteException e) { 5445 throw e.rethrowFromSystemServer(); 5446 } 5447 } 5448 5449 /* Wi-Fi/Cellular Coex */ 5450 5451 /** 5452 * Mandatory coex restriction flag for Wi-Fi Direct. 5453 * 5454 * @see #setCoexUnsafeChannels(List, int) 5455 * 5456 * @hide 5457 */ 5458 @SystemApi 5459 @RequiresApi(Build.VERSION_CODES.S) 5460 public static final int COEX_RESTRICTION_WIFI_DIRECT = 0x1 << 0; 5461 5462 /** 5463 * Mandatory coex restriction flag for SoftAP 5464 * 5465 * @see #setCoexUnsafeChannels(List, int) 5466 * 5467 * @hide 5468 */ 5469 @SystemApi 5470 @RequiresApi(Build.VERSION_CODES.S) 5471 public static final int COEX_RESTRICTION_SOFTAP = 0x1 << 1; 5472 5473 /** 5474 * Mandatory coex restriction flag for Wi-Fi Aware. 5475 * 5476 * @see #setCoexUnsafeChannels(List, int) 5477 * 5478 * @hide 5479 */ 5480 @SystemApi 5481 @RequiresApi(Build.VERSION_CODES.S) 5482 public static final int COEX_RESTRICTION_WIFI_AWARE = 0x1 << 2; 5483 5484 /** @hide */ 5485 @RequiresApi(Build.VERSION_CODES.S) 5486 @Retention(RetentionPolicy.SOURCE) 5487 @IntDef(flag = true, prefix = {"COEX_RESTRICTION_"}, value = { 5488 COEX_RESTRICTION_WIFI_DIRECT, 5489 COEX_RESTRICTION_SOFTAP, 5490 COEX_RESTRICTION_WIFI_AWARE 5491 }) 5492 public @interface CoexRestriction {} 5493 5494 /** 5495 * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise. 5496 * 5497 * @hide 5498 */ isDefaultCoexAlgorithmEnabled()5499 public boolean isDefaultCoexAlgorithmEnabled() { 5500 try { 5501 return mService.isDefaultCoexAlgorithmEnabled(); 5502 } catch (RemoteException e) { 5503 throw e.rethrowFromSystemServer(); 5504 } 5505 } 5506 5507 /** 5508 * Specify the list of {@link CoexUnsafeChannel} to propagate through the framework for 5509 * Wi-Fi/Cellular coex channel avoidance if the default algorithm is disabled via overlay 5510 * (i.e. config_wifiCoexDefaultAlgorithmEnabled = false). Otherwise do nothing. 5511 * 5512 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 5513 * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode 5514 * restrictions on the specified channels. If any restrictions are set, 5515 * then the supplied CoexUnsafeChannels should be completely avoided for 5516 * the specified modes, rather than be avoided with best effort. 5517 * 5518 * @hide 5519 */ 5520 @SystemApi 5521 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS) 5522 @RequiresApi(Build.VERSION_CODES.S) setCoexUnsafeChannels( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)5523 public void setCoexUnsafeChannels( 5524 @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions) { 5525 if (unsafeChannels == null) { 5526 throw new IllegalArgumentException("unsafeChannels must not be null"); 5527 } 5528 try { 5529 mService.setCoexUnsafeChannels(unsafeChannels, restrictions); 5530 } catch (RemoteException e) { 5531 throw e.rethrowFromSystemServer(); 5532 } 5533 } 5534 5535 /** 5536 * Registers a CoexCallback to listen on the current CoexUnsafeChannels and restrictions being 5537 * used for Wi-Fi/cellular coex channel avoidance. The callback method 5538 * {@link CoexCallback#onCoexUnsafeChannelsChanged(List, int)} will be called immediately after 5539 * registration to return the current values. 5540 * 5541 * @param executor Executor to execute listener callback on 5542 * @param callback CoexCallback to register 5543 * 5544 * @hide 5545 */ 5546 @SystemApi 5547 @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) 5548 @RequiresApi(Build.VERSION_CODES.S) registerCoexCallback( @onNull @allbackExecutor Executor executor, @NonNull CoexCallback callback)5549 public void registerCoexCallback( 5550 @NonNull @CallbackExecutor Executor executor, @NonNull CoexCallback callback) { 5551 if (executor == null) throw new IllegalArgumentException("executor must not be null"); 5552 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5553 CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); 5554 proxy.initProxy(executor, callback); 5555 try { 5556 mService.registerCoexCallback(proxy); 5557 } catch (RemoteException e) { 5558 throw e.rethrowFromSystemServer(); 5559 } 5560 } 5561 5562 /** 5563 * Unregisters a CoexCallback from listening on the current CoexUnsafeChannels and restrictions 5564 * being used for Wi-Fi/cellular coex channel avoidance. 5565 * @param callback CoexCallback to unregister 5566 * 5567 * @hide 5568 */ 5569 @SystemApi 5570 @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) 5571 @RequiresApi(Build.VERSION_CODES.S) unregisterCoexCallback(@onNull CoexCallback callback)5572 public void unregisterCoexCallback(@NonNull CoexCallback callback) { 5573 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5574 CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); 5575 try { 5576 mService.unregisterCoexCallback(proxy); 5577 } catch (RemoteException e) { 5578 throw e.rethrowFromSystemServer(); 5579 } finally { 5580 proxy.cleanUpProxy(); 5581 } 5582 } 5583 5584 /** 5585 * Abstract callback class for applications to receive updates about current CoexUnsafeChannels 5586 * for Wi-Fi/Cellular coex channel avoidance. 5587 * 5588 * @hide 5589 */ 5590 @SystemApi 5591 @RequiresApi(Build.VERSION_CODES.S) 5592 public abstract static class CoexCallback { 5593 private final CoexCallbackProxy mCoexCallbackProxy; 5594 CoexCallback()5595 public CoexCallback() { 5596 if (!SdkLevel.isAtLeastS()) { 5597 throw new UnsupportedOperationException(); 5598 } 5599 mCoexCallbackProxy = new CoexCallbackProxy(); 5600 } 5601 5602 /*package*/ @NonNull getProxy()5603 CoexCallbackProxy getProxy() { 5604 return mCoexCallbackProxy; 5605 } 5606 5607 /** 5608 * This indicates the current CoexUnsafeChannels and restrictions calculated by the default 5609 * coex algorithm if config_wifiCoexDefaultAlgorithmEnabled is {@code true}. Otherwise, the 5610 * values will match the ones supplied to {@link #setCoexUnsafeChannels(List, int)}. 5611 * 5612 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 5613 * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode 5614 * restrictions on the specified channels. If any restrictions are set, 5615 * then the supplied CoexUnsafeChannels should be completely avoided for 5616 * the specified modes, rather than be avoided with best effort. 5617 */ onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)5618 public abstract void onCoexUnsafeChannelsChanged( 5619 @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions); 5620 5621 /** 5622 * Callback proxy for CoexCallback objects. 5623 */ 5624 private static class CoexCallbackProxy extends ICoexCallback.Stub { 5625 private final Object mLock = new Object(); 5626 @Nullable @GuardedBy("mLock") private Executor mExecutor; 5627 @Nullable @GuardedBy("mLock") private CoexCallback mCallback; 5628 CoexCallbackProxy()5629 CoexCallbackProxy() { 5630 mExecutor = null; 5631 mCallback = null; 5632 } 5633 initProxy(@onNull Executor executor, @NonNull CoexCallback callback)5634 /*package*/ void initProxy(@NonNull Executor executor, 5635 @NonNull CoexCallback callback) { 5636 synchronized (mLock) { 5637 mExecutor = executor; 5638 mCallback = callback; 5639 } 5640 } 5641 cleanUpProxy()5642 /*package*/ void cleanUpProxy() { 5643 synchronized (mLock) { 5644 mExecutor = null; 5645 mCallback = null; 5646 } 5647 } 5648 5649 @Override onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)5650 public void onCoexUnsafeChannelsChanged( 5651 @NonNull List<CoexUnsafeChannel> unsafeChannels, 5652 @CoexRestriction int restrictions) { 5653 Executor executor; 5654 CoexCallback callback; 5655 synchronized (mLock) { 5656 executor = mExecutor; 5657 callback = mCallback; 5658 } 5659 if (executor == null || callback == null) { 5660 return; 5661 } 5662 Binder.clearCallingIdentity(); 5663 executor.execute(() -> 5664 callback.onCoexUnsafeChannelsChanged(unsafeChannels, restrictions)); 5665 } 5666 } 5667 } 5668 5669 /** 5670 * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. 5671 * Note that starting Soft AP mode may disable station mode operation if the device does not 5672 * support concurrency. 5673 * @param wifiConfig SSID, security and channel details as part of WifiConfiguration, or null to 5674 * use the persisted Soft AP configuration that was previously set using 5675 * {@link #setWifiApConfiguration(WifiConfiguration)}. 5676 * @return {@code true} if the operation succeeded, {@code false} otherwise 5677 * 5678 * @hide 5679 */ 5680 @RequiresPermission(anyOf = { 5681 android.Manifest.permission.NETWORK_STACK, 5682 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5683 }) startSoftAp(@ullable WifiConfiguration wifiConfig)5684 public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) { 5685 try { 5686 return mService.startSoftAp(wifiConfig, mContext.getOpPackageName()); 5687 } catch (RemoteException e) { 5688 throw e.rethrowFromSystemServer(); 5689 } 5690 } 5691 5692 /** 5693 * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. 5694 * Note that starting Soft AP mode may disable station mode operation if the device does not 5695 * support concurrency. 5696 * 5697 * Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid 5698 * unexpected error due to invalid configuration. 5699 * 5700 * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP, or 5701 * null to use the persisted Soft AP configuration that was previously set 5702 * using {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)}. 5703 * @return {@code true} if the operation succeeded, {@code false} otherwise 5704 * 5705 * @deprecated Use {@link #startTetheredHotspot(TetheringManager.TetheringRequest)} 5706 * instead. 5707 * @hide 5708 */ 5709 @SystemApi 5710 @RequiresPermission(anyOf = { 5711 android.Manifest.permission.NETWORK_STACK, 5712 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5713 }) 5714 @Deprecated startTetheredHotspot(@ullable SoftApConfiguration softApConfig)5715 public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) { 5716 try { 5717 return mService.startTetheredHotspot(softApConfig, mContext.getOpPackageName()); 5718 } catch (RemoteException e) { 5719 throw e.rethrowFromSystemServer(); 5720 } 5721 } 5722 5723 /** 5724 * Start Soft AP (hotspot) mode for tethering purposes with the specified TetheringRequest. 5725 * Note that starting Soft AP mode may disable station mode operation if the device does not 5726 * support concurrency. 5727 * 5728 * @param request A valid TetheringRequest specifying the configuration of the SAP. 5729 * @param executor Executor to run the callback on. 5730 * @param callback Callback to listen on state changes for this specific request. 5731 * @hide 5732 */ 5733 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 5734 @SystemApi 5735 @RequiresPermission(anyOf = { 5736 android.Manifest.permission.NETWORK_STACK, 5737 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5738 }) startTetheredHotspot(@onNull TetheringManager.TetheringRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull SoftApCallback callback)5739 public void startTetheredHotspot(@NonNull TetheringManager.TetheringRequest request, 5740 @NonNull @CallbackExecutor Executor executor, @NonNull SoftApCallback callback) { 5741 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 5742 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 5743 ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback, 5744 IFACE_IP_MODE_TETHERED); 5745 try { 5746 mService.startTetheredHotspotRequest(request, binderCallback, 5747 mContext.getOpPackageName()); 5748 } catch (RemoteException e) { 5749 throw e.rethrowFromSystemServer(); 5750 } 5751 } 5752 5753 /** 5754 * Stop SoftAp mode. 5755 * Note that stopping softap mode will restore the previous wifi mode. 5756 * @return {@code true} if the operation succeeds, {@code false} otherwise 5757 * 5758 * @hide 5759 */ 5760 @SystemApi 5761 @RequiresPermission(anyOf = { 5762 android.Manifest.permission.NETWORK_STACK, 5763 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5764 }) stopSoftAp()5765 public boolean stopSoftAp() { 5766 try { 5767 return mService.stopSoftAp(); 5768 } catch (RemoteException e) { 5769 throw e.rethrowFromSystemServer(); 5770 } 5771 } 5772 5773 /** 5774 * Check if input configuration is valid. 5775 * 5776 * @param config a configuration would like to be checked. 5777 * @return true if config is valid, otherwise false. 5778 */ validateSoftApConfiguration(@onNull SoftApConfiguration config)5779 public boolean validateSoftApConfiguration(@NonNull SoftApConfiguration config) { 5780 if (config == null) { 5781 throw new IllegalArgumentException(TAG + ": config can not be null"); 5782 } 5783 try { 5784 return mService.validateSoftApConfiguration(config); 5785 } catch (RemoteException e) { 5786 throw e.rethrowFromSystemServer(); 5787 } 5788 } 5789 5790 /** 5791 * Request a local only hotspot that an application can use to communicate between co-located 5792 * devices connected to the created WiFi hotspot. The network created by this method will not 5793 * have Internet access. Each application can make a single request for the hotspot, but 5794 * multiple applications could be requesting the hotspot at the same time. When multiple 5795 * applications have successfully registered concurrently, they will be sharing the underlying 5796 * hotspot. {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} is called 5797 * when the hotspot is ready for use by the application. 5798 * <p> 5799 * Each application can make a single active call to this method. The {@link 5800 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} callback supplies the 5801 * requestor with a {@link LocalOnlyHotspotReservation} that contains a 5802 * {@link SoftApConfiguration} with the SSID, security type and credentials needed to connect 5803 * to the hotspot. Communicating this information is up to the application. 5804 * <p> 5805 * If the LocalOnlyHotspot cannot be created, the {@link LocalOnlyHotspotCallback#onFailed(int)} 5806 * method will be called. Example failures include errors bringing up the network or if 5807 * there is an incompatible operating mode. For example, if the user is currently using Wifi 5808 * Tethering to provide an upstream to another device, LocalOnlyHotspot may not start due to 5809 * an incompatible mode. The possible error codes include: 5810 * {@link LocalOnlyHotspotCallback#ERROR_NO_CHANNEL}, 5811 * {@link LocalOnlyHotspotCallback#ERROR_GENERIC}, 5812 * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE} and 5813 * {@link LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED}. 5814 * <p> 5815 * Internally, requests will be tracked to prevent the hotspot from being torn down while apps 5816 * are still using it. The {@link LocalOnlyHotspotReservation} object passed in the {@link 5817 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call should be closed when 5818 * the LocalOnlyHotspot is no longer needed using {@link LocalOnlyHotspotReservation#close()}. 5819 * Since the hotspot may be shared among multiple applications, removing the final registered 5820 * application request will trigger the hotspot teardown. This means that applications should 5821 * not listen to broadcasts containing wifi state to determine if the hotspot was stopped after 5822 * they are done using it. Additionally, once {@link LocalOnlyHotspotReservation#close()} is 5823 * called, applications will not receive callbacks of any kind. 5824 * <p> 5825 * Applications should be aware that the user may also stop the LocalOnlyHotspot through the 5826 * Settings UI; it is not guaranteed to stay up as long as there is a requesting application. 5827 * The requestors will be notified of this case via 5828 * {@link LocalOnlyHotspotCallback#onStopped()}. Other cases may arise where the hotspot is 5829 * torn down (Emergency mode, etc). Application developers should be aware that it can stop 5830 * unexpectedly, but they will receive a notification if they have properly registered. 5831 * <p> 5832 * Applications should also be aware that this network will be shared with other applications. 5833 * Applications are responsible for protecting their data on this network (e.g. TLS). 5834 * <p> 5835 * Applications targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later need to have 5836 * the following permissions: {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 5837 * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}. 5838 * Applications targeting {@link Build.VERSION_CODES#S} or prior SDK levels need to have the 5839 * following permissions: {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 5840 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} 5841 * Callers without 5842 * the permissions will trigger a {@link java.lang.SecurityException}. 5843 * <p> 5844 * @param callback LocalOnlyHotspotCallback for the application to receive updates about 5845 * operating status. 5846 * @param handler Handler to be used for callbacks. If the caller passes a null Handler, the 5847 * main thread will be used. 5848 */ 5849 @RequiresPermission(allOf = {CHANGE_WIFI_STATE, ACCESS_FINE_LOCATION, NEARBY_WIFI_DEVICES}, 5850 conditional = true) startLocalOnlyHotspot(LocalOnlyHotspotCallback callback, @Nullable Handler handler)5851 public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback, 5852 @Nullable Handler handler) { 5853 Executor executor = handler == null ? null : new HandlerExecutor(handler); 5854 startLocalOnlyHotspotInternal(null, executor, callback); 5855 } 5856 5857 /** 5858 * Starts a local-only hotspot with a specific configuration applied. See 5859 * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}. 5860 * 5861 * Applications need either {@link android.Manifest.permission#NETWORK_SETUP_WIZARD}, 5862 * {@link android.Manifest.permission#NETWORK_SETTINGS} or 5863 * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} to call this method. 5864 * 5865 * Since custom configuration settings may be incompatible with each other, the hotspot started 5866 * through this method cannot coexist with another hotspot created through 5867 * startLocalOnlyHotspot. If this is attempted, the first hotspot request wins and others 5868 * receive {@link LocalOnlyHotspotCallback#ERROR_GENERIC} through 5869 * {@link LocalOnlyHotspotCallback#onFailed}. 5870 * 5871 * @param config Custom configuration for the hotspot. See {@link SoftApConfiguration}. 5872 * @param executor Executor to run callback methods on, or null to use the main thread. 5873 * @param callback Callback object for updates about hotspot status, or null for no updates. 5874 * @hide 5875 */ 5876 @SystemApi 5877 @RequiresPermission(anyOf = { 5878 android.Manifest.permission.NETWORK_SETTINGS, 5879 android.Manifest.permission.NETWORK_SETUP_WIZARD, 5880 NEARBY_WIFI_DEVICES}) startLocalOnlyHotspot(@onNull SoftApConfiguration config, @Nullable @CallbackExecutor Executor executor, @Nullable LocalOnlyHotspotCallback callback)5881 public void startLocalOnlyHotspot(@NonNull SoftApConfiguration config, 5882 @Nullable @CallbackExecutor Executor executor, 5883 @Nullable LocalOnlyHotspotCallback callback) { 5884 Objects.requireNonNull(config); 5885 startLocalOnlyHotspotInternal(config, executor, callback); 5886 } 5887 5888 /** 5889 * Common implementation of both configurable and non-configurable LOHS. 5890 * 5891 * @param config App-specified configuration, or null. When present, additional privileges are 5892 * required, and the hotspot cannot be shared with other clients. 5893 * @param executor Executor to run callback methods on, or null to use the main thread. 5894 * @param callback Callback object for updates about hotspot status, or null for no updates. 5895 */ startLocalOnlyHotspotInternal( @ullable SoftApConfiguration config, @Nullable @CallbackExecutor Executor executor, @Nullable LocalOnlyHotspotCallback callback)5896 private void startLocalOnlyHotspotInternal( 5897 @Nullable SoftApConfiguration config, 5898 @Nullable @CallbackExecutor Executor executor, 5899 @Nullable LocalOnlyHotspotCallback callback) { 5900 if (executor == null) { 5901 executor = mContext.getMainExecutor(); 5902 } 5903 synchronized (mLock) { 5904 LocalOnlyHotspotCallbackProxy proxy = 5905 new LocalOnlyHotspotCallbackProxy(this, executor, callback); 5906 try { 5907 String packageName = mContext.getOpPackageName(); 5908 String featureId = mContext.getAttributionTag(); 5909 Bundle extras = new Bundle(); 5910 if (SdkLevel.isAtLeastS()) { 5911 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 5912 mContext.getAttributionSource()); 5913 } 5914 int returnCode = mService.startLocalOnlyHotspot(proxy, packageName, featureId, 5915 config, extras); 5916 if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) { 5917 // Send message to the proxy to make sure we call back on the correct thread 5918 proxy.onHotspotFailed(returnCode); 5919 return; 5920 } 5921 mLOHSCallbackProxy = proxy; 5922 } catch (RemoteException e) { 5923 throw e.rethrowFromSystemServer(); 5924 } 5925 } 5926 } 5927 5928 /** 5929 * Cancels a pending local only hotspot request. This can be used by the calling application to 5930 * cancel the existing request if the provided callback has not been triggered. Calling this 5931 * method will be equivalent to closing the returned LocalOnlyHotspotReservation, but it is not 5932 * explicitly required. 5933 * <p> 5934 * When cancelling this request, application developers should be aware that there may still be 5935 * outstanding local only hotspot requests and the hotspot may still start, or continue running. 5936 * Additionally, if a callback was registered, it will no longer be triggered after calling 5937 * cancel. 5938 * 5939 * @hide 5940 */ 5941 @UnsupportedAppUsage cancelLocalOnlyHotspotRequest()5942 public void cancelLocalOnlyHotspotRequest() { 5943 synchronized (mLock) { 5944 stopLocalOnlyHotspot(); 5945 } 5946 } 5947 5948 /** 5949 * Method used to inform WifiService that the LocalOnlyHotspot is no longer needed. This 5950 * method is used by WifiManager to release LocalOnlyHotspotReservations held by calling 5951 * applications and removes the internal tracking for the hotspot request. When all requesting 5952 * applications are finished using the hotspot, it will be stopped and WiFi will return to the 5953 * previous operational mode. 5954 * 5955 * This method should not be called by applications. Instead, they should call the close() 5956 * method on their LocalOnlyHotspotReservation. 5957 */ stopLocalOnlyHotspot()5958 private void stopLocalOnlyHotspot() { 5959 synchronized (mLock) { 5960 if (mLOHSCallbackProxy == null) { 5961 // nothing to do, the callback was already cleaned up. 5962 return; 5963 } 5964 mLOHSCallbackProxy = null; 5965 try { 5966 mService.stopLocalOnlyHotspot(); 5967 } catch (RemoteException e) { 5968 throw e.rethrowFromSystemServer(); 5969 } 5970 } 5971 } 5972 5973 /** 5974 * Registers a callback for local only hotspot. See {@link SoftApCallback}. Caller will receive 5975 * the following callbacks on registration: 5976 * <ul> 5977 * <li> {@link SoftApCallback#onStateChanged(int, int)}</li> 5978 * <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li> 5979 * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li> 5980 * <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li> 5981 * </ul> 5982 * 5983 * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know 5984 * if there are any clients connected to a specific bridged instance of this AP 5985 * (if bridged AP is enabled). 5986 * 5987 * Note: Caller will receive the callback 5988 * {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} 5989 * on registration when there are clients connected to AP. 5990 * 5991 * These will be dispatched on registration to provide the caller with the current state 5992 * (and are not an indication of any current change). Note that receiving an immediate 5993 * WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start 5994 * soft AP has failed. Caller can unregister a previously registered callback using 5995 * {@link #unregisterLocalOnlyHotspotSoftApCallback} 5996 * <p> 5997 * 5998 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 5999 * object. 6000 * @param callback Callback for local only hotspot events 6001 * @hide 6002 */ 6003 @SystemApi 6004 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 6005 @RequiresPermission(NEARBY_WIFI_DEVICES) registerLocalOnlyHotspotSoftApCallback(@onNull @allbackExecutor Executor executor, @NonNull SoftApCallback callback)6006 public void registerLocalOnlyHotspotSoftApCallback(@NonNull @CallbackExecutor Executor executor, 6007 @NonNull SoftApCallback callback) { 6008 if (!SdkLevel.isAtLeastT()) { 6009 throw new UnsupportedOperationException(); 6010 } 6011 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 6012 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 6013 Log.v(TAG, "registerLocalOnlyHotspotSoftApCallback: callback=" + callback + ", executor=" 6014 + executor); 6015 try { 6016 synchronized (sLocalOnlyHotspotSoftApCallbackMap) { 6017 ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback, 6018 IFACE_IP_MODE_LOCAL_ONLY); 6019 sLocalOnlyHotspotSoftApCallbackMap.put(System.identityHashCode(callback), 6020 binderCallback); 6021 Bundle extras = new Bundle(); 6022 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 6023 mContext.getAttributionSource()); 6024 mService.registerLocalOnlyHotspotSoftApCallback(binderCallback, extras); 6025 } 6026 } catch (RemoteException e) { 6027 throw e.rethrowFromSystemServer(); 6028 } 6029 } 6030 6031 /** 6032 * Allow callers to unregister a previously registered callback. After calling this method, 6033 * applications will no longer receive local only hotspot events. 6034 * 6035 * <p> 6036 * 6037 * @param callback Callback to unregister for soft AP events 6038 * 6039 * @hide 6040 */ 6041 @SystemApi 6042 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 6043 @RequiresPermission(NEARBY_WIFI_DEVICES) unregisterLocalOnlyHotspotSoftApCallback(@onNull SoftApCallback callback)6044 public void unregisterLocalOnlyHotspotSoftApCallback(@NonNull SoftApCallback callback) { 6045 if (!SdkLevel.isAtLeastT()) { 6046 throw new UnsupportedOperationException(); 6047 } 6048 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 6049 Log.v(TAG, "unregisterLocalOnlyHotspotSoftApCallback: callback=" + callback); 6050 6051 try { 6052 synchronized (sLocalOnlyHotspotSoftApCallbackMap) { 6053 int callbackIdentifier = System.identityHashCode(callback); 6054 if (!sLocalOnlyHotspotSoftApCallbackMap.contains(callbackIdentifier)) { 6055 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 6056 return; 6057 } 6058 Bundle extras = new Bundle(); 6059 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 6060 mContext.getAttributionSource()); 6061 mService.unregisterLocalOnlyHotspotSoftApCallback( 6062 sLocalOnlyHotspotSoftApCallbackMap.get(callbackIdentifier), extras); 6063 sLocalOnlyHotspotSoftApCallbackMap.remove(callbackIdentifier); 6064 } 6065 } catch (RemoteException e) { 6066 throw e.rethrowFromSystemServer(); 6067 } 6068 } 6069 6070 /** 6071 * Allow callers (Settings UI) to watch LocalOnlyHotspot state changes. Callers will 6072 * receive a {@link LocalOnlyHotspotSubscription} object as a parameter of the 6073 * {@link LocalOnlyHotspotObserver#onRegistered(LocalOnlyHotspotSubscription)}. The registered 6074 * callers will receive the {@link LocalOnlyHotspotObserver#onStarted(SoftApConfiguration)} and 6075 * {@link LocalOnlyHotspotObserver#onStopped()} callbacks. 6076 * <p> 6077 * Applications should have the 6078 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} 6079 * permission. Callers without the permission will trigger a 6080 * {@link java.lang.SecurityException}. 6081 * <p> 6082 * @param observer LocalOnlyHotspotObserver callback. 6083 * @param handler Handler to use for callbacks 6084 * 6085 * @hide 6086 */ watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer, @Nullable Handler handler)6087 public void watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer, 6088 @Nullable Handler handler) { 6089 Executor executor = handler == null ? mContext.getMainExecutor() 6090 : new HandlerExecutor(handler); 6091 synchronized (mLock) { 6092 mLOHSObserverProxy = 6093 new LocalOnlyHotspotObserverProxy(this, executor, observer); 6094 try { 6095 mService.startWatchLocalOnlyHotspot(mLOHSObserverProxy); 6096 mLOHSObserverProxy.registered(); 6097 } catch (RemoteException e) { 6098 mLOHSObserverProxy = null; 6099 throw e.rethrowFromSystemServer(); 6100 } 6101 } 6102 } 6103 6104 /** 6105 * Allow callers to stop watching LocalOnlyHotspot state changes. After calling this method, 6106 * applications will no longer receive callbacks. 6107 * 6108 * @hide 6109 */ unregisterLocalOnlyHotspotObserver()6110 public void unregisterLocalOnlyHotspotObserver() { 6111 synchronized (mLock) { 6112 if (mLOHSObserverProxy == null) { 6113 // nothing to do, the callback was already cleaned up 6114 return; 6115 } 6116 mLOHSObserverProxy = null; 6117 try { 6118 mService.stopWatchLocalOnlyHotspot(); 6119 } catch (RemoteException e) { 6120 throw e.rethrowFromSystemServer(); 6121 } 6122 } 6123 } 6124 6125 /** 6126 * Gets the tethered Wi-Fi hotspot enabled state. 6127 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 6128 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 6129 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 6130 * @see #isWifiApEnabled() 6131 * 6132 * @hide 6133 */ 6134 @SystemApi 6135 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) getWifiApState()6136 public int getWifiApState() { 6137 try { 6138 return mService.getWifiApEnabledState(); 6139 } catch (RemoteException e) { 6140 throw e.rethrowFromSystemServer(); 6141 } 6142 } 6143 6144 /** 6145 * Return whether tethered Wi-Fi AP is enabled or disabled. 6146 * @return {@code true} if tethered Wi-Fi AP is enabled 6147 * @see #getWifiApState() 6148 * 6149 * @hide 6150 */ 6151 @SystemApi 6152 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) isWifiApEnabled()6153 public boolean isWifiApEnabled() { 6154 return getWifiApState() == WIFI_AP_STATE_ENABLED; 6155 } 6156 6157 /** 6158 * Gets the tethered Wi-Fi AP Configuration. 6159 * @return AP details in WifiConfiguration 6160 * 6161 * Note that AP detail may contain configuration which is cannot be represented 6162 * by the legacy WifiConfiguration, in such cases a null will be returned. 6163 * 6164 * @deprecated This API is deprecated. Use {@link #getSoftApConfiguration()} instead. 6165 * @hide 6166 */ 6167 @Nullable 6168 @SystemApi 6169 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 6170 @Deprecated getWifiApConfiguration()6171 public WifiConfiguration getWifiApConfiguration() { 6172 try { 6173 return mService.getWifiApConfiguration(); 6174 } catch (RemoteException e) { 6175 throw e.rethrowFromSystemServer(); 6176 } 6177 } 6178 6179 /** 6180 * Gets the Wi-Fi tethered AP Configuration. 6181 * @return AP details in {@link SoftApConfiguration} 6182 * 6183 * @hide 6184 */ 6185 @NonNull 6186 @SystemApi 6187 @RequiresPermission(anyOf = { 6188 android.Manifest.permission.NETWORK_SETTINGS, 6189 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 6190 }) getSoftApConfiguration()6191 public SoftApConfiguration getSoftApConfiguration() { 6192 try { 6193 return mService.getSoftApConfiguration(); 6194 } catch (RemoteException e) { 6195 throw e.rethrowFromSystemServer(); 6196 } 6197 } 6198 6199 /** 6200 * Gets the last configured Wi-Fi tethered AP passphrase. 6201 * 6202 * Note: It may be null when there is no passphrase changed since 6203 * device boot. 6204 * 6205 * @param executor The executor on which callback will be invoked. 6206 * @param resultCallback An asynchronous callback that will return the last configured 6207 * Wi-Fi tethered AP passphrase. 6208 * 6209 * @throws SecurityException if the caller does not have permission. 6210 * @throws NullPointerException if the caller provided invalid inputs. 6211 * 6212 * @hide 6213 */ 6214 @Nullable 6215 @SystemApi 6216 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) queryLastConfiguredTetheredApPassphraseSinceBoot( @onNull @allbackExecutor Executor executor, @NonNull Consumer<String> resultCallback)6217 public void queryLastConfiguredTetheredApPassphraseSinceBoot( 6218 @NonNull @CallbackExecutor Executor executor, 6219 @NonNull Consumer<String> resultCallback) { 6220 Objects.requireNonNull(executor, "executor cannot be null"); 6221 Objects.requireNonNull(resultCallback, "resultsCallback cannot be null"); 6222 try { 6223 mService.queryLastConfiguredTetheredApPassphraseSinceBoot( 6224 new IStringListener.Stub() { 6225 @Override 6226 public void onResult(String value) { 6227 Binder.clearCallingIdentity(); 6228 executor.execute(() -> { 6229 resultCallback.accept(value); 6230 }); 6231 } 6232 }); 6233 } catch (RemoteException e) { 6234 throw e.rethrowFromSystemServer(); 6235 } 6236 } 6237 6238 /** 6239 * Sets the tethered Wi-Fi AP Configuration. 6240 * @return {@code true} if the operation succeeded, {@code false} otherwise 6241 * 6242 * @deprecated This API is deprecated. Use {@link #setSoftApConfiguration(SoftApConfiguration)} 6243 * instead. 6244 * @hide 6245 */ 6246 @SystemApi 6247 @RequiresPermission(CHANGE_WIFI_STATE) 6248 @Deprecated setWifiApConfiguration(WifiConfiguration wifiConfig)6249 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { 6250 try { 6251 return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName()); 6252 } catch (RemoteException e) { 6253 throw e.rethrowFromSystemServer(); 6254 } 6255 } 6256 6257 /** 6258 * Sets the tethered Wi-Fi AP Configuration. 6259 * 6260 * If the API is called while the tethered soft AP is enabled, the configuration will apply to 6261 * the current soft AP if the new configuration only includes 6262 * {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} 6263 * or {@link SoftApConfiguration.Builder#setShutdownTimeoutMillis(long)} 6264 * or {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)} 6265 * or {@link SoftApConfiguration.Builder#setBlockedClientList(List)} 6266 * or {@link SoftApConfiguration.Builder#setAllowedClientList(List)} 6267 * or {@link SoftApConfiguration.Builder#setAutoShutdownEnabled(boolean)} 6268 * or {@link SoftApConfiguration.Builder#setBridgedModeOpportunisticShutdownEnabled(boolean)} 6269 * 6270 * Otherwise, the configuration changes will be applied when the Soft AP is next started 6271 * (the framework will not stop/start the AP). 6272 * 6273 * Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid 6274 * unexpected error due to invalid configuration. 6275 * 6276 * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP. 6277 * @return {@code true} if the operation succeeded, {@code false} otherwise 6278 * 6279 * @hide 6280 */ 6281 @SystemApi 6282 @RequiresPermission(anyOf = { 6283 android.Manifest.permission.NETWORK_SETTINGS, 6284 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 6285 }) setSoftApConfiguration(@onNull SoftApConfiguration softApConfig)6286 public boolean setSoftApConfiguration(@NonNull SoftApConfiguration softApConfig) { 6287 try { 6288 return mService.setSoftApConfiguration( 6289 softApConfig, mContext.getOpPackageName()); 6290 } catch (RemoteException e) { 6291 throw e.rethrowFromSystemServer(); 6292 } 6293 } 6294 6295 /** 6296 * Enable/Disable TDLS on a specific local route. 6297 * 6298 * <p> 6299 * TDLS enables two wireless endpoints to talk to each other directly 6300 * without going through the access point that is managing the local 6301 * network. It saves bandwidth and improves quality of the link. 6302 * </p> 6303 * <p> 6304 * This API enables/disables the option of using TDLS. If enabled, the 6305 * underlying hardware is free to use TDLS or a hop through the access 6306 * point. If disabled, existing TDLS session is torn down and 6307 * hardware is restricted to use access point for transferring wireless 6308 * packets. Default value for all routes is 'disabled', meaning restricted 6309 * to use access point for transferring packets. 6310 * </p> 6311 * 6312 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 6313 * @param enable true = setup and false = tear down TDLS 6314 */ setTdlsEnabled(InetAddress remoteIPAddress, boolean enable)6315 public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) { 6316 try { 6317 mService.enableTdls(remoteIPAddress.getHostAddress(), enable); 6318 } catch (RemoteException e) { 6319 throw e.rethrowFromSystemServer(); 6320 } 6321 } 6322 6323 /** 6324 * Enable/Disable TDLS on a specific local route. 6325 * 6326 * Similar to {@link #setTdlsEnabled(InetAddress, boolean)}, except 6327 * this version sends the result of the Enable/Disable request. 6328 * 6329 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 6330 * @param enable true = setup and false = tear down TDLS 6331 * @param executor The executor on which callback will be invoked. 6332 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 6333 * whether TDLS was successfully enabled or disabled. 6334 * {@code true} for success, {@code false} for failure. 6335 * 6336 * @throws NullPointerException if the caller provided invalid inputs. 6337 */ setTdlsEnabled(@onNull InetAddress remoteIPAddress, boolean enable, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)6338 public void setTdlsEnabled(@NonNull InetAddress remoteIPAddress, boolean enable, 6339 @NonNull @CallbackExecutor Executor executor, 6340 @NonNull Consumer<Boolean> resultsCallback) { 6341 Objects.requireNonNull(executor, "executor cannot be null"); 6342 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6343 Objects.requireNonNull(remoteIPAddress, "remote IP address cannot be null"); 6344 try { 6345 mService.enableTdlsWithRemoteIpAddress(remoteIPAddress.getHostAddress(), enable, 6346 new IBooleanListener.Stub() { 6347 @Override 6348 public void onResult(boolean value) { 6349 Binder.clearCallingIdentity(); 6350 executor.execute(() -> { 6351 resultsCallback.accept(value); 6352 }); 6353 } 6354 }); 6355 } catch (RemoteException e) { 6356 throw e.rethrowFromSystemServer(); 6357 } 6358 } 6359 6360 /** 6361 * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except 6362 * this version allows you to specify remote endpoint with a MAC address. 6363 * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab 6364 * @param enable true = setup and false = tear down TDLS 6365 */ setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable)6366 public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) { 6367 try { 6368 mService.enableTdlsWithMacAddress(remoteMacAddress, enable); 6369 } catch (RemoteException e) { 6370 throw e.rethrowFromSystemServer(); 6371 } 6372 } 6373 6374 /** 6375 * Enable/Disable TDLS with a specific peer Mac Address. 6376 * 6377 * Similar to {@link #setTdlsEnabledWithMacAddress(String, boolean)}, except 6378 * this version sends the result of the Enable/Disable request. 6379 * 6380 * @param remoteMacAddress Mac address of the endpoint to setup TDLS with 6381 * @param enable true = setup and false = tear down TDLS 6382 * @param executor The executor on which callback will be invoked. 6383 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 6384 * whether TDLS was successfully enabled or disabled. 6385 * {@code true} for success, {@code false} for failure. 6386 * 6387 * @throws NullPointerException if the caller provided invalid inputs. 6388 */ setTdlsEnabledWithMacAddress(@onNull String remoteMacAddress, boolean enable, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)6389 public void setTdlsEnabledWithMacAddress(@NonNull String remoteMacAddress, boolean enable, 6390 @NonNull @CallbackExecutor Executor executor, 6391 @NonNull Consumer<Boolean> resultsCallback) { 6392 Objects.requireNonNull(executor, "executor cannot be null"); 6393 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6394 Objects.requireNonNull(remoteMacAddress, "remote Mac address cannot be null"); 6395 try { 6396 mService.enableTdlsWithRemoteMacAddress(remoteMacAddress, enable, 6397 new IBooleanListener.Stub() { 6398 @Override 6399 public void onResult(boolean value) { 6400 Binder.clearCallingIdentity(); 6401 executor.execute(() -> { 6402 resultsCallback.accept(value); 6403 }); 6404 } 6405 }); 6406 } catch (RemoteException e) { 6407 throw e.rethrowFromSystemServer(); 6408 } 6409 } 6410 6411 /** 6412 * Check if a TDLS session can be established at this time via 6413 * {@link #setTdlsEnabled(InetAddress, boolean)} or 6414 * {@link #setTdlsEnabledWithMacAddress(String, boolean)} or 6415 * {@link #setTdlsEnabled(InetAddress, boolean, Executor, Consumer)} or 6416 * {@link #setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)} 6417 * 6418 * Internally framework checks the STA connected state, device support for TDLS and 6419 * the number of TDLS sessions available in driver/firmware. 6420 * 6421 * @param executor The executor on which callback will be invoked. 6422 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 6423 * whether a TDLS session can be established at this time. 6424 * {@code true} for available, {@code false} for not available. 6425 * 6426 * @throws NullPointerException if the caller provided invalid inputs. 6427 */ isTdlsOperationCurrentlyAvailable(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)6428 public void isTdlsOperationCurrentlyAvailable(@NonNull @CallbackExecutor Executor executor, 6429 @NonNull Consumer<Boolean> resultsCallback) { 6430 Objects.requireNonNull(executor, "executor cannot be null"); 6431 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6432 try { 6433 mService.isTdlsOperationCurrentlyAvailable( 6434 new IBooleanListener.Stub() { 6435 @Override 6436 public void onResult(boolean value) { 6437 Binder.clearCallingIdentity(); 6438 executor.execute(() -> { 6439 resultsCallback.accept(value); 6440 }); 6441 } 6442 }); 6443 } catch (RemoteException e) { 6444 throw e.rethrowFromSystemServer(); 6445 } 6446 } 6447 6448 /** 6449 * Return the maximum number of concurrent TDLS sessions supported by the device. 6450 * 6451 * @param executor The executor on which callback will be invoked. 6452 * @param resultsCallback An asynchronous callback that will return the maximum number of 6453 * concurrent TDLS sessions supported by the device. Returns 6454 * {@code -1} if information is not available, 6455 * e.g. if the driver/firmware doesn't provide this information. 6456 * 6457 * @throws NullPointerException if the caller provided invalid inputs. 6458 * @throws UnsupportedOperationException if the feature is not available. 6459 */ 6460 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) getMaxSupportedConcurrentTdlsSessions(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)6461 public void getMaxSupportedConcurrentTdlsSessions(@NonNull @CallbackExecutor Executor executor, 6462 @NonNull Consumer<Integer> resultsCallback) { 6463 Objects.requireNonNull(executor, "executor cannot be null"); 6464 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6465 try { 6466 mService.getMaxSupportedConcurrentTdlsSessions( 6467 new IIntegerListener.Stub() { 6468 @Override 6469 public void onResult(int value) { 6470 Binder.clearCallingIdentity(); 6471 executor.execute(() -> { 6472 resultsCallback.accept(value); 6473 }); 6474 } 6475 }); 6476 } catch (RemoteException e) { 6477 throw e.rethrowFromSystemServer(); 6478 } 6479 } 6480 6481 /** 6482 * Return the number of currently enabled TDLS sessions. 6483 * 6484 * Tracks the number of peers enabled for TDLS session via 6485 * {@link #setTdlsEnabled(InetAddress, boolean) }, 6486 * {@link #setTdlsEnabledWithMacAddress(String, boolean) }, 6487 * {@link #setTdlsEnabled(InetAddress, boolean, Executor, Consumer) } and 6488 * {@link #setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer) } 6489 * 6490 * @param executor The executor on which callback will be invoked. 6491 * @param resultsCallback An asynchronous callback that will return the number of Peer 6492 * Mac addresses configured in the driver for TDLS session. 6493 * 6494 * @throws NullPointerException if the caller provided invalid inputs. 6495 */ getNumberOfEnabledTdlsSessions(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)6496 public void getNumberOfEnabledTdlsSessions(@NonNull @CallbackExecutor Executor executor, 6497 @NonNull Consumer<Integer> resultsCallback) { 6498 Objects.requireNonNull(executor, "executor cannot be null"); 6499 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6500 try { 6501 mService.getNumberOfEnabledTdlsSessions( 6502 new IIntegerListener.Stub() { 6503 @Override 6504 public void onResult(int value) { 6505 Binder.clearCallingIdentity(); 6506 executor.execute(() -> { 6507 resultsCallback.accept(value); 6508 }); 6509 } 6510 }); 6511 } catch (RemoteException e) { 6512 throw e.rethrowFromSystemServer(); 6513 } 6514 } 6515 6516 /** @hide */ 6517 @Retention(RetentionPolicy.SOURCE) 6518 @IntDef({ActionListener.FAILURE_INTERNAL_ERROR, 6519 ActionListener.FAILURE_IN_PROGRESS, 6520 ActionListener.FAILURE_BUSY, 6521 ActionListener.FAILURE_INVALID_ARGS, 6522 ActionListener.FAILURE_NOT_AUTHORIZED}) 6523 public @interface ActionListenerFailureReason {} 6524 6525 /* WPS specific errors */ 6526 /** WPS overlap detected 6527 * @deprecated This is deprecated 6528 */ 6529 public static final int WPS_OVERLAP_ERROR = 3; 6530 /** WEP on WPS is prohibited 6531 * @deprecated This is deprecated 6532 */ 6533 public static final int WPS_WEP_PROHIBITED = 4; 6534 /** TKIP only prohibited 6535 * @deprecated This is deprecated 6536 */ 6537 public static final int WPS_TKIP_ONLY_PROHIBITED = 5; 6538 /** Authentication failure on WPS 6539 * @deprecated This is deprecated 6540 */ 6541 public static final int WPS_AUTH_FAILURE = 6; 6542 /** WPS timed out 6543 * @deprecated This is deprecated 6544 */ 6545 public static final int WPS_TIMED_OUT = 7; 6546 6547 /** 6548 * Interface for callback invocation on an application action. 6549 * @hide 6550 */ 6551 @SystemApi 6552 public interface ActionListener { 6553 /** 6554 * Passed with {@link #onFailure}. 6555 * Indicates that the operation failed due to an internal error. 6556 */ 6557 int FAILURE_INTERNAL_ERROR = 0; 6558 6559 /** 6560 * Passed with {@link #onFailure}. 6561 * Indicates that the operation is already in progress. 6562 */ 6563 int FAILURE_IN_PROGRESS = 1; 6564 6565 /** 6566 * Passed with {@link #onFailure}. 6567 * Indicates that the operation failed because the framework is busy and is unable to 6568 * service the request. 6569 */ 6570 int FAILURE_BUSY = 2; 6571 6572 /** 6573 * Passed with {@link #onFailure}. 6574 * Indicates that the operation failed due to invalid inputs. 6575 */ 6576 int FAILURE_INVALID_ARGS = 3; 6577 6578 /** 6579 * Passed with {@link #onFailure}. 6580 * Indicates that the operation failed due to insufficient user permissions. 6581 */ 6582 int FAILURE_NOT_AUTHORIZED = 4; 6583 6584 /** 6585 * The operation succeeded. 6586 */ onSuccess()6587 void onSuccess(); 6588 /** 6589 * The operation failed. 6590 * @param reason The reason for failure depends on the operation. 6591 */ onFailure(@ctionListenerFailureReason int reason)6592 void onFailure(@ActionListenerFailureReason int reason); 6593 } 6594 6595 /** Interface for callback invocation on a start WPS action 6596 * @deprecated This is deprecated 6597 */ 6598 public static abstract class WpsCallback { 6599 6600 /** WPS start succeeded 6601 * @deprecated This API is deprecated 6602 */ onStarted(String pin)6603 public abstract void onStarted(String pin); 6604 6605 /** WPS operation completed successfully 6606 * @deprecated This API is deprecated 6607 */ onSucceeded()6608 public abstract void onSucceeded(); 6609 6610 /** 6611 * WPS operation failed 6612 * @param reason The reason for failure could be one of 6613 * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR}, 6614 * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE} 6615 * and some generic errors. 6616 * @deprecated This API is deprecated 6617 */ onFailed(int reason)6618 public abstract void onFailed(int reason); 6619 } 6620 6621 /** 6622 * Base class for soft AP callback. Should be extended by applications and set when calling 6623 * {@link WifiManager#registerSoftApCallback(Executor, SoftApCallback)}. 6624 * 6625 * @hide 6626 */ 6627 @SystemApi 6628 public interface SoftApCallback { 6629 /** 6630 * Called when soft AP state changes. 6631 * 6632 * @param state the new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, 6633 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 6634 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 6635 * @param failureReason reason when in failed state. One of 6636 * {@link #SAP_START_FAILURE_GENERAL}, 6637 * {@link #SAP_START_FAILURE_NO_CHANNEL}, 6638 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}, 6639 * {@link #SAP_START_FAILURE_USER_REJECTED} 6640 */ onStateChanged(@ifiApState int state, @SapStartFailure int failureReason)6641 default void onStateChanged(@WifiApState int state, @SapStartFailure int failureReason) {} 6642 6643 /** 6644 * Called when soft AP state changes. 6645 * <p> 6646 * This provides the same state and failure reason as {@link #onStateChanged(int, int)}, but 6647 * also provides extra information such as interface name and TetheringRequest in order to 6648 * replace usage of the WIFI_AP_STATE_CHANGED_ACTION broadcast. If this method is overridden 6649 * then {@link #onStateChanged(int, int)} will no longer be called. 6650 * 6651 * @param state the new state. 6652 */ 6653 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) onStateChanged(@onNull SoftApState state)6654 default void onStateChanged(@NonNull SoftApState state) { 6655 onStateChanged(state.mState, state.mFailureReason); 6656 } 6657 6658 /** 6659 * Called when the connected clients to soft AP changes. 6660 * 6661 * @param clients the currently connected clients 6662 * 6663 * @deprecated This API is deprecated. 6664 * Use {@link #onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} instead. 6665 */ 6666 @Deprecated onConnectedClientsChanged(@onNull List<WifiClient> clients)6667 default void onConnectedClientsChanged(@NonNull List<WifiClient> clients) {} 6668 6669 6670 /** 6671 * Called when the connected clients for a soft AP instance change. 6672 * 6673 * When the Soft AP is configured in single AP mode, this callback is invoked 6674 * with the same {@link SoftApInfo} for all connected clients changes. 6675 * When the Soft AP is configured as multiple Soft AP instances (using 6676 * {@link SoftApConfiguration.Builder#setBands(int[])} or 6677 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}), this 6678 * callback is invoked with the corresponding {@link SoftApInfo} for the instance in which 6679 * the connected clients changed. 6680 * 6681 * @param info The {@link SoftApInfo} of the AP. 6682 * @param clients The currently connected clients on the AP instance specified by 6683 * {@code info}. 6684 */ onConnectedClientsChanged(@onNull SoftApInfo info, @NonNull List<WifiClient> clients)6685 default void onConnectedClientsChanged(@NonNull SoftApInfo info, 6686 @NonNull List<WifiClient> clients) {} 6687 6688 /** 6689 * Called when the Soft AP information changes. 6690 * 6691 * Note: this API remains valid only when the Soft AP is configured as a single AP - 6692 * not as multiple Soft APs (which are bridged to each other). When multiple Soft APs are 6693 * configured (using {@link SoftApConfiguration.Builder#setBands(int[])} or 6694 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}) 6695 * this callback will not be triggered - use the 6696 * {@link #onInfoChanged(List<SoftApInfo>)} callback in that case. 6697 * 6698 * @param softApInfo is the Soft AP information. {@link SoftApInfo} 6699 * 6700 * @deprecated This API is deprecated. Use {@link #onInfoChanged(List<SoftApInfo>)} 6701 * instead. 6702 */ 6703 @Deprecated onInfoChanged(@onNull SoftApInfo softApInfo)6704 default void onInfoChanged(@NonNull SoftApInfo softApInfo) { 6705 // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. 6706 } 6707 6708 /** 6709 * Called when the Soft AP information changes. 6710 * 6711 * Returns information on all configured Soft AP instances. The number of the elements in 6712 * the list depends on Soft AP configuration and state: 6713 * <ul> 6714 * <li>An empty list will be returned when the Soft AP is disabled. 6715 * <li>One information element will be returned in the list when the Soft AP is configured 6716 * as a single AP or when a single Soft AP remains active. 6717 * <li>Two information elements will be returned in the list when the multiple Soft APs are 6718 * configured and are active. 6719 * (configured using {@link SoftApConfiguration.Builder#setBands(int[])} or 6720 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}). 6721 * </ul> 6722 * 6723 * Note: When multiple Soft AP instances are configured, one of the Soft APs may 6724 * be shut down independently of the other by the framework. This can happen if no devices 6725 * are connected to it for some duration. In that case, one information element will be 6726 * returned. 6727 * 6728 * See {@link #isBridgedApConcurrencySupported()} for support info of multiple (bridged) AP. 6729 * 6730 * @param softApInfoList is the list of the Soft AP information elements - 6731 * {@link SoftApInfo}. 6732 */ onInfoChanged(@onNull List<SoftApInfo> softApInfoList)6733 default void onInfoChanged(@NonNull List<SoftApInfo> softApInfoList) { 6734 // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. 6735 } 6736 6737 /** 6738 * Called when capability of Soft AP changes. 6739 * 6740 * @param softApCapability is the Soft AP capability. {@link SoftApCapability} 6741 */ onCapabilityChanged(@onNull SoftApCapability softApCapability)6742 default void onCapabilityChanged(@NonNull SoftApCapability softApCapability) { 6743 // Do nothing: can be updated to add SoftApCapability details (e.g. meximum supported 6744 // client number) to the UI. 6745 } 6746 6747 /** 6748 * Called when client trying to connect but device blocked the client with specific reason. 6749 * 6750 * Can be used to ask user to update client to allowed list or blocked list 6751 * when reason is {@link SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER}, or 6752 * indicate the block due to maximum supported client number limitation when reason is 6753 * {@link SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS}. 6754 * 6755 * @param client the currently blocked client. 6756 * @param blockedReason one of blocked reason from {@link SapClientBlockedReason} 6757 */ onBlockedClientConnecting(@onNull WifiClient client, @SapClientBlockedReason int blockedReason)6758 default void onBlockedClientConnecting(@NonNull WifiClient client, 6759 @SapClientBlockedReason int blockedReason) { 6760 // Do nothing: can be used to ask user to update client to allowed list or blocked list. 6761 } 6762 } 6763 6764 /** 6765 * Callback proxy for SoftApCallback objects. 6766 * 6767 * @hide 6768 */ 6769 private class SoftApCallbackProxy extends ISoftApCallback.Stub { 6770 private final Executor mExecutor; 6771 private final SoftApCallback mCallback; 6772 // Either {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}. 6773 private final int mIpMode; 6774 private Map<String, List<WifiClient>> mCurrentClients = new HashMap<>(); 6775 private Map<String, SoftApInfo> mCurrentInfos = new HashMap<>(); 6776 getConnectedClientList(Map<String, List<WifiClient>> clientsMap)6777 private List<WifiClient> getConnectedClientList(Map<String, List<WifiClient>> clientsMap) { 6778 List<WifiClient> connectedClientList = new ArrayList<>(); 6779 for (List<WifiClient> it : clientsMap.values()) { 6780 connectedClientList.addAll(it); 6781 } 6782 return connectedClientList; 6783 } 6784 SoftApCallbackProxy(Executor executor, SoftApCallback callback, int mode)6785 SoftApCallbackProxy(Executor executor, SoftApCallback callback, int mode) { 6786 mExecutor = executor; 6787 mCallback = callback; 6788 mIpMode = mode; 6789 } 6790 6791 @Override onStateChanged(SoftApState state)6792 public void onStateChanged(SoftApState state) { 6793 if (mVerboseLoggingEnabled) { 6794 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6795 + ", onStateChanged: " + state); 6796 } 6797 6798 Binder.clearCallingIdentity(); 6799 mExecutor.execute(() -> { 6800 mCallback.onStateChanged(state); 6801 }); 6802 } 6803 6804 @Override onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration)6805 public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, 6806 Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration) { 6807 if (mVerboseLoggingEnabled) { 6808 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6809 + ", onConnectedClientsOrInfoChanged: clients: " 6810 + clients + ", infos: " + infos + ", isBridged is " + isBridged 6811 + ", isRegistration is " + isRegistration); 6812 } 6813 6814 List<SoftApInfo> changedInfoList = new ArrayList<>(infos.values()); 6815 Map<SoftApInfo, List<WifiClient>> changedInfoClients = new HashMap<>(); 6816 // Some devices may not support infos callback, allow them to support client 6817 // connection changed callback. 6818 boolean areClientsChangedWithoutInfosChanged = 6819 infos.size() == 0 && getConnectedClientList(clients).size() 6820 != getConnectedClientList(mCurrentClients).size(); 6821 boolean isInfoChanged = infos.size() != mCurrentInfos.size(); 6822 6823 if (isRegistration) { 6824 // Check if there are clients connected, put it to changedInfoClients 6825 for (SoftApInfo currentInfo : infos.values()) { 6826 String instance = currentInfo.getApInstanceIdentifier(); 6827 if (clients.getOrDefault(instance, Collections.emptyList()).size() > 0) { 6828 changedInfoClients.put(currentInfo, clients.get(instance)); 6829 } 6830 } 6831 } 6832 6833 // Check if old info removed or not (client changed case) 6834 for (SoftApInfo info : mCurrentInfos.values()) { 6835 String changedInstance = info.getApInstanceIdentifier(); 6836 List<WifiClient> changedClientList = clients.getOrDefault( 6837 changedInstance, Collections.emptyList()); 6838 if (!changedInfoList.contains(info)) { 6839 isInfoChanged = true; 6840 if (mCurrentClients.getOrDefault(changedInstance, 6841 Collections.emptyList()).size() > 0) { 6842 SoftApInfo changedInfo = infos.get(changedInstance); 6843 if (changedInfo == null || changedInfo.getFrequency() == 0) { 6844 Log.d(TAG, "SoftApCallbackProxy on mode " + mIpMode 6845 + ", info changed on client connected instance(AP disabled)"); 6846 // Send old info with empty client list for shutdown case 6847 changedInfoClients.put(info, Collections.emptyList()); 6848 } else { 6849 Log.d(TAG, "SoftApCallbackProxy on mode " + mIpMode 6850 + ", info changed on client connected instance"); 6851 changedInfoClients.put(changedInfo, changedClientList); 6852 } 6853 } 6854 } else { 6855 // info doesn't change, check client list 6856 if (changedClientList.size() 6857 != mCurrentClients 6858 .getOrDefault(changedInstance, Collections.emptyList()).size()) { 6859 // Here should notify client changed on new info(same as old info) 6860 changedInfoClients.put(info, changedClientList); 6861 } 6862 } 6863 } 6864 6865 mCurrentClients = clients; 6866 mCurrentInfos = infos; 6867 if (!isInfoChanged && changedInfoClients.isEmpty() 6868 && !isRegistration && !areClientsChangedWithoutInfosChanged) { 6869 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6870 + ", No changed & Not Registration don't need to notify the client"); 6871 return; 6872 } 6873 Binder.clearCallingIdentity(); 6874 // Notify the clients changed first for old info shutdown case 6875 for (SoftApInfo changedInfo : changedInfoClients.keySet()) { 6876 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6877 + ", send onConnectedClientsChanged, changedInfo is " 6878 + changedInfo + " and clients are " + changedInfoClients.get(changedInfo)); 6879 mExecutor.execute(() -> { 6880 mCallback.onConnectedClientsChanged( 6881 changedInfo, changedInfoClients.get(changedInfo)); 6882 }); 6883 } 6884 6885 if (isInfoChanged || isRegistration) { 6886 if (!isBridged) { 6887 SoftApInfo newInfo = changedInfoList.isEmpty() 6888 ? new SoftApInfo() : changedInfoList.get(0); 6889 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6890 + ", send InfoChanged, newInfo: " + newInfo); 6891 mExecutor.execute(() -> { 6892 mCallback.onInfoChanged(newInfo); 6893 }); 6894 } 6895 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6896 + ", send InfoChanged, changedInfoList: " + changedInfoList); 6897 mExecutor.execute(() -> { 6898 mCallback.onInfoChanged(changedInfoList); 6899 }); 6900 } 6901 6902 if (isRegistration || !changedInfoClients.isEmpty() 6903 || areClientsChangedWithoutInfosChanged) { 6904 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6905 + ", send onConnectedClientsChanged(clients): " 6906 + getConnectedClientList(clients)); 6907 mExecutor.execute(() -> { 6908 mCallback.onConnectedClientsChanged(getConnectedClientList(clients)); 6909 }); 6910 } 6911 } 6912 6913 @Override onCapabilityChanged(SoftApCapability capability)6914 public void onCapabilityChanged(SoftApCapability capability) { 6915 if (mVerboseLoggingEnabled) { 6916 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6917 + ", onCapabilityChanged: SoftApCapability = " + capability); 6918 } 6919 6920 Binder.clearCallingIdentity(); 6921 mExecutor.execute(() -> { 6922 mCallback.onCapabilityChanged(capability); 6923 }); 6924 } 6925 6926 @Override onBlockedClientConnecting(@onNull WifiClient client, int blockedReason)6927 public void onBlockedClientConnecting(@NonNull WifiClient client, int blockedReason) { 6928 if (mVerboseLoggingEnabled) { 6929 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6930 + ", onBlockedClientConnecting: client =" + client 6931 + " with reason = " + blockedReason); 6932 } 6933 6934 Binder.clearCallingIdentity(); 6935 mExecutor.execute(() -> { 6936 mCallback.onBlockedClientConnecting(client, blockedReason); 6937 }); 6938 } 6939 } 6940 6941 /** 6942 * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the 6943 * following callbacks on registration: 6944 * <ul> 6945 * <li> {@link SoftApCallback#onStateChanged(int, int)}</li> 6946 * <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li> 6947 * <li> {@link SoftApCallback#onInfoChanged(SoftApInfo)}</li> 6948 * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li> 6949 * <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li> 6950 * </ul> 6951 * 6952 * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know 6953 * if there are any clients connected to a specific bridged instance of this AP 6954 * (if bridged AP is enabled). 6955 * 6956 * Note: Caller will receive the callback 6957 * {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} 6958 * on registration when there are clients connected to AP. 6959 * 6960 * These will be dispatched on registration to provide the caller with the current state 6961 * (and are not an indication of any current change). Note that receiving an immediate 6962 * WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start 6963 * soft AP has failed. Caller can unregister a previously registered callback using 6964 * {@link #unregisterSoftApCallback} 6965 * <p> 6966 * Applications should have the 6967 * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers 6968 * without the permission will trigger a {@link java.lang.SecurityException}. 6969 * <p> 6970 * 6971 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 6972 * object. 6973 * @param callback Callback for soft AP events 6974 * @hide 6975 */ 6976 @SystemApi 6977 @RequiresPermission(anyOf = { 6978 android.Manifest.permission.NETWORK_SETTINGS, 6979 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 6980 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 6981 }) registerSoftApCallback(@onNull @allbackExecutor Executor executor, @NonNull SoftApCallback callback)6982 public void registerSoftApCallback(@NonNull @CallbackExecutor Executor executor, 6983 @NonNull SoftApCallback callback) { 6984 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 6985 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 6986 Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", executor=" + executor); 6987 6988 try { 6989 synchronized (sSoftApCallbackMap) { 6990 ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback, 6991 IFACE_IP_MODE_TETHERED); 6992 sSoftApCallbackMap.put(System.identityHashCode(callback), binderCallback); 6993 mService.registerSoftApCallback(binderCallback); 6994 } 6995 } catch (RemoteException e) { 6996 throw e.rethrowFromSystemServer(); 6997 } 6998 } 6999 7000 /** 7001 * Allow callers to unregister a previously registered callback. After calling this method, 7002 * applications will no longer receive soft AP events. 7003 * 7004 * @param callback Callback to unregister for soft AP events 7005 * 7006 * @hide 7007 */ 7008 @SystemApi 7009 @RequiresPermission(anyOf = { 7010 android.Manifest.permission.NETWORK_SETTINGS, 7011 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 7012 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 7013 }) unregisterSoftApCallback(@onNull SoftApCallback callback)7014 public void unregisterSoftApCallback(@NonNull SoftApCallback callback) { 7015 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 7016 Log.v(TAG, "unregisterSoftApCallback: callback=" + callback); 7017 7018 try { 7019 synchronized (sSoftApCallbackMap) { 7020 int callbackIdentifier = System.identityHashCode(callback); 7021 if (!sSoftApCallbackMap.contains(callbackIdentifier)) { 7022 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 7023 return; 7024 } 7025 mService.unregisterSoftApCallback(sSoftApCallbackMap.get(callbackIdentifier)); 7026 sSoftApCallbackMap.remove(callbackIdentifier); 7027 } 7028 } catch (RemoteException e) { 7029 throw e.rethrowFromSystemServer(); 7030 } 7031 } 7032 7033 /** 7034 * LocalOnlyHotspotReservation that contains the {@link SoftApConfiguration} for the active 7035 * LocalOnlyHotspot request. 7036 * <p> 7037 * Applications requesting LocalOnlyHotspot for sharing will receive an instance of the 7038 * LocalOnlyHotspotReservation in the 7039 * {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call. This 7040 * reservation contains the relevant {@link SoftApConfiguration}. 7041 * When an application is done with the LocalOnlyHotspot, they should call {@link 7042 * LocalOnlyHotspotReservation#close()}. Once this happens, the application will not receive 7043 * any further callbacks. If the LocalOnlyHotspot is stopped due to a 7044 * user triggered mode change, applications will be notified via the {@link 7045 * LocalOnlyHotspotCallback#onStopped()} callback. 7046 */ 7047 public class LocalOnlyHotspotReservation implements AutoCloseable { 7048 7049 private final CloseGuard mCloseGuard = new CloseGuard(); 7050 private final SoftApConfiguration mSoftApConfig; 7051 private final WifiConfiguration mWifiConfig; 7052 private boolean mClosed = false; 7053 7054 /** @hide */ 7055 @VisibleForTesting LocalOnlyHotspotReservation(SoftApConfiguration config)7056 public LocalOnlyHotspotReservation(SoftApConfiguration config) { 7057 mSoftApConfig = config; 7058 mWifiConfig = config.toWifiConfiguration(); 7059 mCloseGuard.open("close"); 7060 } 7061 7062 /** 7063 * Returns the {@link WifiConfiguration} of the current Local Only Hotspot (LOHS). 7064 * May be null if hotspot enabled and security type is not 7065 * {@code WifiConfiguration.KeyMgmt.None} or {@code WifiConfiguration.KeyMgmt.WPA2_PSK}. 7066 * 7067 * @deprecated Use {@code WifiManager#getSoftApConfiguration()} to get the 7068 * LOHS configuration. 7069 */ 7070 @Deprecated 7071 @Nullable getWifiConfiguration()7072 public WifiConfiguration getWifiConfiguration() { 7073 return mWifiConfig; 7074 } 7075 7076 /** 7077 * Returns the {@link SoftApConfiguration} of the current Local Only Hotspot (LOHS). 7078 */ 7079 @NonNull getSoftApConfiguration()7080 public SoftApConfiguration getSoftApConfiguration() { 7081 return mSoftApConfig; 7082 } 7083 7084 @Override close()7085 public void close() { 7086 try { 7087 synchronized (mLock) { 7088 if (!mClosed) { 7089 mClosed = true; 7090 stopLocalOnlyHotspot(); 7091 mCloseGuard.close(); 7092 } 7093 } 7094 } catch (Exception e) { 7095 Log.e(TAG, "Failed to stop Local Only Hotspot."); 7096 } finally { 7097 Reference.reachabilityFence(this); 7098 } 7099 } 7100 7101 @Override finalize()7102 protected void finalize() throws Throwable { 7103 try { 7104 if (mCloseGuard != null) { 7105 mCloseGuard.warnIfOpen(); 7106 } 7107 close(); 7108 } finally { 7109 super.finalize(); 7110 } 7111 } 7112 } 7113 7114 /** 7115 * Callback class for applications to receive updates about the LocalOnlyHotspot status. 7116 */ 7117 public static class LocalOnlyHotspotCallback { 7118 /** @hide */ 7119 public static final int REQUEST_REGISTERED = 0; 7120 7121 public static final int ERROR_NO_CHANNEL = 1; 7122 public static final int ERROR_GENERIC = 2; 7123 public static final int ERROR_INCOMPATIBLE_MODE = 3; 7124 public static final int ERROR_TETHERING_DISALLOWED = 4; 7125 7126 /** LocalOnlyHotspot start succeeded. */ onStarted(LocalOnlyHotspotReservation reservation)7127 public void onStarted(LocalOnlyHotspotReservation reservation) {}; 7128 7129 /** 7130 * LocalOnlyHotspot stopped. 7131 * <p> 7132 * The LocalOnlyHotspot can be disabled at any time by the user. When this happens, 7133 * applications will be notified that it was stopped. This will not be invoked when an 7134 * application calls {@link LocalOnlyHotspotReservation#close()}. 7135 */ onStopped()7136 public void onStopped() {}; 7137 7138 /** 7139 * LocalOnlyHotspot failed to start. 7140 * <p> 7141 * Applications can attempt to call 7142 * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} again at 7143 * a later time. 7144 * <p> 7145 * @param reason The reason for failure could be one of: {@link 7146 * #ERROR_TETHERING_DISALLOWED}, {@link #ERROR_INCOMPATIBLE_MODE}, 7147 * {@link #ERROR_NO_CHANNEL}, or {@link #ERROR_GENERIC}. 7148 */ onFailed(int reason)7149 public void onFailed(int reason) { }; 7150 } 7151 7152 /** 7153 * Callback proxy for LocalOnlyHotspotCallback objects. 7154 */ 7155 private static class LocalOnlyHotspotCallbackProxy extends ILocalOnlyHotspotCallback.Stub { 7156 private final WeakReference<WifiManager> mWifiManager; 7157 private final Executor mExecutor; 7158 private final LocalOnlyHotspotCallback mCallback; 7159 7160 /** 7161 * Constructs a {@link LocalOnlyHotspotCallbackProxy} using the specified executor. All 7162 * callbacks will run using the given executor. 7163 * 7164 * @param manager WifiManager 7165 * @param executor Executor for delivering callbacks. 7166 * @param callback LocalOnlyHotspotCallback to notify the calling application, or null. 7167 */ LocalOnlyHotspotCallbackProxy( @onNull WifiManager manager, @NonNull @CallbackExecutor Executor executor, @Nullable LocalOnlyHotspotCallback callback)7168 LocalOnlyHotspotCallbackProxy( 7169 @NonNull WifiManager manager, 7170 @NonNull @CallbackExecutor Executor executor, 7171 @Nullable LocalOnlyHotspotCallback callback) { 7172 mWifiManager = new WeakReference<>(manager); 7173 mExecutor = executor; 7174 mCallback = callback; 7175 } 7176 7177 @Override onHotspotStarted(SoftApConfiguration config)7178 public void onHotspotStarted(SoftApConfiguration config) { 7179 WifiManager manager = mWifiManager.get(); 7180 if (manager == null) return; 7181 7182 if (config == null) { 7183 Log.e(TAG, "LocalOnlyHotspotCallbackProxy: config cannot be null."); 7184 onHotspotFailed(LocalOnlyHotspotCallback.ERROR_GENERIC); 7185 return; 7186 } 7187 final LocalOnlyHotspotReservation reservation = 7188 manager.new LocalOnlyHotspotReservation(config); 7189 if (mCallback == null) return; 7190 mExecutor.execute(() -> mCallback.onStarted(reservation)); 7191 } 7192 7193 @Override onHotspotStopped()7194 public void onHotspotStopped() { 7195 WifiManager manager = mWifiManager.get(); 7196 if (manager == null) return; 7197 7198 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: hotspot stopped"); 7199 if (mCallback == null) return; 7200 mExecutor.execute(() -> mCallback.onStopped()); 7201 } 7202 7203 @Override onHotspotFailed(int reason)7204 public void onHotspotFailed(int reason) { 7205 WifiManager manager = mWifiManager.get(); 7206 if (manager == null) return; 7207 7208 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: failed to start. reason: " 7209 + reason); 7210 if (mCallback == null) return; 7211 mExecutor.execute(() -> mCallback.onFailed(reason)); 7212 } 7213 } 7214 7215 /** 7216 * LocalOnlyHotspotSubscription that is an AutoCloseable object for tracking applications 7217 * watching for LocalOnlyHotspot changes. 7218 * 7219 * @hide 7220 */ 7221 public class LocalOnlyHotspotSubscription implements AutoCloseable { 7222 private final CloseGuard mCloseGuard = new CloseGuard(); 7223 7224 /** @hide */ 7225 @VisibleForTesting LocalOnlyHotspotSubscription()7226 public LocalOnlyHotspotSubscription() { 7227 mCloseGuard.open("close"); 7228 } 7229 7230 @Override close()7231 public void close() { 7232 try { 7233 unregisterLocalOnlyHotspotObserver(); 7234 mCloseGuard.close(); 7235 } catch (Exception e) { 7236 Log.e(TAG, "Failed to unregister LocalOnlyHotspotObserver."); 7237 } finally { 7238 Reference.reachabilityFence(this); 7239 } 7240 } 7241 7242 @Override finalize()7243 protected void finalize() throws Throwable { 7244 try { 7245 if (mCloseGuard != null) { 7246 mCloseGuard.warnIfOpen(); 7247 } 7248 close(); 7249 } finally { 7250 super.finalize(); 7251 } 7252 } 7253 } 7254 7255 /** 7256 * Class to notify calling applications that watch for changes in LocalOnlyHotspot of updates. 7257 * 7258 * @hide 7259 */ 7260 public static class LocalOnlyHotspotObserver { 7261 /** 7262 * Confirm registration for LocalOnlyHotspotChanges by returning a 7263 * LocalOnlyHotspotSubscription. 7264 */ onRegistered(LocalOnlyHotspotSubscription subscription)7265 public void onRegistered(LocalOnlyHotspotSubscription subscription) {}; 7266 7267 /** 7268 * LocalOnlyHotspot started with the supplied config. 7269 */ onStarted(SoftApConfiguration config)7270 public void onStarted(SoftApConfiguration config) {}; 7271 7272 /** 7273 * LocalOnlyHotspot stopped. 7274 */ onStopped()7275 public void onStopped() {}; 7276 } 7277 7278 /** 7279 * Callback proxy for LocalOnlyHotspotObserver objects. 7280 */ 7281 private static class LocalOnlyHotspotObserverProxy extends ILocalOnlyHotspotCallback.Stub { 7282 private final WeakReference<WifiManager> mWifiManager; 7283 private final Executor mExecutor; 7284 private final LocalOnlyHotspotObserver mObserver; 7285 7286 /** 7287 * Constructs a {@link LocalOnlyHotspotObserverProxy} using the specified looper. 7288 * All callbacks will be delivered on the thread of the specified looper. 7289 * 7290 * @param manager WifiManager 7291 * @param executor Executor for delivering callbacks 7292 * @param observer LocalOnlyHotspotObserver to notify the calling application. 7293 */ LocalOnlyHotspotObserverProxy(WifiManager manager, Executor executor, final LocalOnlyHotspotObserver observer)7294 LocalOnlyHotspotObserverProxy(WifiManager manager, Executor executor, 7295 final LocalOnlyHotspotObserver observer) { 7296 mWifiManager = new WeakReference<>(manager); 7297 mExecutor = executor; 7298 mObserver = observer; 7299 } 7300 registered()7301 public void registered() throws RemoteException { 7302 WifiManager manager = mWifiManager.get(); 7303 if (manager == null) return; 7304 7305 mExecutor.execute(() -> 7306 mObserver.onRegistered(manager.new LocalOnlyHotspotSubscription())); 7307 } 7308 7309 @Override onHotspotStarted(SoftApConfiguration config)7310 public void onHotspotStarted(SoftApConfiguration config) { 7311 WifiManager manager = mWifiManager.get(); 7312 if (manager == null) return; 7313 7314 if (config == null) { 7315 Log.e(TAG, "LocalOnlyHotspotObserverProxy: config cannot be null."); 7316 return; 7317 } 7318 mExecutor.execute(() -> mObserver.onStarted(config)); 7319 } 7320 7321 @Override onHotspotStopped()7322 public void onHotspotStopped() { 7323 WifiManager manager = mWifiManager.get(); 7324 if (manager == null) return; 7325 7326 mExecutor.execute(() -> mObserver.onStopped()); 7327 } 7328 7329 @Override onHotspotFailed(int reason)7330 public void onHotspotFailed(int reason) { 7331 // do nothing 7332 } 7333 } 7334 7335 /** 7336 * Callback proxy for ActionListener objects. 7337 */ 7338 private class ActionListenerProxy extends IActionListener.Stub { 7339 private final String mActionTag; 7340 private final Handler mHandler; 7341 private final ActionListener mCallback; 7342 ActionListenerProxy(String actionTag, Looper looper, ActionListener callback)7343 ActionListenerProxy(String actionTag, Looper looper, ActionListener callback) { 7344 mActionTag = actionTag; 7345 mHandler = new Handler(looper); 7346 mCallback = callback; 7347 } 7348 7349 @Override onSuccess()7350 public void onSuccess() { 7351 if (mVerboseLoggingEnabled) { 7352 Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onSuccess"); 7353 } 7354 mHandler.post(() -> { 7355 mCallback.onSuccess(); 7356 }); 7357 } 7358 7359 @Override onFailure(@ctionListenerFailureReason int reason)7360 public void onFailure(@ActionListenerFailureReason int reason) { 7361 if (mVerboseLoggingEnabled) { 7362 Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onFailure=" + reason); 7363 } 7364 mHandler.post(() -> { 7365 mCallback.onFailure(reason); 7366 }); 7367 } 7368 } 7369 connectInternal(@ullable WifiConfiguration config, int networkId, @Nullable ActionListener listener)7370 private void connectInternal(@Nullable WifiConfiguration config, int networkId, 7371 @Nullable ActionListener listener) { 7372 ActionListenerProxy listenerProxy = null; 7373 if (listener != null) { 7374 listenerProxy = new ActionListenerProxy("connect", mLooper, listener); 7375 } 7376 try { 7377 Bundle extras = new Bundle(); 7378 if (SdkLevel.isAtLeastS()) { 7379 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 7380 mContext.getAttributionSource()); 7381 } 7382 mService.connect(config, networkId, listenerProxy, mContext.getOpPackageName(), extras); 7383 } catch (RemoteException e) { 7384 if (listenerProxy != null) { 7385 listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7386 } 7387 } catch (SecurityException e) { 7388 if (listenerProxy != null) { 7389 listenerProxy.onFailure(ActionListener.FAILURE_NOT_AUTHORIZED); 7390 } 7391 } 7392 } 7393 7394 /** 7395 * Connect to a network with the given configuration. The network also 7396 * gets added to the list of configured networks for the foreground user. 7397 * 7398 * For a new network, this function is used instead of a 7399 * sequence of addNetwork(), enableNetwork(), and reconnect() 7400 * 7401 * @param config the set of variables that describe the configuration, 7402 * contained in a {@link WifiConfiguration} object. 7403 * @param listener for callbacks on success or failure. Can be null. 7404 * @throws IllegalStateException if the WifiManager instance needs to be 7405 * initialized again 7406 * 7407 * @hide 7408 */ 7409 @SystemApi 7410 @RequiresPermission(anyOf = { 7411 android.Manifest.permission.NETWORK_SETTINGS, 7412 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7413 android.Manifest.permission.NETWORK_STACK 7414 }) connect(@onNull WifiConfiguration config, @Nullable ActionListener listener)7415 public void connect(@NonNull WifiConfiguration config, @Nullable ActionListener listener) { 7416 if (config == null) throw new IllegalArgumentException("config cannot be null"); 7417 connectInternal(config, WifiConfiguration.INVALID_NETWORK_ID, listener); 7418 } 7419 7420 /** 7421 * Connect to a network with the given networkId. 7422 * 7423 * This function is used instead of a enableNetwork() and reconnect() 7424 * 7425 * <li> This API will cause reconnect if the credentials of the current active 7426 * connection has been changed.</li> 7427 * <li> This API will cause reconnect if the current active connection is marked metered.</li> 7428 * 7429 * @param networkId the ID of the network as returned by {@link #addNetwork} or {@link 7430 * #getConfiguredNetworks()}. 7431 * @param listener for callbacks on success or failure. Can be null. 7432 * @throws IllegalStateException if the WifiManager instance needs to be 7433 * initialized again 7434 * @hide 7435 */ 7436 @SystemApi 7437 @RequiresPermission(anyOf = { 7438 android.Manifest.permission.NETWORK_SETTINGS, 7439 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7440 android.Manifest.permission.NETWORK_STACK 7441 }) connect(int networkId, @Nullable ActionListener listener)7442 public void connect(int networkId, @Nullable ActionListener listener) { 7443 if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 7444 connectInternal(null, networkId, listener); 7445 } 7446 7447 /** 7448 * Temporarily disable autojoin for all currently visible and provisioned (saved, suggested) 7449 * wifi networks except merged carrier networks from the provided subscription ID. 7450 * 7451 * Disabled networks will get automatically re-enabled when they are out of range for a period 7452 * of time, or after the maximum disable duration specified in the framework. 7453 * 7454 * Calling {@link #stopRestrictingAutoJoinToSubscriptionId()} will immediately re-enable 7455 * autojoin on all disabled networks. 7456 * 7457 * @param subscriptionId the subscription ID of the carrier whose merged wifi networks won't be 7458 * disabled {@link android.telephony.SubscriptionInfo#getSubscriptionId()} 7459 * @hide 7460 */ 7461 @SystemApi 7462 @RequiresPermission(anyOf = { 7463 android.Manifest.permission.NETWORK_SETTINGS, 7464 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 7465 @RequiresApi(Build.VERSION_CODES.S) startRestrictingAutoJoinToSubscriptionId(int subscriptionId)7466 public void startRestrictingAutoJoinToSubscriptionId(int subscriptionId) { 7467 try { 7468 mService.startRestrictingAutoJoinToSubscriptionId(subscriptionId); 7469 } catch (RemoteException e) { 7470 throw e.rethrowFromSystemServer(); 7471 } 7472 } 7473 7474 /** 7475 * Re-enable autojoin for all non carrier merged wifi networks temporarily disconnected by 7476 * {@link #startRestrictingAutoJoinToSubscriptionId(int)}. 7477 * @hide 7478 */ 7479 @SystemApi 7480 @RequiresPermission(anyOf = { 7481 android.Manifest.permission.NETWORK_SETTINGS, 7482 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 7483 @RequiresApi(Build.VERSION_CODES.S) stopRestrictingAutoJoinToSubscriptionId()7484 public void stopRestrictingAutoJoinToSubscriptionId() { 7485 try { 7486 mService.stopRestrictingAutoJoinToSubscriptionId(); 7487 } catch (RemoteException e) { 7488 throw e.rethrowFromSystemServer(); 7489 } 7490 } 7491 7492 /** 7493 * Save the given network to the list of configured networks for the 7494 * foreground user. If the network already exists, the configuration 7495 * is updated. Any new network is enabled by default. 7496 * 7497 * For a new network, this function is used instead of a 7498 * sequence of addNetwork() and enableNetwork(). 7499 * 7500 * For an existing network, it accomplishes the task of updateNetwork() 7501 * 7502 * <li> This API will cause reconnect if the credentials of the current active 7503 * connection has been changed.</li> 7504 * <li> This API will cause disconnect if the current active connection is marked metered.</li> 7505 * 7506 * @param config the set of variables that describe the configuration, 7507 * contained in a {@link WifiConfiguration} object. 7508 * @param listener for callbacks on success or failure. Can be null. 7509 * @throws IllegalStateException if the WifiManager instance needs to be 7510 * initialized again 7511 * @hide 7512 */ 7513 @SystemApi 7514 @RequiresPermission(anyOf = { 7515 android.Manifest.permission.NETWORK_SETTINGS, 7516 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7517 android.Manifest.permission.NETWORK_STACK 7518 }) save(@onNull WifiConfiguration config, @Nullable ActionListener listener)7519 public void save(@NonNull WifiConfiguration config, @Nullable ActionListener listener) { 7520 if (config == null) throw new IllegalArgumentException("config cannot be null"); 7521 ActionListenerProxy listenerProxy = null; 7522 if (listener != null) { 7523 listenerProxy = new ActionListenerProxy("save", mLooper, listener); 7524 } 7525 try { 7526 mService.save(config, listenerProxy, mContext.getOpPackageName()); 7527 } catch (RemoteException e) { 7528 if (listenerProxy != null) { 7529 listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7530 } 7531 } catch (SecurityException e) { 7532 if (listenerProxy != null) { 7533 listenerProxy.onFailure(ActionListener.FAILURE_NOT_AUTHORIZED); 7534 } 7535 } 7536 } 7537 7538 /** 7539 * Delete the network from the list of configured networks for the 7540 * foreground user. 7541 * 7542 * This function is used instead of a sequence of removeNetwork() 7543 * 7544 * @param config the set of variables that describe the configuration, 7545 * contained in a {@link WifiConfiguration} object. 7546 * @param listener for callbacks on success or failure. Can be null. 7547 * @throws IllegalStateException if the WifiManager instance needs to be 7548 * initialized again 7549 * @hide 7550 */ 7551 @SystemApi 7552 @RequiresPermission(anyOf = { 7553 android.Manifest.permission.NETWORK_SETTINGS, 7554 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7555 android.Manifest.permission.NETWORK_STACK 7556 }) forget(int netId, @Nullable ActionListener listener)7557 public void forget(int netId, @Nullable ActionListener listener) { 7558 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 7559 ActionListenerProxy listenerProxy = null; 7560 if (listener != null) { 7561 listenerProxy = new ActionListenerProxy("forget", mLooper, listener); 7562 } 7563 try { 7564 mService.forget(netId, listenerProxy); 7565 } catch (RemoteException e) { 7566 if (listenerProxy != null) { 7567 listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7568 } 7569 } catch (SecurityException e) { 7570 if (listenerProxy != null) { 7571 listenerProxy.onFailure(ActionListener.FAILURE_NOT_AUTHORIZED); 7572 } 7573 } 7574 } 7575 7576 /** 7577 * Disable network 7578 * 7579 * @param netId is the network Id 7580 * @param listener for callbacks on success or failure. Can be null. 7581 * @throws IllegalStateException if the WifiManager instance needs to be 7582 * initialized again 7583 * @deprecated This API is deprecated. Use {@link #disableNetwork(int)} instead. 7584 * @hide 7585 */ 7586 @SystemApi 7587 @RequiresPermission(anyOf = { 7588 android.Manifest.permission.NETWORK_SETTINGS, 7589 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7590 android.Manifest.permission.NETWORK_STACK 7591 }) 7592 @Deprecated disable(int netId, @Nullable ActionListener listener)7593 public void disable(int netId, @Nullable ActionListener listener) { 7594 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 7595 // Simple wrapper which forwards the call to disableNetwork. This is a temporary 7596 // implementation until we can remove this API completely. 7597 boolean status = disableNetwork(netId); 7598 if (listener != null) { 7599 if (status) { 7600 listener.onSuccess(); 7601 } else { 7602 listener.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7603 } 7604 } 7605 } 7606 7607 /** 7608 * Control whether the device will automatically search for and connect to Wi-Fi networks - 7609 * auto-join Wi-Fi networks. Disabling this option will not impact manual connections - i.e. 7610 * the user will still be able to manually select and connect to a Wi-Fi network. Disabling 7611 * this option significantly impacts the device connectivity and is a restricted operation 7612 * (see below for permissions). Note that disabling this operation will also disable 7613 * connectivity initiated scanning operations. 7614 * <p> 7615 * Disabling the auto-join configuration is a temporary operation (with the exception of a 7616 * DO/PO caller): it will be reset (to enabled) when the device reboots or the user toggles 7617 * Wi-Fi off/on. When the caller is a DO/PO then toggling Wi-Fi will not reset the 7618 * configuration. Additionally, if a DO/PO disables auto-join then it cannot be (re)enabled by 7619 * a non-DO/PO caller. 7620 * 7621 * @param allowAutojoin true to allow auto-join, false to disallow auto-join 7622 * 7623 * Available for DO/PO apps. 7624 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 7625 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 7626 */ allowAutojoinGlobal(boolean allowAutojoin)7627 public void allowAutojoinGlobal(boolean allowAutojoin) { 7628 try { 7629 Bundle extras = new Bundle(); 7630 if (SdkLevel.isAtLeastS()) { 7631 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 7632 mContext.getAttributionSource()); 7633 } 7634 mService.allowAutojoinGlobal(allowAutojoin, mContext.getOpPackageName(), extras); 7635 } catch (RemoteException e) { 7636 throw e.rethrowFromSystemServer(); 7637 } 7638 } 7639 7640 /** 7641 * Query whether or not auto-join global is enabled/disabled 7642 * @see #allowAutojoinGlobal(boolean) 7643 * 7644 * Available for DO/PO apps. 7645 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 7646 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 7647 * 7648 * @param executor The executor on which callback will be invoked. 7649 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 7650 * whether auto-join global is enabled/disabled. 7651 * 7652 * @throws SecurityException if the caller does not have permission. 7653 * @throws NullPointerException if the caller provided invalid inputs. 7654 */ queryAutojoinGlobal(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)7655 public void queryAutojoinGlobal(@NonNull @CallbackExecutor Executor executor, 7656 @NonNull Consumer<Boolean> resultsCallback) { 7657 Objects.requireNonNull(executor, "executor cannot be null"); 7658 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 7659 try { 7660 mService.queryAutojoinGlobal( 7661 new IBooleanListener.Stub() { 7662 @Override 7663 public void onResult(boolean value) { 7664 Binder.clearCallingIdentity(); 7665 executor.execute(() -> { 7666 resultsCallback.accept(value); 7667 }); 7668 } 7669 }); 7670 } catch (RemoteException e) { 7671 throw e.rethrowFromSystemServer(); 7672 } 7673 } 7674 7675 /** 7676 * Sets the user choice for allowing auto-join to a network. 7677 * The updated choice will be made available through the updated config supplied by the 7678 * CONFIGURED_NETWORKS_CHANGED broadcast. 7679 * 7680 * @param netId the id of the network to allow/disallow auto-join for. 7681 * @param allowAutojoin true to allow auto-join, false to disallow auto-join 7682 * @hide 7683 */ 7684 @SystemApi 7685 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) allowAutojoin(int netId, boolean allowAutojoin)7686 public void allowAutojoin(int netId, boolean allowAutojoin) { 7687 try { 7688 mService.allowAutojoin(netId, allowAutojoin); 7689 } catch (RemoteException e) { 7690 throw e.rethrowFromSystemServer(); 7691 } 7692 } 7693 7694 /** 7695 * Configure auto-join settings for a Passpoint profile. 7696 * 7697 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 7698 * @param allowAutojoin true to enable auto-join, false to disable auto-join. 7699 * @hide 7700 */ 7701 @SystemApi 7702 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) allowAutojoinPasspoint(@onNull String fqdn, boolean allowAutojoin)7703 public void allowAutojoinPasspoint(@NonNull String fqdn, boolean allowAutojoin) { 7704 try { 7705 mService.allowAutojoinPasspoint(fqdn, allowAutojoin); 7706 } catch (RemoteException e) { 7707 throw e.rethrowFromSystemServer(); 7708 } 7709 } 7710 7711 /** 7712 * Configure MAC randomization setting for a Passpoint profile. 7713 * MAC randomization is enabled by default. 7714 * 7715 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 7716 * @param enable true to enable MAC randomization, false to disable MAC randomization. 7717 * @hide 7718 */ 7719 @SystemApi 7720 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setMacRandomizationSettingPasspointEnabled(@onNull String fqdn, boolean enable)7721 public void setMacRandomizationSettingPasspointEnabled(@NonNull String fqdn, boolean enable) { 7722 try { 7723 mService.setMacRandomizationSettingPasspointEnabled(fqdn, enable); 7724 } catch (RemoteException e) { 7725 throw e.rethrowFromSystemServer(); 7726 } 7727 } 7728 7729 /** 7730 * Sets the user's choice of metered override for a Passpoint profile. 7731 * 7732 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 7733 * @param meteredOverride One of three values: {@link WifiConfiguration#METERED_OVERRIDE_NONE}, 7734 * {@link WifiConfiguration#METERED_OVERRIDE_METERED}, 7735 * {@link WifiConfiguration#METERED_OVERRIDE_NOT_METERED} 7736 * @hide 7737 */ 7738 @SystemApi 7739 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setPasspointMeteredOverride(@onNull String fqdn, @WifiConfiguration.MeteredOverride int meteredOverride)7740 public void setPasspointMeteredOverride(@NonNull String fqdn, 7741 @WifiConfiguration.MeteredOverride int meteredOverride) { 7742 try { 7743 mService.setPasspointMeteredOverride(fqdn, meteredOverride); 7744 } catch (RemoteException e) { 7745 throw e.rethrowFromSystemServer(); 7746 } 7747 } 7748 7749 /** 7750 * Temporarily disable a network. Should always trigger with user disconnect network. 7751 * 7752 * @param network Input can be SSID or FQDN. And caller must ensure that the SSID passed thru 7753 * this API matched the WifiConfiguration.SSID rules, and thus be surrounded by 7754 * quotes. 7755 * @hide 7756 */ 7757 @SystemApi 7758 @RequiresPermission(anyOf = { 7759 android.Manifest.permission.NETWORK_SETTINGS, 7760 android.Manifest.permission.NETWORK_STACK 7761 }) disableEphemeralNetwork(@onNull String network)7762 public void disableEphemeralNetwork(@NonNull String network) { 7763 if (TextUtils.isEmpty(network)) { 7764 throw new IllegalArgumentException("SSID cannot be null or empty!"); 7765 } 7766 try { 7767 mService.disableEphemeralNetwork(network, mContext.getOpPackageName()); 7768 } catch (RemoteException e) { 7769 throw e.rethrowFromSystemServer(); 7770 } 7771 } 7772 7773 /** 7774 * WPS suport has been deprecated from Client mode and this method will immediately trigger 7775 * {@link WpsCallback#onFailed(int)} with a generic error. 7776 * 7777 * @param config WPS configuration (does not support {@link WpsInfo#LABEL}) 7778 * @param listener for callbacks on success or failure. Can be null. 7779 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 7780 * @deprecated This API is deprecated 7781 */ startWps(WpsInfo config, WpsCallback listener)7782 public void startWps(WpsInfo config, WpsCallback listener) { 7783 if (listener != null ) { 7784 listener.onFailed(ActionListener.FAILURE_INTERNAL_ERROR); 7785 } 7786 } 7787 7788 /** 7789 * WPS support has been deprecated from Client mode and this method will immediately trigger 7790 * {@link WpsCallback#onFailed(int)} with a generic error. 7791 * 7792 * @param listener for callbacks on success or failure. Can be null. 7793 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 7794 * @deprecated This API is deprecated 7795 */ cancelWps(WpsCallback listener)7796 public void cancelWps(WpsCallback listener) { 7797 if (listener != null) { 7798 listener.onFailed(ActionListener.FAILURE_INTERNAL_ERROR); 7799 } 7800 } 7801 7802 /** 7803 * Allows an application to keep the Wi-Fi radio awake. 7804 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 7805 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 7806 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 7807 * WifiLocks are held in any application. 7808 * <p> 7809 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 7810 * could function over a mobile network, if available. A program that needs to download large 7811 * files should hold a WifiLock to ensure that the download will complete, but a program whose 7812 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 7813 * affecting battery life. 7814 * <p> 7815 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 7816 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 7817 * is idle. 7818 * <p> 7819 * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK} 7820 * permission in an {@code <uses-permission>} element of the application's manifest. 7821 */ 7822 public class WifiLock { 7823 private String mTag; 7824 private final IBinder mBinder; 7825 private int mRefCount; 7826 int mLockType; 7827 private boolean mRefCounted; 7828 private boolean mHeld; 7829 private WorkSource mWorkSource; 7830 WifiLock(int lockType, String tag)7831 private WifiLock(int lockType, String tag) { 7832 mTag = tag; 7833 mLockType = lockType; 7834 mBinder = new Binder(); 7835 mRefCount = 0; 7836 mRefCounted = true; 7837 mHeld = false; 7838 } 7839 7840 /** 7841 * Locks the Wi-Fi radio on until {@link #release} is called. 7842 * 7843 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 7844 * reference count, and the radio will remain locked as long as the reference count is 7845 * above zero. 7846 * 7847 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 7848 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 7849 * will be required, regardless of the number of times that {@code acquire} is called. 7850 */ acquire()7851 public void acquire() { 7852 synchronized (mBinder) { 7853 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 7854 try { 7855 Bundle extras = new Bundle(); 7856 if (SdkLevel.isAtLeastS()) { 7857 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 7858 mContext.getAttributionSource()); 7859 } 7860 mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource, 7861 mContext.getOpPackageName(), extras); 7862 synchronized (WifiManager.this) { 7863 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 7864 mService.releaseWifiLock(mBinder); 7865 throw new UnsupportedOperationException( 7866 "Exceeded maximum number of wifi locks"); 7867 } 7868 mActiveLockCount++; 7869 } 7870 } catch (RemoteException e) { 7871 throw e.rethrowFromSystemServer(); 7872 } 7873 mHeld = true; 7874 } 7875 } 7876 } 7877 7878 /** 7879 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 7880 * 7881 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 7882 * reference count, and the radio will be unlocked only when the reference count reaches 7883 * zero. If the reference count goes below zero (that is, if {@code release} is called 7884 * a greater number of times than {@link #acquire}), an exception is thrown. 7885 * 7886 * If this WifiLock is not reference-counted, the first call to {@code release} (after 7887 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 7888 * calls will be ignored. 7889 */ release()7890 public void release() { 7891 synchronized (mBinder) { 7892 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 7893 try { 7894 mService.releaseWifiLock(mBinder); 7895 synchronized (WifiManager.this) { 7896 mActiveLockCount--; 7897 } 7898 } catch (RemoteException e) { 7899 throw e.rethrowFromSystemServer(); 7900 } 7901 mHeld = false; 7902 } 7903 if (mRefCount < 0) { 7904 throw new RuntimeException("WifiLock under-locked " + mTag); 7905 } 7906 } 7907 } 7908 7909 /** 7910 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 7911 * 7912 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 7913 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 7914 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 7915 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 7916 * radio whenever {@link #release} is called and it is locked. 7917 * 7918 * @param refCounted true if this WifiLock should keep a reference count 7919 */ setReferenceCounted(boolean refCounted)7920 public void setReferenceCounted(boolean refCounted) { 7921 mRefCounted = refCounted; 7922 } 7923 7924 /** 7925 * Checks whether this WifiLock is currently held. 7926 * 7927 * @return true if this WifiLock is held, false otherwise 7928 */ isHeld()7929 public boolean isHeld() { 7930 synchronized (mBinder) { 7931 return mHeld; 7932 } 7933 } 7934 setWorkSource(WorkSource ws)7935 public void setWorkSource(WorkSource ws) { 7936 synchronized (mBinder) { 7937 if (ws != null && ws.isEmpty()) { 7938 ws = null; 7939 } 7940 boolean changed = true; 7941 if (ws == null) { 7942 mWorkSource = null; 7943 } else { 7944 ws = ws.withoutNames(); 7945 if (mWorkSource == null) { 7946 changed = mWorkSource != null; 7947 mWorkSource = new WorkSource(ws); 7948 } else { 7949 changed = !mWorkSource.equals(ws); 7950 if (changed) { 7951 mWorkSource.set(ws); 7952 } 7953 } 7954 } 7955 if (changed && mHeld) { 7956 try { 7957 Bundle extras = new Bundle(); 7958 if (SdkLevel.isAtLeastS()) { 7959 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 7960 mContext.getAttributionSource()); 7961 } 7962 mService.updateWifiLockWorkSource(mBinder, mWorkSource, 7963 mContext.getOpPackageName(), extras); 7964 } catch (RemoteException e) { 7965 throw e.rethrowFromSystemServer(); 7966 } 7967 } 7968 } 7969 } 7970 toString()7971 public String toString() { 7972 String s1, s2, s3; 7973 synchronized (mBinder) { 7974 s1 = Integer.toHexString(System.identityHashCode(this)); 7975 s2 = mHeld ? "held; " : ""; 7976 if (mRefCounted) { 7977 s3 = "refcounted: refcount = " + mRefCount; 7978 } else { 7979 s3 = "not refcounted"; 7980 } 7981 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 7982 } 7983 } 7984 7985 @Override finalize()7986 protected void finalize() throws Throwable { 7987 super.finalize(); 7988 synchronized (mBinder) { 7989 if (mHeld) { 7990 try { 7991 mService.releaseWifiLock(mBinder); 7992 synchronized (WifiManager.this) { 7993 mActiveLockCount--; 7994 } 7995 } catch (RemoteException e) { 7996 throw e.rethrowFromSystemServer(); 7997 } 7998 } 7999 } 8000 } 8001 } 8002 8003 /** 8004 * Creates a new WifiLock. 8005 * 8006 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL_HIGH_PERF} 8007 * and {@link #WIFI_MODE_FULL_LOW_LATENCY} for descriptions of the types of Wi-Fi locks. 8008 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 8009 * never shown to the user under normal conditions, but should be descriptive 8010 * enough to identify your application and the specific WifiLock within it, if it 8011 * holds multiple WifiLocks. 8012 * 8013 * @return a new, unacquired WifiLock with the given tag. 8014 * 8015 * @see WifiLock 8016 */ createWifiLock(int lockType, String tag)8017 public WifiLock createWifiLock(int lockType, String tag) { 8018 return new WifiLock(lockType, tag); 8019 } 8020 8021 /** 8022 * Interface for low latency lock listener. Should be extended by application and set when 8023 * calling {@link WifiManager#addWifiLowLatencyLockListener(Executor, 8024 * WifiLowLatencyLockListener)}. 8025 * 8026 * @hide 8027 */ 8028 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 8029 @SystemApi 8030 public interface WifiLowLatencyLockListener { 8031 /** 8032 * Provides low latency mode is activated or not. Triggered when Wi-Fi chip enters into low 8033 * latency mode. 8034 * 8035 * <p>Note: Always called with current state when a new listener gets registered. 8036 */ 8037 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) onActivatedStateChanged(boolean activated)8038 void onActivatedStateChanged(boolean activated); 8039 8040 /** 8041 * Provides UIDs (lock owners) of the applications which currently acquired low latency 8042 * lock. Triggered when an application acquires or releases a lock. 8043 * 8044 * <p>Note: Always called with UIDs of the current acquired locks when a new listener gets 8045 * registered. 8046 * 8047 * @param ownerUids An array of UIDs. 8048 */ 8049 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) onOwnershipChanged(@onNull int[] ownerUids)8050 default void onOwnershipChanged(@NonNull int[] ownerUids) {} 8051 8052 /** 8053 * Provides UIDs of the applications which acquired the low latency lock and is currently 8054 * active. See {@link WifiManager#WIFI_MODE_FULL_LOW_LATENCY} for the conditions to be met 8055 * for low latency lock to be active. Triggered when application acquiring the lock 8056 * satisfies or does not satisfy low latency conditions when the low latency mode is 8057 * activated. Also gets triggered when the lock becomes active, immediately after the {@link 8058 * WifiLowLatencyLockListener#onActivatedStateChanged(boolean)} callback is triggered. 8059 * 8060 * <p>Note: Always called with UIDs of the current active locks when a new listener gets 8061 * registered if the Wi-Fi chip is in low latency mode. 8062 * 8063 * @param activeUids An array of UIDs. 8064 */ 8065 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) onActiveUsersChanged(@onNull int[] activeUids)8066 default void onActiveUsersChanged(@NonNull int[] activeUids) {} 8067 } 8068 8069 /** 8070 * Helper class to support wifi low latency lock listener. 8071 */ 8072 private static class OnWifiLowLatencyLockProxy extends IWifiLowLatencyLockListener.Stub { 8073 @NonNull 8074 private Executor mExecutor; 8075 @NonNull 8076 private WifiLowLatencyLockListener mListener; 8077 OnWifiLowLatencyLockProxy(@onNull Executor executor, @NonNull WifiLowLatencyLockListener listener)8078 OnWifiLowLatencyLockProxy(@NonNull Executor executor, 8079 @NonNull WifiLowLatencyLockListener listener) { 8080 Objects.requireNonNull(executor); 8081 Objects.requireNonNull(listener); 8082 mExecutor = executor; 8083 mListener = listener; 8084 } 8085 8086 @Override onActivatedStateChanged(boolean activated)8087 public void onActivatedStateChanged(boolean activated) { 8088 Binder.clearCallingIdentity(); 8089 mExecutor.execute(() -> mListener.onActivatedStateChanged(activated)); 8090 8091 } 8092 8093 @Override onOwnershipChanged(@onNull int[] ownerUids)8094 public void onOwnershipChanged(@NonNull int[] ownerUids) { 8095 Binder.clearCallingIdentity(); 8096 mExecutor.execute(() -> mListener.onOwnershipChanged(ownerUids)); 8097 8098 } 8099 8100 @Override onActiveUsersChanged(@onNull int[] activeUids)8101 public void onActiveUsersChanged(@NonNull int[] activeUids) { 8102 Binder.clearCallingIdentity(); 8103 mExecutor.execute(() -> mListener.onActiveUsersChanged(activeUids)); 8104 } 8105 } 8106 8107 /** 8108 * Add a listener for monitoring the low latency lock. The caller can unregister a previously 8109 * registered listener using {@link WifiManager#removeWifiLowLatencyLockListener( 8110 * WifiLowLatencyLockListener)}. 8111 * 8112 * <p>Applications should have the {@link android.Manifest.permission#NETWORK_SETTINGS} and 8113 * {@link android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. Callers without 8114 * the permission will trigger a {@link java.lang.SecurityException}. 8115 * 8116 * @param executor The Executor on which to execute the callbacks. 8117 * @param listener The listener for the latency mode change. 8118 * @throws IllegalArgumentException if incorrect input arguments are provided. 8119 * @throws SecurityException if the caller is not allowed to call this API 8120 * @hide 8121 */ 8122 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 8123 @SystemApi 8124 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 8125 @RequiresPermission( 8126 anyOf = {android.Manifest.permission.NETWORK_SETTINGS, MANAGE_WIFI_NETWORK_SELECTION}) addWifiLowLatencyLockListener( @onNull @allbackExecutor Executor executor, @NonNull WifiLowLatencyLockListener listener)8127 public void addWifiLowLatencyLockListener( 8128 @NonNull @CallbackExecutor Executor executor, 8129 @NonNull WifiLowLatencyLockListener listener) { 8130 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 8131 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 8132 if (mVerboseLoggingEnabled) { 8133 Log.d(TAG, "addWifiLowLatencyLockListener: listener=" + listener + ", executor=" 8134 + executor); 8135 } 8136 final int listenerIdentifier = System.identityHashCode(listener); 8137 try { 8138 synchronized (sWifiLowLatencyLockListenerMap) { 8139 IWifiLowLatencyLockListener.Stub listenerProxy = new OnWifiLowLatencyLockProxy( 8140 executor, 8141 listener); 8142 sWifiLowLatencyLockListenerMap.put(listenerIdentifier, listenerProxy); 8143 mService.addWifiLowLatencyLockListener(listenerProxy); 8144 } 8145 } catch (RemoteException e) { 8146 sWifiLowLatencyLockListenerMap.remove(listenerIdentifier); 8147 throw e.rethrowFromSystemServer(); 8148 } 8149 } 8150 8151 /** 8152 * Removes a listener added using {@link WifiManager#addWifiLowLatencyLockListener(Executor, 8153 * WifiLowLatencyLockListener)}. After calling this method, applications will no longer receive 8154 * low latency mode notifications. 8155 * 8156 * @param listener the listener to be removed. 8157 * @throws IllegalArgumentException if incorrect input arguments are provided. 8158 * @hide 8159 */ 8160 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 8161 @SystemApi 8162 @RequiresApi(Build.VERSION_CODES.TIRAMISU) removeWifiLowLatencyLockListener(@onNull WifiLowLatencyLockListener listener)8163 public void removeWifiLowLatencyLockListener(@NonNull WifiLowLatencyLockListener listener) { 8164 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 8165 if (mVerboseLoggingEnabled) { 8166 Log.d(TAG, "removeWifiLowLatencyLockListener: listener=" + listener); 8167 } 8168 final int listenerIdentifier = System.identityHashCode(listener); 8169 synchronized (sWifiLowLatencyLockListenerMap) { 8170 try { 8171 if (!sWifiLowLatencyLockListenerMap.contains(listenerIdentifier)) { 8172 Log.w(TAG, "Unknown external listener " + listenerIdentifier); 8173 return; 8174 } 8175 mService.removeWifiLowLatencyLockListener( 8176 sWifiLowLatencyLockListenerMap.get(listenerIdentifier)); 8177 8178 } catch (RemoteException e) { 8179 throw e.rethrowFromSystemServer(); 8180 } finally { 8181 sWifiLowLatencyLockListenerMap.remove(listenerIdentifier); 8182 } 8183 } 8184 } 8185 8186 /** 8187 * Creates a new WifiLock. 8188 * 8189 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 8190 * never shown to the user under normal conditions, but should be descriptive 8191 * enough to identify your application and the specific WifiLock within it, if it 8192 * holds multiple WifiLocks. 8193 * 8194 * @return a new, unacquired WifiLock with the given tag. 8195 * 8196 * @see WifiLock 8197 * 8198 * @deprecated This API is non-functional. 8199 */ 8200 @Deprecated createWifiLock(String tag)8201 public WifiLock createWifiLock(String tag) { 8202 return new WifiLock(WIFI_MODE_FULL, tag); 8203 } 8204 8205 /** 8206 * Create a new MulticastLock 8207 * 8208 * @param tag a tag for the MulticastLock to identify it in debugging 8209 * messages. This string is never shown to the user under 8210 * normal conditions, but should be descriptive enough to 8211 * identify your application and the specific MulticastLock 8212 * within it, if it holds multiple MulticastLocks. 8213 * 8214 * @return a new, unacquired MulticastLock with the given tag. 8215 * 8216 * @see MulticastLock 8217 */ createMulticastLock(String tag)8218 public MulticastLock createMulticastLock(String tag) { 8219 return new MulticastLock(tag); 8220 } 8221 8222 /** 8223 * Allows an application to receive Wifi Multicast packets. 8224 * Normally the Wifi stack filters out packets not explicitly 8225 * addressed to this device. Acquring a MulticastLock will 8226 * cause the stack to receive packets addressed to multicast 8227 * addresses. Processing these extra packets can cause a noticeable 8228 * battery drain and should be disabled when not needed. 8229 */ 8230 public class MulticastLock { 8231 private String mTag; 8232 private final IBinder mBinder; 8233 private int mRefCount; 8234 private boolean mRefCounted; 8235 private boolean mHeld; 8236 MulticastLock(String tag)8237 private MulticastLock(String tag) { 8238 mTag = tag; 8239 mBinder = new Binder(); 8240 mRefCount = 0; 8241 mRefCounted = true; 8242 mHeld = false; 8243 } 8244 8245 /** 8246 * Locks Wifi Multicast on until {@link #release} is called. 8247 * 8248 * If this MulticastLock is reference-counted each call to 8249 * {@code acquire} will increment the reference count, and the 8250 * wifi interface will receive multicast packets as long as the 8251 * reference count is above zero. 8252 * 8253 * If this MulticastLock is not reference-counted, the first call to 8254 * {@code acquire} will turn on the multicast packets, but subsequent 8255 * calls will be ignored. Only one call to {@link #release} will 8256 * be required, regardless of the number of times that {@code acquire} 8257 * is called. 8258 * 8259 * Note that other applications may also lock Wifi Multicast on. 8260 * Only they can relinquish their lock. 8261 * 8262 * Also note that applications cannot leave Multicast locked on. 8263 * When an app exits or crashes, any Multicast locks will be released. 8264 */ acquire()8265 public void acquire() { 8266 synchronized (mBinder) { 8267 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 8268 try { 8269 mService.acquireMulticastLock(mBinder, mTag); 8270 synchronized (WifiManager.this) { 8271 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 8272 mService.releaseMulticastLock(mTag); 8273 throw new UnsupportedOperationException( 8274 "Exceeded maximum number of wifi locks"); 8275 } 8276 mActiveLockCount++; 8277 } 8278 } catch (RemoteException e) { 8279 throw e.rethrowFromSystemServer(); 8280 } 8281 mHeld = true; 8282 } 8283 } 8284 } 8285 8286 /** 8287 * Unlocks Wifi Multicast, restoring the filter of packets 8288 * not addressed specifically to this device and saving power. 8289 * 8290 * If this MulticastLock is reference-counted, each call to 8291 * {@code release} will decrement the reference count, and the 8292 * multicast packets will only stop being received when the reference 8293 * count reaches zero. If the reference count goes below zero (that 8294 * is, if {@code release} is called a greater number of times than 8295 * {@link #acquire}), an exception is thrown. 8296 * 8297 * If this MulticastLock is not reference-counted, the first call to 8298 * {@code release} (after the radio was multicast locked using 8299 * {@link #acquire}) will unlock the multicast, and subsequent calls 8300 * will be ignored. 8301 * 8302 * Note that if any other Wifi Multicast Locks are still outstanding 8303 * this {@code release} call will not have an immediate effect. Only 8304 * when all applications have released all their Multicast Locks will 8305 * the Multicast filter be turned back on. 8306 * 8307 * Also note that when an app exits or crashes all of its Multicast 8308 * Locks will be automatically released. 8309 */ release()8310 public void release() { 8311 synchronized (mBinder) { 8312 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 8313 try { 8314 mService.releaseMulticastLock(mTag); 8315 synchronized (WifiManager.this) { 8316 mActiveLockCount--; 8317 } 8318 } catch (RemoteException e) { 8319 throw e.rethrowFromSystemServer(); 8320 } 8321 mHeld = false; 8322 } 8323 if (mRefCount < 0) { 8324 throw new RuntimeException("MulticastLock under-locked " 8325 + mTag); 8326 } 8327 } 8328 } 8329 8330 /** 8331 * Controls whether this is a reference-counted or non-reference- 8332 * counted MulticastLock. 8333 * 8334 * Reference-counted MulticastLocks keep track of the number of calls 8335 * to {@link #acquire} and {@link #release}, and only stop the 8336 * reception of multicast packets when every call to {@link #acquire} 8337 * has been balanced with a call to {@link #release}. Non-reference- 8338 * counted MulticastLocks allow the reception of multicast packets 8339 * whenever {@link #acquire} is called and stop accepting multicast 8340 * packets whenever {@link #release} is called. 8341 * 8342 * @param refCounted true if this MulticastLock should keep a reference 8343 * count 8344 */ setReferenceCounted(boolean refCounted)8345 public void setReferenceCounted(boolean refCounted) { 8346 mRefCounted = refCounted; 8347 } 8348 8349 /** 8350 * Checks whether this MulticastLock is currently held. 8351 * 8352 * @return true if this MulticastLock is held, false otherwise 8353 */ isHeld()8354 public boolean isHeld() { 8355 synchronized (mBinder) { 8356 return mHeld; 8357 } 8358 } 8359 toString()8360 public String toString() { 8361 String s1, s2, s3; 8362 synchronized (mBinder) { 8363 s1 = Integer.toHexString(System.identityHashCode(this)); 8364 s2 = mHeld ? "held; " : ""; 8365 if (mRefCounted) { 8366 s3 = "refcounted: refcount = " + mRefCount; 8367 } else { 8368 s3 = "not refcounted"; 8369 } 8370 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 8371 } 8372 } 8373 8374 @Override finalize()8375 protected void finalize() throws Throwable { 8376 super.finalize(); 8377 setReferenceCounted(false); 8378 release(); 8379 } 8380 } 8381 8382 /** 8383 * Check multicast filter status. 8384 * 8385 * @return true if multicast packets are allowed. 8386 * 8387 * @hide pending API council approval 8388 */ isMulticastEnabled()8389 public boolean isMulticastEnabled() { 8390 try { 8391 return mService.isMulticastEnabled(); 8392 } catch (RemoteException e) { 8393 throw e.rethrowFromSystemServer(); 8394 } 8395 } 8396 8397 /** 8398 * Initialize the multicast filtering to 'on' 8399 * @hide no intent to publish 8400 */ 8401 @UnsupportedAppUsage initializeMulticastFiltering()8402 public boolean initializeMulticastFiltering() { 8403 try { 8404 mService.initializeMulticastFiltering(); 8405 return true; 8406 } catch (RemoteException e) { 8407 throw e.rethrowFromSystemServer(); 8408 } 8409 } 8410 8411 /** 8412 * Set Wi-Fi verbose logging level from developer settings. 8413 * 8414 * @param enable true to enable verbose logging, false to disable. 8415 * 8416 * @hide 8417 */ 8418 @SystemApi 8419 @RequiresPermission(anyOf = { 8420 android.Manifest.permission.NETWORK_SETTINGS, 8421 android.Manifest.permission.DUMP 8422 }) setVerboseLoggingEnabled(boolean enable)8423 public void setVerboseLoggingEnabled(boolean enable) { 8424 enableVerboseLogging(enable ? VERBOSE_LOGGING_LEVEL_ENABLED 8425 : VERBOSE_LOGGING_LEVEL_DISABLED); 8426 } 8427 8428 /** 8429 * Set Wi-Fi verbose logging level from developer settings. 8430 * 8431 * @param verbose the verbose logging mode which could be 8432 * {@link #VERBOSE_LOGGING_LEVEL_DISABLED}, {@link #VERBOSE_LOGGING_LEVEL_ENABLED}, or 8433 * {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}. 8434 * 8435 * @hide 8436 */ 8437 @SystemApi 8438 @RequiresPermission(anyOf = { 8439 android.Manifest.permission.NETWORK_SETTINGS, 8440 android.Manifest.permission.DUMP 8441 }) setVerboseLoggingLevel(@erboseLoggingLevel int verbose)8442 public void setVerboseLoggingLevel(@VerboseLoggingLevel int verbose) { 8443 enableVerboseLogging(verbose); 8444 } 8445 8446 /** @hide */ 8447 @UnsupportedAppUsage( 8448 maxTargetSdk = Build.VERSION_CODES.Q, 8449 publicAlternatives = "Use {@code #setVerboseLoggingEnabled(boolean)} instead." 8450 ) 8451 @RequiresPermission(anyOf = { 8452 android.Manifest.permission.NETWORK_SETTINGS, 8453 android.Manifest.permission.DUMP 8454 }) enableVerboseLogging(@erboseLoggingLevel int verbose)8455 public void enableVerboseLogging(@VerboseLoggingLevel int verbose) { 8456 try { 8457 mService.enableVerboseLogging(verbose); 8458 mVerboseLoggingEnabled = 8459 verbose == VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY 8460 || verbose == VERBOSE_LOGGING_LEVEL_ENABLED; 8461 } catch (RemoteException e) { 8462 throw e.rethrowFromSystemServer(); 8463 } 8464 } 8465 8466 /** 8467 * Get the persisted Wi-Fi verbose logging level, set by 8468 * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}. 8469 * No permissions are required to call this method. 8470 * 8471 * @return true to indicate that verbose logging is enabled, false to indicate that verbose 8472 * logging is disabled. 8473 * 8474 * @hide 8475 */ 8476 @SystemApi isVerboseLoggingEnabled()8477 public boolean isVerboseLoggingEnabled() { 8478 int verboseLoggingLevel = getVerboseLoggingLevel(); 8479 return verboseLoggingLevel == VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY 8480 || verboseLoggingLevel == VERBOSE_LOGGING_LEVEL_ENABLED; 8481 } 8482 8483 /** 8484 * Get the persisted Wi-Fi verbose logging level, set by 8485 * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}. 8486 * No permissions are required to call this method. 8487 * 8488 * @return one of {@link #VERBOSE_LOGGING_LEVEL_DISABLED}, 8489 * {@link #VERBOSE_LOGGING_LEVEL_ENABLED}, 8490 * or {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}. 8491 * 8492 * @hide 8493 */ 8494 @SystemApi getVerboseLoggingLevel()8495 public @VerboseLoggingLevel int getVerboseLoggingLevel() { 8496 try { 8497 return mService.getVerboseLoggingLevel(); 8498 } catch (RemoteException e) { 8499 throw e.rethrowFromSystemServer(); 8500 } 8501 } 8502 8503 /** 8504 * Removes all saved Wi-Fi networks, Passpoint configurations, ephemeral networks, Network 8505 * Requests, and Network Suggestions. 8506 * 8507 * @hide 8508 */ 8509 @SystemApi 8510 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) factoryReset()8511 public void factoryReset() { 8512 try { 8513 mService.factoryReset(mContext.getOpPackageName()); 8514 } catch (RemoteException e) { 8515 throw e.rethrowFromSystemServer(); 8516 } 8517 } 8518 8519 /** 8520 * Get {@link Network} object of current wifi network, or null if not connected. 8521 * @hide 8522 */ 8523 @Nullable 8524 @SystemApi 8525 @RequiresPermission(anyOf = { 8526 android.Manifest.permission.NETWORK_SETTINGS, 8527 android.Manifest.permission.NETWORK_SETUP_WIZARD 8528 }) getCurrentNetwork()8529 public Network getCurrentNetwork() { 8530 try { 8531 return mService.getCurrentNetwork(); 8532 } catch (RemoteException e) { 8533 throw e.rethrowFromSystemServer(); 8534 } 8535 } 8536 8537 /** 8538 * Deprecated 8539 * returns false 8540 * @hide 8541 * @deprecated 8542 */ setEnableAutoJoinWhenAssociated(boolean enabled)8543 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 8544 return false; 8545 } 8546 8547 /** 8548 * Deprecated 8549 * returns false 8550 * @hide 8551 * @deprecated 8552 */ getEnableAutoJoinWhenAssociated()8553 public boolean getEnableAutoJoinWhenAssociated() { 8554 return false; 8555 } 8556 8557 /** 8558 * Returns a byte stream representing the data that needs to be backed up to save the 8559 * current Wifi state. 8560 * This Wifi state can be restored by calling {@link #restoreWifiBackupData(byte[])}. 8561 * @hide 8562 */ 8563 @SystemApi 8564 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 8565 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) 8566 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) retrieveWifiBackupData(@onNull @allbackExecutor Executor executor, @NonNull Consumer<byte[]> resultsCallback)8567 public void retrieveWifiBackupData(@NonNull @CallbackExecutor Executor executor, 8568 @NonNull Consumer<byte[]> resultsCallback) { 8569 if (!SdkLevel.isAtLeastV()) { 8570 throw new UnsupportedOperationException(); 8571 } 8572 8573 Objects.requireNonNull(executor, "executor cannot be null"); 8574 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 8575 try { 8576 mService.retrieveWifiBackupData( 8577 new IByteArrayListener.Stub() { 8578 @Override 8579 public void onResult(byte[] value) { 8580 Binder.clearCallingIdentity(); 8581 executor.execute(() -> { 8582 resultsCallback.accept(value); 8583 }); 8584 } 8585 }); 8586 } catch (RemoteException e) { 8587 throw e.rethrowFromSystemServer(); 8588 } 8589 } 8590 8591 /** 8592 * Restore state from the backed up data. 8593 * @param data byte stream in the same format produced by {@link #retrieveWifiBackupData()} 8594 * @hide 8595 */ 8596 @SystemApi 8597 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 8598 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) 8599 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) restoreWifiBackupData(@onNull byte[] data)8600 public void restoreWifiBackupData(@NonNull byte[] data) { 8601 if (!SdkLevel.isAtLeastV()) { 8602 throw new UnsupportedOperationException(); 8603 } 8604 try { 8605 mService.restoreWifiBackupData(data); 8606 } catch (RemoteException e) { 8607 throw e.rethrowFromSystemServer(); 8608 } 8609 } 8610 8611 /** 8612 * Returns a byte stream representing the data that needs to be backed up to save the 8613 * current Wifi state. 8614 * This Wifi state can be restored by calling {@link #restoreBackupData(byte[])}. 8615 * @hide 8616 */ 8617 @NonNull 8618 @SystemApi 8619 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) retrieveBackupData()8620 public byte[] retrieveBackupData() { 8621 try { 8622 return mService.retrieveBackupData(); 8623 } catch (RemoteException e) { 8624 throw e.rethrowFromSystemServer(); 8625 } 8626 } 8627 8628 /** 8629 * Restore state from the backed up data. 8630 * @param data byte stream in the same format produced by {@link #retrieveBackupData()} 8631 * @hide 8632 */ 8633 @SystemApi 8634 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreBackupData(@onNull byte[] data)8635 public void restoreBackupData(@NonNull byte[] data) { 8636 try { 8637 mService.restoreBackupData(data); 8638 } catch (RemoteException e) { 8639 throw e.rethrowFromSystemServer(); 8640 } 8641 } 8642 8643 /** 8644 * Returns a byte stream representing the data that needs to be backed up to save the 8645 * current soft ap config data. 8646 * 8647 * This soft ap config can be restored by calling {@link #restoreSoftApBackupData(byte[])} 8648 * @hide 8649 */ 8650 @NonNull 8651 @SystemApi 8652 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) retrieveSoftApBackupData()8653 public byte[] retrieveSoftApBackupData() { 8654 try { 8655 return mService.retrieveSoftApBackupData(); 8656 } catch (RemoteException e) { 8657 throw e.rethrowFromSystemServer(); 8658 } 8659 } 8660 8661 /** 8662 * Returns soft ap config from the backed up data or null if data is invalid. 8663 * @param data byte stream in the same format produced by {@link #retrieveSoftApBackupData()} 8664 * 8665 * @hide 8666 */ 8667 @Nullable 8668 @SystemApi 8669 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreSoftApBackupData(@onNull byte[] data)8670 public SoftApConfiguration restoreSoftApBackupData(@NonNull byte[] data) { 8671 try { 8672 return mService.restoreSoftApBackupData(data); 8673 } catch (RemoteException e) { 8674 throw e.rethrowFromSystemServer(); 8675 } 8676 } 8677 8678 /** 8679 * Restore state from the older version of back up data. 8680 * The old backup data was essentially a backup of wpa_supplicant.conf 8681 * and ipconfig.txt file. 8682 * @param supplicantData bytes representing wpa_supplicant.conf 8683 * @param ipConfigData bytes representing ipconfig.txt 8684 * @hide 8685 */ 8686 @SystemApi 8687 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreSupplicantBackupData( @onNull byte[] supplicantData, @NonNull byte[] ipConfigData)8688 public void restoreSupplicantBackupData( 8689 @NonNull byte[] supplicantData, @NonNull byte[] ipConfigData) { 8690 try { 8691 mService.restoreSupplicantBackupData(supplicantData, ipConfigData); 8692 } catch (RemoteException e) { 8693 throw e.rethrowFromSystemServer(); 8694 } 8695 } 8696 8697 /** 8698 * Start subscription provisioning flow 8699 * 8700 * @param provider {@link OsuProvider} to provision with 8701 * @param executor the Executor on which to run the callback. 8702 * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow 8703 * @hide 8704 */ 8705 @SystemApi 8706 @RequiresPermission(anyOf = { 8707 android.Manifest.permission.NETWORK_SETTINGS, 8708 android.Manifest.permission.NETWORK_SETUP_WIZARD 8709 }) startSubscriptionProvisioning(@onNull OsuProvider provider, @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback)8710 public void startSubscriptionProvisioning(@NonNull OsuProvider provider, 8711 @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback) { 8712 // Verify arguments 8713 if (executor == null) { 8714 throw new IllegalArgumentException("executor must not be null"); 8715 } 8716 if (callback == null) { 8717 throw new IllegalArgumentException("callback must not be null"); 8718 } 8719 try { 8720 mService.startSubscriptionProvisioning(provider, 8721 new ProvisioningCallbackProxy(executor, callback)); 8722 } catch (RemoteException e) { 8723 throw e.rethrowFromSystemServer(); 8724 } 8725 } 8726 8727 /** 8728 * Helper class to support OSU Provisioning callbacks 8729 */ 8730 private static class ProvisioningCallbackProxy extends IProvisioningCallback.Stub { 8731 private final Executor mExecutor; 8732 private final ProvisioningCallback mCallback; 8733 ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback)8734 ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback) { 8735 mExecutor = executor; 8736 mCallback = callback; 8737 } 8738 8739 @Override onProvisioningStatus(int status)8740 public void onProvisioningStatus(int status) { 8741 mExecutor.execute(() -> mCallback.onProvisioningStatus(status)); 8742 } 8743 8744 @Override onProvisioningFailure(int status)8745 public void onProvisioningFailure(int status) { 8746 mExecutor.execute(() -> mCallback.onProvisioningFailure(status)); 8747 } 8748 8749 @Override onProvisioningComplete()8750 public void onProvisioningComplete() { 8751 mExecutor.execute(() -> mCallback.onProvisioningComplete()); 8752 } 8753 } 8754 8755 /** 8756 * Interface for Traffic state callback. Should be extended by applications and set when 8757 * calling {@link #registerTrafficStateCallback(Executor, WifiManager.TrafficStateCallback)}. 8758 * @hide 8759 */ 8760 @SystemApi 8761 public interface TrafficStateCallback { 8762 /** @hide */ 8763 @Retention(RetentionPolicy.SOURCE) 8764 @IntDef(prefix = {"DATA_ACTIVITY_"}, value = { 8765 DATA_ACTIVITY_NONE, 8766 DATA_ACTIVITY_IN, 8767 DATA_ACTIVITY_OUT, 8768 DATA_ACTIVITY_INOUT}) 8769 @interface DataActivity {} 8770 8771 // Lowest bit indicates data reception and the second lowest bit indicates data transmitted 8772 /** No data in or out */ 8773 int DATA_ACTIVITY_NONE = 0x00; 8774 /** Data in, no data out */ 8775 int DATA_ACTIVITY_IN = 0x01; 8776 /** Data out, no data in */ 8777 int DATA_ACTIVITY_OUT = 0x02; 8778 /** Data in and out */ 8779 int DATA_ACTIVITY_INOUT = 0x03; 8780 8781 /** 8782 * Callback invoked to inform clients about the current traffic state. 8783 * 8784 * @param state One of the values: {@link #DATA_ACTIVITY_NONE}, {@link #DATA_ACTIVITY_IN}, 8785 * {@link #DATA_ACTIVITY_OUT} & {@link #DATA_ACTIVITY_INOUT}. 8786 */ onStateChanged(@ataActivity int state)8787 void onStateChanged(@DataActivity int state); 8788 } 8789 8790 /** 8791 * Callback proxy for TrafficStateCallback objects. 8792 * 8793 * @hide 8794 */ 8795 private class TrafficStateCallbackProxy extends ITrafficStateCallback.Stub { 8796 private final Executor mExecutor; 8797 private final TrafficStateCallback mCallback; 8798 TrafficStateCallbackProxy(Executor executor, TrafficStateCallback callback)8799 TrafficStateCallbackProxy(Executor executor, TrafficStateCallback callback) { 8800 mExecutor = executor; 8801 mCallback = callback; 8802 } 8803 8804 @Override onStateChanged(int state)8805 public void onStateChanged(int state) { 8806 if (mVerboseLoggingEnabled) { 8807 Log.v(TAG, "TrafficStateCallbackProxy: onStateChanged state=" + state); 8808 } 8809 Binder.clearCallingIdentity(); 8810 mExecutor.execute(() -> { 8811 mCallback.onStateChanged(state); 8812 }); 8813 } 8814 } 8815 8816 /** 8817 * Registers a callback for monitoring traffic state. See {@link TrafficStateCallback}. These 8818 * callbacks will be invoked periodically by platform to inform clients about the current 8819 * traffic state. Caller can unregister a previously registered callback using 8820 * {@link #unregisterTrafficStateCallback(TrafficStateCallback)} 8821 * <p> 8822 * Applications should have the 8823 * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers 8824 * without the permission will trigger a {@link java.lang.SecurityException}. 8825 * <p> 8826 * 8827 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 8828 * object. 8829 * @param callback Callback for traffic state events 8830 * @hide 8831 */ 8832 @SystemApi 8833 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) registerTrafficStateCallback(@onNull @allbackExecutor Executor executor, @NonNull TrafficStateCallback callback)8834 public void registerTrafficStateCallback(@NonNull @CallbackExecutor Executor executor, 8835 @NonNull TrafficStateCallback callback) { 8836 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 8837 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 8838 Log.v(TAG, "registerTrafficStateCallback: callback=" + callback + ", executor=" + executor); 8839 8840 try { 8841 synchronized (sTrafficStateCallbackMap) { 8842 ITrafficStateCallback.Stub binderCallback = new TrafficStateCallbackProxy(executor, 8843 callback); 8844 sTrafficStateCallbackMap.put(System.identityHashCode(callback), binderCallback); 8845 mService.registerTrafficStateCallback(binderCallback); 8846 } 8847 } catch (RemoteException e) { 8848 throw e.rethrowFromSystemServer(); 8849 } 8850 } 8851 8852 /** 8853 * Allow callers to unregister a previously registered callback. After calling this method, 8854 * applications will no longer receive traffic state notifications. 8855 * 8856 * @param callback Callback to unregister for traffic state events 8857 * @hide 8858 */ 8859 @SystemApi 8860 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) unregisterTrafficStateCallback(@onNull TrafficStateCallback callback)8861 public void unregisterTrafficStateCallback(@NonNull TrafficStateCallback callback) { 8862 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 8863 Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback); 8864 8865 try { 8866 synchronized (sTrafficStateCallbackMap) { 8867 int callbackIdentifier = System.identityHashCode(callback); 8868 if (!sTrafficStateCallbackMap.contains(callbackIdentifier)) { 8869 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 8870 return; 8871 } 8872 mService.unregisterTrafficStateCallback( 8873 sTrafficStateCallbackMap.get(callbackIdentifier)); 8874 sTrafficStateCallbackMap.remove(callbackIdentifier); 8875 } 8876 } catch (RemoteException e) { 8877 throw e.rethrowFromSystemServer(); 8878 } 8879 } 8880 8881 /** 8882 * Helper method to update the local verbose logging flag based on the verbose logging 8883 * level from wifi service. 8884 */ updateVerboseLoggingEnabledFromService()8885 private void updateVerboseLoggingEnabledFromService() { 8886 mVerboseLoggingEnabled = isVerboseLoggingEnabled(); 8887 } 8888 8889 /** 8890 * @return true if this device supports WPA3-Personal SAE 8891 */ isWpa3SaeSupported()8892 public boolean isWpa3SaeSupported() { 8893 return isFeatureSupported(WIFI_FEATURE_WPA3_SAE); 8894 } 8895 8896 /** 8897 * @return true if this device supports WPA3-Enterprise Suite-B-192 8898 */ isWpa3SuiteBSupported()8899 public boolean isWpa3SuiteBSupported() { 8900 return isFeatureSupported(WIFI_FEATURE_WPA3_SUITE_B); 8901 } 8902 8903 /** 8904 * @return true if this device supports Wi-Fi Enhanced Open (OWE) 8905 */ isEnhancedOpenSupported()8906 public boolean isEnhancedOpenSupported() { 8907 return isFeatureSupported(WIFI_FEATURE_OWE); 8908 } 8909 8910 /** 8911 * Wi-Fi Easy Connect (DPP) introduces standardized mechanisms to simplify the provisioning and 8912 * configuration of Wi-Fi devices. 8913 * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and 8914 * search for "Easy Connect" or "Device Provisioning Protocol specification". 8915 * 8916 * @return true if this device supports Wi-Fi Easy-connect (Device Provisioning Protocol) 8917 */ isEasyConnectSupported()8918 public boolean isEasyConnectSupported() { 8919 return isFeatureSupported(WIFI_FEATURE_DPP); 8920 } 8921 8922 /** 8923 * @return true if this device supports Wi-Fi Easy Connect (DPP) Enrollee Responder mode. 8924 */ isEasyConnectEnrolleeResponderModeSupported()8925 public boolean isEasyConnectEnrolleeResponderModeSupported() { 8926 return isFeatureSupported(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER); 8927 } 8928 8929 /** 8930 * @return true if this device supports WAPI. 8931 */ isWapiSupported()8932 public boolean isWapiSupported() { 8933 return isFeatureSupported(WIFI_FEATURE_WAPI); 8934 } 8935 8936 /** 8937 * @return true if this device supports WPA3 SAE Public Key. 8938 */ isWpa3SaePublicKeySupported()8939 public boolean isWpa3SaePublicKeySupported() { 8940 // This feature is not fully implemented in the framework yet. 8941 // After the feature complete, it returns whether WIFI_FEATURE_SAE_PK 8942 // is supported or not directly. 8943 return false; 8944 } 8945 8946 /** 8947 * @return true if this device supports Wi-Fi Passpoint Terms and Conditions feature. 8948 */ isPasspointTermsAndConditionsSupported()8949 public boolean isPasspointTermsAndConditionsSupported() { 8950 return isFeatureSupported(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS); 8951 } 8952 8953 /** 8954 * @return true if this device supports WPA3 SAE Hash-to-Element. 8955 */ isWpa3SaeH2eSupported()8956 public boolean isWpa3SaeH2eSupported() { 8957 return isFeatureSupported(WIFI_FEATURE_SAE_H2E); 8958 } 8959 8960 /** 8961 * @return true if this device supports Wi-Fi Display R2. 8962 */ isWifiDisplayR2Supported()8963 public boolean isWifiDisplayR2Supported() { 8964 return isFeatureSupported(WIFI_FEATURE_WFD_R2); 8965 } 8966 8967 /** 8968 * @return true if this device supports RFC 7542 decorated identity. 8969 */ isDecoratedIdentitySupported()8970 public boolean isDecoratedIdentitySupported() { 8971 return isFeatureSupported(WIFI_FEATURE_DECORATED_IDENTITY); 8972 } 8973 8974 /** 8975 * @return true if this device supports Trust On First Use (TOFU). 8976 */ isTrustOnFirstUseSupported()8977 public boolean isTrustOnFirstUseSupported() { 8978 return isFeatureSupported(WIFI_FEATURE_TRUST_ON_FIRST_USE); 8979 } 8980 8981 /** 8982 * Wi-Fi Easy Connect DPP AKM enables provisioning and configuration of Wi-Fi devices without 8983 * the need of using the device PSK passphrase. 8984 * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and 8985 * search for "Easy Connect" or "Device Provisioning Protocol specification". 8986 * 8987 * @return true if this device supports Wi-Fi Easy-connect DPP (Device Provisioning Protocol) 8988 * AKM, false otherwise. 8989 */ isEasyConnectDppAkmSupported()8990 public boolean isEasyConnectDppAkmSupported() { 8991 return isFeatureSupported(WIFI_FEATURE_DPP_AKM); 8992 } 8993 8994 /** 8995 * Indicate that whether or not settings required TLS minimum version is supported. 8996 * 8997 * If the device doesn't support this capability, the minimum accepted TLS version is 1.0. 8998 * 8999 * @return true if this device supports setting TLS minimum version. 9000 */ isTlsMinimumVersionSupported()9001 public boolean isTlsMinimumVersionSupported() { 9002 return isFeatureSupported(WIFI_FEATURE_SET_TLS_MINIMUM_VERSION); 9003 } 9004 9005 /** 9006 * Indicate that whether or not TLS v1.3 is supported. 9007 * 9008 * If requested minimum is not supported, it will default to the maximum supported version. 9009 * 9010 * @return true if this device supports TLS v1.3. 9011 */ isTlsV13Supported()9012 public boolean isTlsV13Supported() { 9013 return isFeatureSupported(WIFI_FEATURE_TLS_V1_3); 9014 } 9015 9016 /** 9017 * @return true if this device supports Dual Band Simultaneous (DBS) operation. 9018 */ isDualBandSimultaneousSupported()9019 public boolean isDualBandSimultaneousSupported() { 9020 return isFeatureSupported(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS); 9021 } 9022 9023 /** 9024 * @return true if this device supports TID-To-Link Mapping Negotiation. 9025 */ isTidToLinkMappingNegotiationSupported()9026 public boolean isTidToLinkMappingNegotiationSupported() { 9027 return isFeatureSupported(WIFI_FEATURE_T2LM_NEGOTIATION); 9028 } 9029 9030 9031 /** 9032 * @return true if this device supports connections to Wi-Fi WEP networks. 9033 */ 9034 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) isWepSupported()9035 public boolean isWepSupported() { 9036 return isFeatureSupported(WIFI_FEATURE_WEP); 9037 } 9038 9039 /** 9040 * @return true if this device supports connections to Wi-Fi WPA-Personal networks. 9041 * 9042 * Note that this is the older and less secure WPA-Personal protocol, not WPA2-Personal 9043 * or later protocols. 9044 */ 9045 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) isWpaPersonalSupported()9046 public boolean isWpaPersonalSupported() { 9047 return isFeatureSupported(WIFI_FEATURE_WPA_PERSONAL); 9048 } 9049 9050 /** 9051 * Gets the factory Wi-Fi MAC addresses. 9052 * @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array 9053 * if failed. 9054 * @hide 9055 */ 9056 @NonNull 9057 @SystemApi 9058 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) getFactoryMacAddresses()9059 public String[] getFactoryMacAddresses() { 9060 try { 9061 return mService.getFactoryMacAddresses(); 9062 } catch (RemoteException e) { 9063 throw e.rethrowFromSystemServer(); 9064 } 9065 } 9066 9067 /** @hide */ 9068 @Retention(RetentionPolicy.SOURCE) 9069 @IntDef(prefix = {"DEVICE_MOBILITY_STATE_"}, value = { 9070 DEVICE_MOBILITY_STATE_UNKNOWN, 9071 DEVICE_MOBILITY_STATE_HIGH_MVMT, 9072 DEVICE_MOBILITY_STATE_LOW_MVMT, 9073 DEVICE_MOBILITY_STATE_STATIONARY}) 9074 public @interface DeviceMobilityState {} 9075 9076 /** 9077 * Unknown device mobility state 9078 * 9079 * @see #setDeviceMobilityState(int) 9080 * 9081 * @hide 9082 */ 9083 @SystemApi 9084 public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0; 9085 9086 /** 9087 * High movement device mobility state. 9088 * e.g. on a bike, in a motor vehicle 9089 * 9090 * @see #setDeviceMobilityState(int) 9091 * 9092 * @hide 9093 */ 9094 @SystemApi 9095 public static final int DEVICE_MOBILITY_STATE_HIGH_MVMT = 1; 9096 9097 /** 9098 * Low movement device mobility state. 9099 * e.g. walking, running 9100 * 9101 * @see #setDeviceMobilityState(int) 9102 * 9103 * @hide 9104 */ 9105 @SystemApi 9106 public static final int DEVICE_MOBILITY_STATE_LOW_MVMT = 2; 9107 9108 /** 9109 * Stationary device mobility state 9110 * 9111 * @see #setDeviceMobilityState(int) 9112 * 9113 * @hide 9114 */ 9115 @SystemApi 9116 public static final int DEVICE_MOBILITY_STATE_STATIONARY = 3; 9117 9118 /** 9119 * Updates the device mobility state. Wifi uses this information to adjust the interval between 9120 * Wifi scans in order to balance power consumption with scan accuracy. 9121 * The default mobility state when the device boots is {@link #DEVICE_MOBILITY_STATE_UNKNOWN}. 9122 * This API should be called whenever there is a change in the mobility state. 9123 * @param state the updated device mobility state 9124 * @hide 9125 */ 9126 @SystemApi 9127 @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) setDeviceMobilityState(@eviceMobilityState int state)9128 public void setDeviceMobilityState(@DeviceMobilityState int state) { 9129 try { 9130 mService.setDeviceMobilityState(state); 9131 } catch (RemoteException e) { 9132 throw e.rethrowFromSystemServer(); 9133 } 9134 } 9135 9136 /* Easy Connect - AKA Device Provisioning Protocol (DPP) */ 9137 9138 /** 9139 * Easy Connect Network role: Station. 9140 * 9141 * @hide 9142 */ 9143 @SystemApi 9144 public static final int EASY_CONNECT_NETWORK_ROLE_STA = 0; 9145 9146 /** 9147 * Easy Connect Network role: Access Point. 9148 * 9149 * @hide 9150 */ 9151 @SystemApi 9152 public static final int EASY_CONNECT_NETWORK_ROLE_AP = 1; 9153 9154 /** @hide */ 9155 @IntDef(prefix = {"EASY_CONNECT_NETWORK_ROLE_"}, value = { 9156 EASY_CONNECT_NETWORK_ROLE_STA, 9157 EASY_CONNECT_NETWORK_ROLE_AP, 9158 }) 9159 @Retention(RetentionPolicy.SOURCE) 9160 public @interface EasyConnectNetworkRole { 9161 } 9162 9163 /** Easy Connect Device information maximum allowed length */ 9164 private static final int EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH = 40; 9165 9166 /** 9167 * Easy Connect Cryptography Curve name: prime256v1 9168 * 9169 * @hide 9170 */ 9171 @SystemApi 9172 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1 = 0; 9173 9174 /** 9175 * Easy Connect Cryptography Curve name: secp384r1 9176 * 9177 * @hide 9178 */ 9179 @SystemApi 9180 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1 = 1; 9181 9182 /** 9183 * Easy Connect Cryptography Curve name: secp521r1 9184 * 9185 * @hide 9186 */ 9187 @SystemApi 9188 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1 = 2; 9189 9190 9191 /** 9192 * Easy Connect Cryptography Curve name: brainpoolP256r1 9193 * 9194 * @hide 9195 */ 9196 @SystemApi 9197 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1 = 3; 9198 9199 9200 /** 9201 * Easy Connect Cryptography Curve name: brainpoolP384r1 9202 * 9203 * @hide 9204 */ 9205 @SystemApi 9206 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1 = 4; 9207 9208 9209 /** 9210 * Easy Connect Cryptography Curve name: brainpoolP512r1 9211 * 9212 * @hide 9213 */ 9214 @SystemApi 9215 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1 = 5; 9216 9217 /** @hide */ 9218 @IntDef(prefix = {"EASY_CONNECT_CRYPTOGRAPHY_CURVE_"}, value = { 9219 EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1, 9220 EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1, 9221 EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1, 9222 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1, 9223 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1, 9224 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1, 9225 }) 9226 @Retention(RetentionPolicy.SOURCE) 9227 public @interface EasyConnectCryptographyCurve { 9228 } 9229 9230 /** 9231 * Verbose logging mode: DISABLED. 9232 * @hide 9233 */ 9234 @SystemApi 9235 public static final int VERBOSE_LOGGING_LEVEL_DISABLED = 0; 9236 9237 /** 9238 * Verbose logging mode: ENABLED. 9239 * @hide 9240 */ 9241 @SystemApi 9242 public static final int VERBOSE_LOGGING_LEVEL_ENABLED = 1; 9243 9244 /** 9245 * Verbose logging mode: ENABLED_SHOW_KEY. This mode causes the Wi-Fi password and encryption 9246 * keys to be output to the logcat. This is security sensitive information useful for debugging. 9247 * This configuration is enabled for 30 seconds and then falls back to the regular verbose mode 9248 * (i.e. to {@link VERBOSE_LOGGING_LEVEL_ENABLED}). Show key mode is not persistent, i.e. 9249 * rebooting the device would fallback to the regular verbose mode. 9250 * 9251 * @hide 9252 */ 9253 @SystemApi public static final int VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY = 2; 9254 9255 /** 9256 * Verbose logging mode: only enable for Wi-Fi Aware feature. 9257 * 9258 * @hide 9259 */ 9260 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 9261 @SystemApi 9262 public static final int VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY = 3; 9263 9264 /** @hide */ 9265 @IntDef(prefix = {"VERBOSE_LOGGING_LEVEL_"}, value = { 9266 VERBOSE_LOGGING_LEVEL_DISABLED, 9267 VERBOSE_LOGGING_LEVEL_ENABLED, 9268 VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY, 9269 VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY, 9270 }) 9271 @Retention(RetentionPolicy.SOURCE) 9272 public @interface VerboseLoggingLevel { 9273 } 9274 9275 /** 9276 * Start Easy Connect (DPP) in Configurator-Initiator role. The current device will initiate 9277 * Easy Connect bootstrapping with a peer, and configure the peer with the SSID and password of 9278 * the specified network using the Easy Connect protocol on an encrypted link. 9279 * 9280 * @param enrolleeUri URI of the Enrollee obtained separately (e.g. QR code scanning) 9281 * @param selectedNetworkId Selected network ID to be sent to the peer 9282 * @param enrolleeNetworkRole The network role of the enrollee 9283 * @param callback Callback for status updates 9284 * @param executor The Executor on which to run the callback. 9285 * @hide 9286 */ 9287 @SystemApi 9288 @RequiresPermission(anyOf = { 9289 android.Manifest.permission.NETWORK_SETTINGS, 9290 android.Manifest.permission.NETWORK_SETUP_WIZARD}) startEasyConnectAsConfiguratorInitiator(@onNull String enrolleeUri, int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)9291 public void startEasyConnectAsConfiguratorInitiator(@NonNull String enrolleeUri, 9292 int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole, 9293 @NonNull @CallbackExecutor Executor executor, 9294 @NonNull EasyConnectStatusCallback callback) { 9295 Binder binder = new Binder(); 9296 try { 9297 mService.startDppAsConfiguratorInitiator(binder, mContext.getOpPackageName(), 9298 enrolleeUri, selectedNetworkId, enrolleeNetworkRole, 9299 new EasyConnectCallbackProxy(executor, callback)); 9300 } catch (RemoteException e) { 9301 throw e.rethrowFromSystemServer(); 9302 } 9303 } 9304 9305 /** 9306 * Start Easy Connect (DPP) in Enrollee-Initiator role. The current device will initiate Easy 9307 * Connect bootstrapping with a peer, and receive the SSID and password from the peer 9308 * configurator. 9309 * 9310 * @param configuratorUri URI of the Configurator obtained separately (e.g. QR code scanning) 9311 * @param callback Callback for status updates 9312 * @param executor The Executor on which to run the callback. 9313 * @hide 9314 */ 9315 @SystemApi 9316 @RequiresPermission(anyOf = { 9317 android.Manifest.permission.NETWORK_SETTINGS, 9318 android.Manifest.permission.NETWORK_SETUP_WIZARD}) startEasyConnectAsEnrolleeInitiator(@onNull String configuratorUri, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)9319 public void startEasyConnectAsEnrolleeInitiator(@NonNull String configuratorUri, 9320 @NonNull @CallbackExecutor Executor executor, 9321 @NonNull EasyConnectStatusCallback callback) { 9322 Binder binder = new Binder(); 9323 try { 9324 mService.startDppAsEnrolleeInitiator(binder, configuratorUri, 9325 new EasyConnectCallbackProxy(executor, callback)); 9326 } catch (RemoteException e) { 9327 throw e.rethrowFromSystemServer(); 9328 } 9329 } 9330 9331 /** 9332 * Start Easy Connect (DPP) in Enrollee-Responder role. 9333 * The device will: 9334 * 1. Generate a DPP bootstrap URI and return it using the 9335 * {@link EasyConnectStatusCallback#onBootstrapUriGenerated(Uri)} method. 9336 * 2. Start DPP as a Responder, waiting for an Initiator device to start the DPP 9337 * authentication process. 9338 * The caller should use the URI provided in step #1, for instance display it as a QR code 9339 * or communicate it in some other way to the initiator device. 9340 * 9341 * @param deviceInfo Device specific information to add to the DPP URI. This field allows 9342 * the users of the configurators to identify the device. 9343 * Optional - if not provided or in case of an empty string, 9344 * Info field (I:) will be skipped in the generated DPP URI. 9345 * Allowed Range of ASCII characters in deviceInfo - %x20-7E. 9346 * semicolon and space are not allowed. Due to the limitation of maximum 9347 * allowed characters in QR code, framework adds a limit to maximum 9348 * characters in deviceInfo. Users must call 9349 * {@link WifiManager#getEasyConnectMaxAllowedResponderDeviceInfoLength() 9350 * } method to know max allowed length. Violation of these rules will 9351 * result in an exception. 9352 * @param curve Elliptic curve cryptography used to generate DPP 9353 * public/private key pair. If application is not interested in a 9354 * specific curve, use specification mandated NIST P-256 elliptic curve, 9355 * {@link WifiManager#EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1}. 9356 * @param callback Callback for status updates 9357 * @param executor The Executor on which to run the callback. 9358 * @hide 9359 */ 9360 @SystemApi 9361 @RequiresPermission(anyOf = { 9362 android.Manifest.permission.NETWORK_SETTINGS, 9363 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 9364 @RequiresApi(Build.VERSION_CODES.S) startEasyConnectAsEnrolleeResponder(@ullable String deviceInfo, @EasyConnectCryptographyCurve int curve, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)9365 public void startEasyConnectAsEnrolleeResponder(@Nullable String deviceInfo, 9366 @EasyConnectCryptographyCurve int curve, 9367 @NonNull @CallbackExecutor Executor executor, 9368 @NonNull EasyConnectStatusCallback callback) { 9369 Binder binder = new Binder(); 9370 try { 9371 mService.startDppAsEnrolleeResponder(binder, deviceInfo, curve, 9372 new EasyConnectCallbackProxy(executor, callback)); 9373 } catch (RemoteException e) { 9374 throw e.rethrowFromSystemServer(); 9375 } 9376 } 9377 9378 /** 9379 * Maximum allowed length of Device specific information that can be added to the URI of 9380 * Easy Connect responder device. 9381 * @see #startEasyConnectAsEnrolleeResponder(String, int, Executor, EasyConnectStatusCallback)} 9382 * 9383 * @hide 9384 */ 9385 @SystemApi getEasyConnectMaxAllowedResponderDeviceInfoLength()9386 public static int getEasyConnectMaxAllowedResponderDeviceInfoLength() { 9387 return EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH; 9388 } 9389 9390 /** 9391 * Stop or abort a current Easy Connect (DPP) session. This call, once processed, will 9392 * terminate any ongoing transaction, and clean up all associated resources. Caller should not 9393 * expect any callbacks once this call is made. However, due to the asynchronous nature of 9394 * this call, a callback may be fired if it was already pending in the queue. 9395 * 9396 * @hide 9397 */ 9398 @SystemApi 9399 @RequiresPermission(anyOf = { 9400 android.Manifest.permission.NETWORK_SETTINGS, 9401 android.Manifest.permission.NETWORK_SETUP_WIZARD}) stopEasyConnectSession()9402 public void stopEasyConnectSession() { 9403 try { 9404 /* Request lower layers to stop/abort and clear resources */ 9405 mService.stopDppSession(); 9406 } catch (RemoteException e) { 9407 throw e.rethrowFromSystemServer(); 9408 } 9409 } 9410 9411 /** 9412 * Helper class to support Easy Connect (DPP) callbacks 9413 * 9414 * @hide 9415 */ 9416 private static class EasyConnectCallbackProxy extends IDppCallback.Stub { 9417 private final Executor mExecutor; 9418 private final EasyConnectStatusCallback mEasyConnectStatusCallback; 9419 EasyConnectCallbackProxy(Executor executor, EasyConnectStatusCallback easyConnectStatusCallback)9420 EasyConnectCallbackProxy(Executor executor, 9421 EasyConnectStatusCallback easyConnectStatusCallback) { 9422 mExecutor = executor; 9423 mEasyConnectStatusCallback = easyConnectStatusCallback; 9424 } 9425 9426 @Override onSuccessConfigReceived(int newNetworkId)9427 public void onSuccessConfigReceived(int newNetworkId) { 9428 Log.d(TAG, "Easy Connect onSuccessConfigReceived callback"); 9429 Binder.clearCallingIdentity(); 9430 mExecutor.execute(() -> { 9431 mEasyConnectStatusCallback.onEnrolleeSuccess(newNetworkId); 9432 }); 9433 } 9434 9435 @Override onSuccess(int status)9436 public void onSuccess(int status) { 9437 Log.d(TAG, "Easy Connect onSuccess callback"); 9438 Binder.clearCallingIdentity(); 9439 mExecutor.execute(() -> { 9440 mEasyConnectStatusCallback.onConfiguratorSuccess(status); 9441 }); 9442 } 9443 9444 @Override onFailure(int status, String ssid, String channelList, int[] operatingClassArray)9445 public void onFailure(int status, String ssid, String channelList, 9446 int[] operatingClassArray) { 9447 Log.d(TAG, "Easy Connect onFailure callback"); 9448 Binder.clearCallingIdentity(); 9449 mExecutor.execute(() -> { 9450 SparseArray<int[]> channelListArray = parseDppChannelList(channelList); 9451 mEasyConnectStatusCallback.onFailure(status, ssid, channelListArray, 9452 operatingClassArray); 9453 }); 9454 } 9455 9456 @Override onProgress(int status)9457 public void onProgress(int status) { 9458 Log.d(TAG, "Easy Connect onProgress callback"); 9459 Binder.clearCallingIdentity(); 9460 mExecutor.execute(() -> { 9461 mEasyConnectStatusCallback.onProgress(status); 9462 }); 9463 } 9464 9465 @Override onBootstrapUriGenerated(@onNull String uri)9466 public void onBootstrapUriGenerated(@NonNull String uri) { 9467 Log.d(TAG, "Easy Connect onBootstrapUriGenerated callback"); 9468 if (!SdkLevel.isAtLeastS()) { 9469 Log.e(TAG, "Easy Connect bootstrap URI callback supported only on S+"); 9470 return; 9471 } 9472 Binder.clearCallingIdentity(); 9473 mExecutor.execute(() -> { 9474 mEasyConnectStatusCallback.onBootstrapUriGenerated(Uri.parse(uri)); 9475 }); 9476 } 9477 } 9478 9479 /** 9480 * Interface for Wi-Fi usability statistics listener. Should be implemented by applications and 9481 * set when calling {@link WifiManager#addOnWifiUsabilityStatsListener(Executor, 9482 * OnWifiUsabilityStatsListener)}. 9483 * 9484 * @hide 9485 */ 9486 @SystemApi 9487 public interface OnWifiUsabilityStatsListener { 9488 /** 9489 * Called when Wi-Fi usability statistics is updated. 9490 * 9491 * @param seqNum The sequence number of statistics, used to derive the timing of updated 9492 * Wi-Fi usability statistics, set by framework and incremented by one after 9493 * each update. 9494 * @param isSameBssidAndFreq The flag to indicate whether the BSSID and the frequency of 9495 * network stays the same or not relative to the last update of 9496 * Wi-Fi usability stats. 9497 * @param stats The updated Wi-Fi usability statistics. 9498 */ onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, @NonNull WifiUsabilityStatsEntry stats)9499 void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, 9500 @NonNull WifiUsabilityStatsEntry stats); 9501 } 9502 9503 /** 9504 * Interface for Wi-Fi verbose logging status listener. Should be implemented by applications 9505 * and set when calling {@link WifiManager#addWifiVerboseLoggingStatusListener(Executor, 9506 * WifiVerboseLoggingStatusListener)}. 9507 * 9508 * @hide 9509 */ 9510 @SystemApi 9511 public interface WifiVerboseLoggingStatusChangedListener { 9512 /** 9513 * Called when Wi-Fi verbose logging setting is updated. 9514 * 9515 * @param enabled true if verbose logging is enabled, false if verbose logging is disabled. 9516 */ onWifiVerboseLoggingStatusChanged(boolean enabled)9517 void onWifiVerboseLoggingStatusChanged(boolean enabled); 9518 } 9519 9520 /** 9521 * Adds a listener for Wi-Fi usability statistics. See {@link OnWifiUsabilityStatsListener}. 9522 * Multiple listeners can be added. Callers will be invoked periodically by framework to 9523 * inform clients about the current Wi-Fi usability statistics. Callers can remove a previously 9524 * added listener using 9525 * {@link #removeOnWifiUsabilityStatsListener(OnWifiUsabilityStatsListener)}. 9526 * 9527 * @param executor The executor on which callback will be invoked. 9528 * @param listener Listener for Wifi usability statistics. 9529 * 9530 * @hide 9531 */ 9532 @SystemApi 9533 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) addOnWifiUsabilityStatsListener(@onNull @allbackExecutor Executor executor, @NonNull OnWifiUsabilityStatsListener listener)9534 public void addOnWifiUsabilityStatsListener(@NonNull @CallbackExecutor Executor executor, 9535 @NonNull OnWifiUsabilityStatsListener listener) { 9536 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 9537 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 9538 if (mVerboseLoggingEnabled) { 9539 Log.v(TAG, "addOnWifiUsabilityStatsListener: listener=" + listener); 9540 } 9541 try { 9542 synchronized (sOnWifiUsabilityStatsListenerMap) { 9543 IOnWifiUsabilityStatsListener.Stub binderCallback = 9544 new IOnWifiUsabilityStatsListener.Stub() { 9545 @Override 9546 public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, 9547 WifiUsabilityStatsEntry stats) { 9548 if (mVerboseLoggingEnabled) { 9549 Log.v(TAG, "OnWifiUsabilityStatsListener: " 9550 + "onWifiUsabilityStats: seqNum=" + seqNum); 9551 } 9552 Binder.clearCallingIdentity(); 9553 executor.execute(() -> listener.onWifiUsabilityStats( 9554 seqNum, isSameBssidAndFreq, stats)); 9555 } 9556 }; 9557 sOnWifiUsabilityStatsListenerMap.put(System.identityHashCode(listener), 9558 binderCallback); 9559 mService.addOnWifiUsabilityStatsListener(binderCallback); 9560 } 9561 } catch (RemoteException e) { 9562 throw e.rethrowFromSystemServer(); 9563 } 9564 } 9565 9566 /** 9567 * Allow callers to remove a previously registered listener. After calling this method, 9568 * applications will no longer receive Wi-Fi usability statistics. 9569 * 9570 * @param listener Listener to remove the Wi-Fi usability statistics. 9571 * 9572 * @hide 9573 */ 9574 @SystemApi 9575 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) removeOnWifiUsabilityStatsListener(@onNull OnWifiUsabilityStatsListener listener)9576 public void removeOnWifiUsabilityStatsListener(@NonNull OnWifiUsabilityStatsListener listener) { 9577 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 9578 if (mVerboseLoggingEnabled) { 9579 Log.v(TAG, "removeOnWifiUsabilityStatsListener: listener=" + listener); 9580 } 9581 try { 9582 synchronized (sOnWifiUsabilityStatsListenerMap) { 9583 int listenerIdentifier = System.identityHashCode(listener); 9584 if (!sOnWifiUsabilityStatsListenerMap.contains(listenerIdentifier)) { 9585 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 9586 return; 9587 } 9588 mService.removeOnWifiUsabilityStatsListener( 9589 sOnWifiUsabilityStatsListenerMap.get(listenerIdentifier)); 9590 sOnWifiUsabilityStatsListenerMap.remove(listenerIdentifier); 9591 } 9592 } catch (RemoteException e) { 9593 throw e.rethrowFromSystemServer(); 9594 } 9595 } 9596 9597 /** 9598 * Provide a Wi-Fi usability score information to be recorded (but not acted upon) by the 9599 * framework. The Wi-Fi usability score is derived from {@link OnWifiUsabilityStatsListener} 9600 * where a score is matched to Wi-Fi usability statistics using the sequence number. The score 9601 * is used to quantify whether Wi-Fi is usable in a future time. 9602 * 9603 * @param seqNum Sequence number of the Wi-Fi usability score. 9604 * @param score The Wi-Fi usability score, expected range: [0, 100]. 9605 * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score in second, 9606 * expected range: [0, 30]. 9607 * 9608 * @hide 9609 */ 9610 @SystemApi 9611 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec)9612 public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { 9613 try { 9614 mService.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec); 9615 } catch (RemoteException e) { 9616 throw e.rethrowFromSystemServer(); 9617 } 9618 } 9619 9620 /** 9621 * Gets the list of BSSIDs which are currently disabled for Wi-Fi auto-join connections. 9622 * 9623 * @param ssids If empty, then get all currently disabled BSSIDs. 9624 * If non-empty, then only get currently disabled BSSIDs with matching SSIDs. 9625 * @param executor The executor to execute the callback of the {@code resultListener} object. 9626 * @param resultListener callback to retrieve the blocked BSSIDs 9627 * 9628 * @hide 9629 */ 9630 @SystemApi 9631 @FlaggedApi(Flags.FLAG_GET_BSSID_BLOCKLIST_API) 9632 @RequiresPermission(anyOf = { 9633 android.Manifest.permission.NETWORK_SETTINGS, 9634 android.Manifest.permission.NETWORK_SETUP_WIZARD}) getBssidBlocklist(@onNull List<WifiSsid> ssids, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<List<MacAddress>> resultListener)9635 public void getBssidBlocklist(@NonNull List<WifiSsid> ssids, 9636 @NonNull @CallbackExecutor Executor executor, 9637 @NonNull Consumer<List<MacAddress>> resultListener) { 9638 Objects.requireNonNull(ssids, "ssids cannot be null"); 9639 Objects.requireNonNull(executor, "executor cannot be null"); 9640 Objects.requireNonNull(resultListener, "resultsCallback cannot be null"); 9641 try { 9642 mService.getBssidBlocklist( 9643 new ParceledListSlice<>(ssids), 9644 new IMacAddressListListener.Stub() { 9645 @Override 9646 public void onResult(ParceledListSlice<MacAddress> value) { 9647 Binder.clearCallingIdentity(); 9648 executor.execute(() -> { 9649 resultListener.accept(value.getList()); 9650 }); 9651 } 9652 }); 9653 } catch (RemoteException e) { 9654 throw e.rethrowFromSystemServer(); 9655 } 9656 } 9657 9658 /** 9659 * Abstract class for scan results callback. Should be extended by applications and set when 9660 * calling {@link WifiManager#registerScanResultsCallback(Executor, ScanResultsCallback)}. 9661 */ 9662 public abstract static class ScanResultsCallback { 9663 private final ScanResultsCallbackProxy mScanResultsCallbackProxy; 9664 ScanResultsCallback()9665 public ScanResultsCallback() { 9666 mScanResultsCallbackProxy = new ScanResultsCallbackProxy(); 9667 } 9668 9669 /** 9670 * Called when new scan results are available. 9671 * Clients should use {@link WifiManager#getScanResults()} to get the scan results. 9672 */ onScanResultsAvailable()9673 public abstract void onScanResultsAvailable(); 9674 getProxy()9675 /*package*/ @NonNull ScanResultsCallbackProxy getProxy() { 9676 return mScanResultsCallbackProxy; 9677 } 9678 9679 private static class ScanResultsCallbackProxy extends IScanResultsCallback.Stub { 9680 private final Object mLock = new Object(); 9681 @Nullable @GuardedBy("mLock") private Executor mExecutor; 9682 @Nullable @GuardedBy("mLock") private ScanResultsCallback mCallback; 9683 ScanResultsCallbackProxy()9684 ScanResultsCallbackProxy() { 9685 mCallback = null; 9686 mExecutor = null; 9687 } 9688 initProxy(@onNull Executor executor, @NonNull ScanResultsCallback callback)9689 /*package*/ void initProxy(@NonNull Executor executor, 9690 @NonNull ScanResultsCallback callback) { 9691 synchronized (mLock) { 9692 mExecutor = executor; 9693 mCallback = callback; 9694 } 9695 } 9696 cleanUpProxy()9697 /*package*/ void cleanUpProxy() { 9698 synchronized (mLock) { 9699 mExecutor = null; 9700 mCallback = null; 9701 } 9702 } 9703 9704 @Override onScanResultsAvailable()9705 public void onScanResultsAvailable() { 9706 ScanResultsCallback callback; 9707 Executor executor; 9708 synchronized (mLock) { 9709 executor = mExecutor; 9710 callback = mCallback; 9711 } 9712 if (callback == null || executor == null) { 9713 return; 9714 } 9715 Binder.clearCallingIdentity(); 9716 executor.execute(callback::onScanResultsAvailable); 9717 } 9718 } 9719 } 9720 9721 /** 9722 * Register a callback for Scan Results. See {@link ScanResultsCallback}. 9723 * Caller will receive the event when scan results are available. 9724 * Caller should use {@link WifiManager#getScanResults()} requires 9725 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} to get the scan results. 9726 * Caller can remove a previously registered callback using 9727 * {@link WifiManager#unregisterScanResultsCallback(ScanResultsCallback)} 9728 * Same caller can add multiple listeners. 9729 * <p> 9730 * Applications should have the 9731 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission. Callers 9732 * without the permission will trigger a {@link java.lang.SecurityException}. 9733 * <p> 9734 * 9735 * @param executor The executor to execute the callback of the {@code callback} object. 9736 * @param callback callback for Scan Results events 9737 */ 9738 9739 @RequiresPermission(ACCESS_WIFI_STATE) registerScanResultsCallback(@onNull @allbackExecutor Executor executor, @NonNull ScanResultsCallback callback)9740 public void registerScanResultsCallback(@NonNull @CallbackExecutor Executor executor, 9741 @NonNull ScanResultsCallback callback) { 9742 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 9743 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 9744 9745 Log.v(TAG, "registerScanResultsCallback: callback=" + callback 9746 + ", executor=" + executor); 9747 ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy(); 9748 proxy.initProxy(executor, callback); 9749 try { 9750 mService.registerScanResultsCallback(proxy); 9751 } catch (RemoteException e) { 9752 throw e.rethrowFromSystemServer(); 9753 } 9754 } 9755 9756 /** 9757 * Allow callers to unregister a previously registered callback. After calling this method, 9758 * applications will no longer receive Scan Results events. 9759 * 9760 * @param callback callback to unregister for Scan Results events 9761 */ 9762 @RequiresPermission(ACCESS_WIFI_STATE) unregisterScanResultsCallback(@onNull ScanResultsCallback callback)9763 public void unregisterScanResultsCallback(@NonNull ScanResultsCallback callback) { 9764 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 9765 Log.v(TAG, "unregisterScanResultsCallback: Callback=" + callback); 9766 ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy(); 9767 try { 9768 mService.unregisterScanResultsCallback(proxy); 9769 } catch (RemoteException e) { 9770 throw e.rethrowFromSystemServer(); 9771 } finally { 9772 proxy.cleanUpProxy(); 9773 } 9774 } 9775 9776 /** 9777 * Interface for suggestion connection status listener. 9778 * Should be implemented by applications and set when calling 9779 * {@link WifiManager#addSuggestionConnectionStatusListener( 9780 * Executor, SuggestionConnectionStatusListener)}. 9781 */ 9782 public interface SuggestionConnectionStatusListener { 9783 9784 /** 9785 * Called when the framework attempted to connect to a suggestion provided by the 9786 * registering app, but the connection to the suggestion failed. 9787 * @param wifiNetworkSuggestion The suggestion which failed to connect. 9788 * @param failureReason the connection failure reason code. 9789 */ onConnectionStatus( @onNull WifiNetworkSuggestion wifiNetworkSuggestion, @SuggestionConnectionStatusCode int failureReason)9790 void onConnectionStatus( 9791 @NonNull WifiNetworkSuggestion wifiNetworkSuggestion, 9792 @SuggestionConnectionStatusCode int failureReason); 9793 } 9794 9795 private class SuggestionConnectionStatusListenerProxy extends 9796 ISuggestionConnectionStatusListener.Stub { 9797 private final Executor mExecutor; 9798 private final SuggestionConnectionStatusListener mListener; 9799 SuggestionConnectionStatusListenerProxy(@onNull Executor executor, @NonNull SuggestionConnectionStatusListener listener)9800 SuggestionConnectionStatusListenerProxy(@NonNull Executor executor, 9801 @NonNull SuggestionConnectionStatusListener listener) { 9802 mExecutor = executor; 9803 mListener = listener; 9804 } 9805 9806 @Override onConnectionStatus(@onNull WifiNetworkSuggestion wifiNetworkSuggestion, int failureReason)9807 public void onConnectionStatus(@NonNull WifiNetworkSuggestion wifiNetworkSuggestion, 9808 int failureReason) { 9809 Binder.clearCallingIdentity(); 9810 mExecutor.execute(() -> 9811 mListener.onConnectionStatus(wifiNetworkSuggestion, failureReason)); 9812 } 9813 9814 } 9815 9816 /** 9817 * Interface for local-only connection failure listener. 9818 * Should be implemented by applications and set when calling 9819 * {@link WifiManager#addLocalOnlyConnectionFailureListener(Executor, LocalOnlyConnectionFailureListener)} 9820 */ 9821 public interface LocalOnlyConnectionFailureListener { 9822 9823 /** 9824 * Called when the framework attempted to connect to a local-only network requested by the 9825 * registering app, but the connection to the network failed. 9826 * @param wifiNetworkSpecifier The {@link WifiNetworkSpecifier} which failed to connect. 9827 * @param failureReason the connection failure reason code. 9828 */ onConnectionFailed( @onNull WifiNetworkSpecifier wifiNetworkSpecifier, @LocalOnlyConnectionStatusCode int failureReason)9829 void onConnectionFailed( 9830 @NonNull WifiNetworkSpecifier wifiNetworkSpecifier, 9831 @LocalOnlyConnectionStatusCode int failureReason); 9832 } 9833 9834 private static class LocalOnlyConnectionStatusListenerProxy extends 9835 ILocalOnlyConnectionStatusListener.Stub { 9836 private final Executor mExecutor; 9837 private final LocalOnlyConnectionFailureListener mListener; 9838 LocalOnlyConnectionStatusListenerProxy(@onNull Executor executor, @NonNull LocalOnlyConnectionFailureListener listener)9839 LocalOnlyConnectionStatusListenerProxy(@NonNull Executor executor, 9840 @NonNull LocalOnlyConnectionFailureListener listener) { 9841 mExecutor = executor; 9842 mListener = listener; 9843 } 9844 9845 @Override onConnectionStatus(@onNull WifiNetworkSpecifier networkSpecifier, int failureReason)9846 public void onConnectionStatus(@NonNull WifiNetworkSpecifier networkSpecifier, 9847 int failureReason) { 9848 Binder.clearCallingIdentity(); 9849 mExecutor.execute(() -> 9850 mListener.onConnectionFailed(networkSpecifier, failureReason)); 9851 } 9852 9853 } 9854 9855 /** 9856 * Add a listener listening to wifi verbose logging changes. 9857 * See {@link WifiVerboseLoggingStatusChangedListener}. 9858 * Caller can remove a previously registered listener using 9859 * {@link WifiManager#removeWifiVerboseLoggingStatusChangedListener( 9860 * WifiVerboseLoggingStatusChangedListener)} 9861 * Same caller can add multiple listeners to monitor the event. 9862 * <p> 9863 * Applications should have the 9864 * {@link android.Manifest.permission#ACCESS_WIFI_STATE}. 9865 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 9866 * <p> 9867 * @param executor The executor to execute the listener of the {@code listener} object. 9868 * @param listener listener for changes in wifi verbose logging. 9869 * 9870 * @hide 9871 */ 9872 @SystemApi 9873 @RequiresPermission(ACCESS_WIFI_STATE) addWifiVerboseLoggingStatusChangedListener( @onNull @allbackExecutor Executor executor, @NonNull WifiVerboseLoggingStatusChangedListener listener)9874 public void addWifiVerboseLoggingStatusChangedListener( 9875 @NonNull @CallbackExecutor Executor executor, 9876 @NonNull WifiVerboseLoggingStatusChangedListener listener) { 9877 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9878 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 9879 if (mVerboseLoggingEnabled) { 9880 Log.v(TAG, "addWifiVerboseLoggingStatusChangedListener listener=" + listener 9881 + ", executor=" + executor); 9882 } 9883 try { 9884 synchronized (sWifiVerboseLoggingStatusChangedListenerMap) { 9885 IWifiVerboseLoggingStatusChangedListener.Stub binderCallback = 9886 new IWifiVerboseLoggingStatusChangedListener.Stub() { 9887 @Override 9888 public void onStatusChanged(boolean enabled) { 9889 if (mVerboseLoggingEnabled) { 9890 Log.v(TAG, "WifiVerboseLoggingStatusListener: " 9891 + "onVerboseLoggingStatusChanged: enabled=" + enabled); 9892 } 9893 Binder.clearCallingIdentity(); 9894 executor.execute(() -> listener.onWifiVerboseLoggingStatusChanged( 9895 enabled)); 9896 } 9897 }; 9898 sWifiVerboseLoggingStatusChangedListenerMap.put(System.identityHashCode(listener), 9899 binderCallback); 9900 mService.addWifiVerboseLoggingStatusChangedListener(binderCallback); 9901 } 9902 } catch (RemoteException e) { 9903 throw e.rethrowFromSystemServer(); 9904 } 9905 } 9906 9907 /** 9908 * Allow callers to remove a previously registered listener. 9909 * <p> 9910 * Applications should have the 9911 * {@link android.Manifest.permission#ACCESS_WIFI_STATE}. 9912 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 9913 * <p> 9914 * @param listener listener to remove. 9915 * 9916 * @hide 9917 */ 9918 @SystemApi 9919 @RequiresPermission(ACCESS_WIFI_STATE) removeWifiVerboseLoggingStatusChangedListener( @onNull WifiVerboseLoggingStatusChangedListener listener)9920 public void removeWifiVerboseLoggingStatusChangedListener( 9921 @NonNull WifiVerboseLoggingStatusChangedListener listener) { 9922 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9923 Log.v(TAG, "removeWifiVerboseLoggingStatusChangedListener: listener=" + listener); 9924 try { 9925 synchronized (sWifiVerboseLoggingStatusChangedListenerMap) { 9926 int listenerIdentifier = System.identityHashCode(listener); 9927 if (!sWifiVerboseLoggingStatusChangedListenerMap.contains(listenerIdentifier)) { 9928 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 9929 return; 9930 } 9931 mService.removeWifiVerboseLoggingStatusChangedListener( 9932 sWifiVerboseLoggingStatusChangedListenerMap.get(listenerIdentifier)); 9933 sWifiVerboseLoggingStatusChangedListenerMap.remove(listenerIdentifier); 9934 } 9935 } catch (RemoteException e) { 9936 throw e.rethrowFromSystemServer(); 9937 } 9938 } 9939 9940 /** 9941 * Add a listener for suggestion networks. See {@link SuggestionConnectionStatusListener}. 9942 * Caller will receive the event when suggested network have connection failure. 9943 * Caller can remove a previously registered listener using 9944 * {@link WifiManager#removeSuggestionConnectionStatusListener( 9945 * SuggestionConnectionStatusListener)} 9946 * Same caller can add multiple listeners to monitor the event. 9947 * <p> 9948 * Applications should have the 9949 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and 9950 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permissions. 9951 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 9952 * <p> 9953 * 9954 * @param executor The executor to execute the listener of the {@code listener} object. 9955 * @param listener listener for suggestion network connection failure. 9956 */ 9957 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) addSuggestionConnectionStatusListener(@onNull @allbackExecutor Executor executor, @NonNull SuggestionConnectionStatusListener listener)9958 public void addSuggestionConnectionStatusListener(@NonNull @CallbackExecutor Executor executor, 9959 @NonNull SuggestionConnectionStatusListener listener) { 9960 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9961 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 9962 Log.v(TAG, "addSuggestionConnectionStatusListener listener=" + listener 9963 + ", executor=" + executor); 9964 try { 9965 synchronized (sSuggestionConnectionStatusListenerMap) { 9966 ISuggestionConnectionStatusListener.Stub binderCallback = 9967 new SuggestionConnectionStatusListenerProxy(executor, listener); 9968 sSuggestionConnectionStatusListenerMap.put(System.identityHashCode(listener), 9969 binderCallback); 9970 mService.registerSuggestionConnectionStatusListener(binderCallback, 9971 mContext.getOpPackageName(), mContext.getAttributionTag()); 9972 } 9973 } catch (RemoteException e) { 9974 throw e.rethrowFromSystemServer(); 9975 } 9976 9977 } 9978 9979 /** 9980 * Allow callers to remove a previously registered listener. After calling this method, 9981 * applications will no longer receive suggestion connection events through that listener. 9982 * 9983 * @param listener listener to remove. 9984 */ 9985 @RequiresPermission(ACCESS_WIFI_STATE) removeSuggestionConnectionStatusListener( @onNull SuggestionConnectionStatusListener listener)9986 public void removeSuggestionConnectionStatusListener( 9987 @NonNull SuggestionConnectionStatusListener listener) { 9988 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9989 Log.v(TAG, "removeSuggestionConnectionStatusListener: listener=" + listener); 9990 try { 9991 synchronized (sSuggestionConnectionStatusListenerMap) { 9992 int listenerIdentifier = System.identityHashCode(listener); 9993 if (!sSuggestionConnectionStatusListenerMap.contains(listenerIdentifier)) { 9994 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 9995 return; 9996 } 9997 mService.unregisterSuggestionConnectionStatusListener( 9998 sSuggestionConnectionStatusListenerMap.get(listenerIdentifier), 9999 mContext.getOpPackageName()); 10000 sSuggestionConnectionStatusListenerMap.remove(listenerIdentifier); 10001 } 10002 } catch (RemoteException e) { 10003 throw e.rethrowFromSystemServer(); 10004 } 10005 } 10006 10007 /** 10008 * Add a listener for local-only networks. See {@link WifiNetworkSpecifier}. 10009 * Specify the caller will only get connection failures for networks they requested. 10010 * Caller can remove a previously registered listener using 10011 * {@link WifiManager#removeLocalOnlyConnectionFailureListener(LocalOnlyConnectionFailureListener)} 10012 * Same caller can add multiple listeners to monitor the event. 10013 * <p> 10014 * Applications should have the {@link android.Manifest.permission#ACCESS_WIFI_STATE} 10015 * permissions. 10016 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 10017 * <p> 10018 * 10019 * @param executor The executor to execute the listener of the {@code listener} object. 10020 * @param listener listener for local-only network connection failure. 10021 */ 10022 @RequiresPermission(ACCESS_WIFI_STATE) addLocalOnlyConnectionFailureListener(@onNull @allbackExecutor Executor executor, @NonNull LocalOnlyConnectionFailureListener listener)10023 public void addLocalOnlyConnectionFailureListener(@NonNull @CallbackExecutor Executor executor, 10024 @NonNull LocalOnlyConnectionFailureListener listener) { 10025 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 10026 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 10027 try { 10028 synchronized (sLocalOnlyConnectionStatusListenerMap) { 10029 if (sLocalOnlyConnectionStatusListenerMap 10030 .contains(System.identityHashCode(listener))) { 10031 Log.w(TAG, "Same listener already registered"); 10032 return; 10033 } 10034 ILocalOnlyConnectionStatusListener.Stub binderCallback = 10035 new LocalOnlyConnectionStatusListenerProxy(executor, listener); 10036 sLocalOnlyConnectionStatusListenerMap.put(System.identityHashCode(listener), 10037 binderCallback); 10038 mService.addLocalOnlyConnectionStatusListener(binderCallback, 10039 mContext.getOpPackageName(), mContext.getAttributionTag()); 10040 } 10041 } catch (RemoteException e) { 10042 throw e.rethrowFromSystemServer(); 10043 } 10044 } 10045 10046 /** 10047 * Allow callers to remove a previously registered listener. After calling this method, 10048 * applications will no longer receive local-only connection events through that listener. 10049 * 10050 * @param listener listener to remove. 10051 */ 10052 @RequiresPermission(ACCESS_WIFI_STATE) removeLocalOnlyConnectionFailureListener( @onNull LocalOnlyConnectionFailureListener listener)10053 public void removeLocalOnlyConnectionFailureListener( 10054 @NonNull LocalOnlyConnectionFailureListener listener) { 10055 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 10056 try { 10057 synchronized (sLocalOnlyConnectionStatusListenerMap) { 10058 int listenerIdentifier = System.identityHashCode(listener); 10059 if (!sLocalOnlyConnectionStatusListenerMap.contains(listenerIdentifier)) { 10060 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 10061 return; 10062 } 10063 mService.removeLocalOnlyConnectionStatusListener( 10064 sLocalOnlyConnectionStatusListenerMap.get(listenerIdentifier), 10065 mContext.getOpPackageName()); 10066 sLocalOnlyConnectionStatusListenerMap.remove(listenerIdentifier); 10067 } 10068 } catch (RemoteException e) { 10069 throw e.rethrowFromSystemServer(); 10070 } 10071 } 10072 10073 /** 10074 * Parse the list of channels the DPP enrollee reports when it fails to find an AP. 10075 * 10076 * @param channelList List of channels in the format defined in the DPP specification. 10077 * @return A parsed sparse array, where the operating class is the key. 10078 * @hide 10079 */ 10080 @VisibleForTesting parseDppChannelList(String channelList)10081 public static SparseArray<int[]> parseDppChannelList(String channelList) { 10082 SparseArray<int[]> channelListArray = new SparseArray<>(); 10083 10084 if (TextUtils.isEmpty(channelList)) { 10085 return channelListArray; 10086 } 10087 StringTokenizer str = new StringTokenizer(channelList, ","); 10088 String classStr = null; 10089 List<Integer> channelsInClass = new ArrayList<>(); 10090 10091 try { 10092 while (str.hasMoreElements()) { 10093 String cur = str.nextToken(); 10094 10095 /** 10096 * Example for a channel list: 10097 * 10098 * 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, 10099 * 116,120,124,128,132,136,140,0/144,124/149,153,157,161,125/165 10100 * 10101 * Detect operating class by the delimiter of '/' and use a string tokenizer with 10102 * ',' as a delimiter. 10103 */ 10104 int classDelim = cur.indexOf('/'); 10105 if (classDelim != -1) { 10106 if (classStr != null) { 10107 // Store the last channel array in the sparse array, where the operating 10108 // class is the key (as an integer). 10109 int[] channelsArray = new int[channelsInClass.size()]; 10110 for (int i = 0; i < channelsInClass.size(); i++) { 10111 channelsArray[i] = channelsInClass.get(i); 10112 } 10113 channelListArray.append(Integer.parseInt(classStr), channelsArray); 10114 channelsInClass = new ArrayList<>(); 10115 } 10116 10117 // Init a new operating class and store the first channel 10118 classStr = cur.substring(0, classDelim); 10119 String channelStr = cur.substring(classDelim + 1); 10120 channelsInClass.add(Integer.parseInt(channelStr)); 10121 } else { 10122 if (classStr == null) { 10123 // Invalid format 10124 Log.e(TAG, "Cannot parse DPP channel list"); 10125 return new SparseArray<>(); 10126 } 10127 channelsInClass.add(Integer.parseInt(cur)); 10128 } 10129 } 10130 10131 // Store the last array 10132 if (classStr != null) { 10133 int[] channelsArray = new int[channelsInClass.size()]; 10134 for (int i = 0; i < channelsInClass.size(); i++) { 10135 channelsArray[i] = channelsInClass.get(i); 10136 } 10137 channelListArray.append(Integer.parseInt(classStr), channelsArray); 10138 } 10139 return channelListArray; 10140 } catch (NumberFormatException e) { 10141 Log.e(TAG, "Cannot parse DPP channel list"); 10142 return new SparseArray<>(); 10143 } 10144 } 10145 10146 /** 10147 * Callback interface for framework to receive network status updates and trigger of updating 10148 * {@link WifiUsabilityStatsEntry}. 10149 * 10150 * @hide 10151 */ 10152 @SystemApi 10153 public interface ScoreUpdateObserver { 10154 /** 10155 * Called by applications to indicate network status. For applications targeting 10156 * {@link android.os.Build.VERSION_CODES#S} or above: The score is not used to take action 10157 * on network selection but for the purpose of Wifi metric collection only; Network 10158 * selection is influenced by inputs from 10159 * {@link ScoreUpdateObserver#notifyStatusUpdate(int, boolean)}, 10160 * {@link ScoreUpdateObserver#requestNudOperation(int, boolean)}, and 10161 * {@link ScoreUpdateObserver#blocklistCurrentBssid(int)}. 10162 * 10163 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10164 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10165 * @param score The score representing link quality of current Wi-Fi network connection. 10166 * Populated by connected network scorer in applications.. 10167 */ notifyScoreUpdate(int sessionId, int score)10168 void notifyScoreUpdate(int sessionId, int score); 10169 10170 /** 10171 * Called by applications to trigger an update of {@link WifiUsabilityStatsEntry}. 10172 * To receive update applications need to add WifiUsabilityStatsEntry listener. See 10173 * {@link addOnWifiUsabilityStatsListener(Executor, OnWifiUsabilityStatsListener)}. 10174 * 10175 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10176 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10177 */ triggerUpdateOfWifiUsabilityStats(int sessionId)10178 void triggerUpdateOfWifiUsabilityStats(int sessionId); 10179 10180 /** 10181 * Called by applications to indicate whether current Wi-Fi network is usable or not. 10182 * 10183 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10184 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10185 * @param isUsable The boolean representing whether current Wi-Fi network is usable, and it 10186 * may be sent to ConnectivityService and used for setting default network. 10187 * Populated by connected network scorer in applications. 10188 */ 10189 @RequiresApi(Build.VERSION_CODES.S) notifyStatusUpdate(int sessionId, boolean isUsable)10190 default void notifyStatusUpdate(int sessionId, boolean isUsable) {} 10191 10192 /** 10193 * Called by applications to start a NUD (Neighbor Unreachability Detection) operation. The 10194 * framework throttles NUD operations to no more frequently than every five seconds 10195 * (see {@link WifiScoreReport#NUD_THROTTLE_MILLIS}). The framework keeps track of requests 10196 * and executes them as soon as possible based on the throttling criteria. 10197 * 10198 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10199 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10200 */ 10201 @RequiresApi(Build.VERSION_CODES.S) requestNudOperation(int sessionId)10202 default void requestNudOperation(int sessionId) {} 10203 10204 /** 10205 * Called by applications to blocklist currently connected BSSID. No blocklisting operation 10206 * if called after disconnection. 10207 * 10208 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10209 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10210 */ 10211 @RequiresApi(Build.VERSION_CODES.S) blocklistCurrentBssid(int sessionId)10212 default void blocklistCurrentBssid(int sessionId) {} 10213 } 10214 10215 /** 10216 * Callback proxy for {@link ScoreUpdateObserver} objects. 10217 * 10218 * @hide 10219 */ 10220 private class ScoreUpdateObserverProxy implements ScoreUpdateObserver { 10221 private final IScoreUpdateObserver mScoreUpdateObserver; 10222 ScoreUpdateObserverProxy(IScoreUpdateObserver observer)10223 private ScoreUpdateObserverProxy(IScoreUpdateObserver observer) { 10224 mScoreUpdateObserver = observer; 10225 } 10226 10227 @Override notifyScoreUpdate(int sessionId, int score)10228 public void notifyScoreUpdate(int sessionId, int score) { 10229 try { 10230 mScoreUpdateObserver.notifyScoreUpdate(sessionId, score); 10231 } catch (RemoteException e) { 10232 throw e.rethrowFromSystemServer(); 10233 } 10234 } 10235 10236 @Override triggerUpdateOfWifiUsabilityStats(int sessionId)10237 public void triggerUpdateOfWifiUsabilityStats(int sessionId) { 10238 try { 10239 mScoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(sessionId); 10240 } catch (RemoteException e) { 10241 throw e.rethrowFromSystemServer(); 10242 } 10243 } 10244 10245 @Override notifyStatusUpdate(int sessionId, boolean isUsable)10246 public void notifyStatusUpdate(int sessionId, boolean isUsable) { 10247 if (!SdkLevel.isAtLeastS()) { 10248 throw new UnsupportedOperationException(); 10249 } 10250 try { 10251 mScoreUpdateObserver.notifyStatusUpdate(sessionId, isUsable); 10252 } catch (RemoteException e) { 10253 throw e.rethrowFromSystemServer(); 10254 } 10255 } 10256 10257 @Override requestNudOperation(int sessionId)10258 public void requestNudOperation(int sessionId) { 10259 if (!SdkLevel.isAtLeastS()) { 10260 throw new UnsupportedOperationException(); 10261 } 10262 try { 10263 mScoreUpdateObserver.requestNudOperation(sessionId); 10264 } catch (RemoteException e) { 10265 throw e.rethrowFromSystemServer(); 10266 } 10267 } 10268 10269 @Override blocklistCurrentBssid(int sessionId)10270 public void blocklistCurrentBssid(int sessionId) { 10271 if (!SdkLevel.isAtLeastS()) { 10272 throw new UnsupportedOperationException(); 10273 } 10274 try { 10275 mScoreUpdateObserver.blocklistCurrentBssid(sessionId); 10276 } catch (RemoteException e) { 10277 throw e.rethrowFromSystemServer(); 10278 } 10279 } 10280 } 10281 10282 /** 10283 * Interface for Wi-Fi connected network scorer. Should be implemented by applications and set 10284 * when calling 10285 * {@link WifiManager#setWifiConnectedNetworkScorer(Executor, WifiConnectedNetworkScorer)}. 10286 * 10287 * @hide 10288 */ 10289 @SystemApi 10290 public interface WifiConnectedNetworkScorer { 10291 /** 10292 * Called by framework to indicate the start of a network connection. 10293 * @param sessionId The ID to indicate current Wi-Fi network connection. 10294 * @deprecated This API is deprecated. Please use 10295 * {@link WifiConnectedNetworkScorer#onStart(WifiConnectedSessionInfo)}. 10296 */ 10297 @Deprecated onStart(int sessionId)10298 default void onStart(int sessionId) {} 10299 10300 /** 10301 * Called by framework to indicate the start of a network connection. 10302 * @param sessionInfo The session information to indicate current Wi-Fi network connection. 10303 * See {@link WifiConnectedSessionInfo}. 10304 */ onStart(@onNull WifiConnectedSessionInfo sessionInfo)10305 default void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) { 10306 onStart(sessionInfo.getSessionId()); 10307 } 10308 10309 /** 10310 * Called by framework to indicate the end of a network connection. 10311 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10312 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10313 */ onStop(int sessionId)10314 void onStop(int sessionId); 10315 10316 /** 10317 * Framework sets callback for score change events after application sets its scorer. 10318 * @param observerImpl The instance for {@link WifiManager#ScoreUpdateObserver}. Should be 10319 * implemented and instantiated by framework. 10320 */ onSetScoreUpdateObserver(@onNull ScoreUpdateObserver observerImpl)10321 void onSetScoreUpdateObserver(@NonNull ScoreUpdateObserver observerImpl); 10322 10323 /** 10324 * Called by framework to indicate the user accepted a dialog to switch to a new network. 10325 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10326 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10327 * @param targetNetworkId Network ID of the target network. 10328 * @param targetBssid BSSID of the target network. 10329 */ onNetworkSwitchAccepted( int sessionId, int targetNetworkId, @NonNull String targetBssid)10330 default void onNetworkSwitchAccepted( 10331 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10332 // No-op. 10333 } 10334 10335 /** 10336 * Called by framework to indicate the user rejected a dialog to switch to new network. 10337 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10338 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10339 * @param targetNetworkId Network ID of the target network. 10340 * @param targetBssid BSSID of the target network. 10341 */ onNetworkSwitchRejected( int sessionId, int targetNetworkId, @NonNull String targetBssid)10342 default void onNetworkSwitchRejected( 10343 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10344 // No-op. 10345 } 10346 } 10347 10348 10349 /** 10350 * Callback registered with {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor, 10351 * PnoScanResultsCallback)}. Returns status and result information on offloaded external PNO 10352 * requests. 10353 * @hide 10354 */ 10355 @SystemApi 10356 public interface PnoScanResultsCallback { 10357 /** 10358 * A status code returned by {@link #onRegisterFailed(int)}. 10359 * Unknown failure. 10360 */ 10361 int REGISTER_PNO_CALLBACK_UNKNOWN = 0; 10362 10363 /** 10364 * A status code returned by {@link #onRegisterFailed(int)}. 10365 * A callback has already been registered by the caller. 10366 */ 10367 int REGISTER_PNO_CALLBACK_ALREADY_REGISTERED = 1; 10368 10369 /** 10370 * A status code returned by {@link #onRegisterFailed(int)}. 10371 * The platform is unable to serve this request because another app has a PNO scan request 10372 * active. 10373 */ 10374 int REGISTER_PNO_CALLBACK_RESOURCE_BUSY = 2; 10375 10376 /** 10377 * A status code returned by {@link #onRegisterFailed(int)}. 10378 * PNO scans are not supported on this device. 10379 */ 10380 int REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED = 3; 10381 10382 /** @hide */ 10383 @IntDef(prefix = { "REGISTER_PNO_CALLBACK_" }, value = { 10384 REGISTER_PNO_CALLBACK_UNKNOWN, 10385 REGISTER_PNO_CALLBACK_ALREADY_REGISTERED, 10386 REGISTER_PNO_CALLBACK_RESOURCE_BUSY, 10387 REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED 10388 }) 10389 @Retention(RetentionPolicy.SOURCE) 10390 public @interface RegisterFailureReason {} 10391 10392 /** 10393 * A status code returned by {@link #onRemoved(int)}. 10394 * Unknown reason. 10395 */ 10396 int REMOVE_PNO_CALLBACK_UNKNOWN = 0; 10397 10398 /** 10399 * A status code returned by {@link #onRemoved(int)}. 10400 * This Callback is automatically removed after results ScanResults are delivered. 10401 */ 10402 int REMOVE_PNO_CALLBACK_RESULTS_DELIVERED = 1; 10403 10404 /** 10405 * A status code returned by {@link #onRemoved(int)}. 10406 * This callback has been unregistered via {@link WifiManager#clearExternalPnoScanRequest()} 10407 */ 10408 int REMOVE_PNO_CALLBACK_UNREGISTERED = 2; 10409 10410 /** @hide */ 10411 @IntDef(prefix = { "REMOVE_PNO_CALLBACK_" }, value = { 10412 REMOVE_PNO_CALLBACK_UNKNOWN, 10413 REMOVE_PNO_CALLBACK_RESULTS_DELIVERED, 10414 REMOVE_PNO_CALLBACK_UNREGISTERED 10415 }) 10416 @Retention(RetentionPolicy.SOURCE) 10417 public @interface RemovalReason {} 10418 10419 /** 10420 * Called when PNO scan finds one of the requested SSIDs. This is a one time callback. 10421 * After results are reported the callback will be automatically unregistered. 10422 */ onScanResultsAvailable(@onNull List<ScanResult> scanResults)10423 void onScanResultsAvailable(@NonNull List<ScanResult> scanResults); 10424 10425 /** 10426 * Called when this callback has been successfully registered. 10427 */ onRegisterSuccess()10428 void onRegisterSuccess(); 10429 10430 /** 10431 * Called when this callback failed to register with the failure reason. 10432 * See {@link RegisterFailureReason} for details. 10433 */ onRegisterFailed(@egisterFailureReason int reason)10434 void onRegisterFailed(@RegisterFailureReason int reason); 10435 10436 /** 10437 * Called when this callback has been unregistered from the Wi-Fi subsystem. 10438 * See {@link RemovalReason} for details. 10439 */ onRemoved(@emovalReason int reason)10440 void onRemoved(@RemovalReason int reason); 10441 } 10442 10443 10444 private class PnoScanResultsCallbackProxy extends IPnoScanResultsCallback.Stub { 10445 private Executor mExecutor; 10446 private PnoScanResultsCallback mCallback; 10447 PnoScanResultsCallbackProxy(@onNull Executor executor, @NonNull PnoScanResultsCallback callback)10448 PnoScanResultsCallbackProxy(@NonNull Executor executor, 10449 @NonNull PnoScanResultsCallback callback) { 10450 mExecutor = executor; 10451 mCallback = callback; 10452 } 10453 10454 @Override onScanResultsAvailable(List<ScanResult> scanResults)10455 public void onScanResultsAvailable(List<ScanResult> scanResults) { 10456 if (mVerboseLoggingEnabled) { 10457 Log.v(TAG, "PnoScanResultsCallback: " + "onScanResultsAvailable"); 10458 } 10459 Binder.clearCallingIdentity(); 10460 mExecutor.execute(() -> mCallback.onScanResultsAvailable(scanResults)); 10461 } 10462 10463 @Override onRegisterSuccess()10464 public void onRegisterSuccess() { 10465 if (mVerboseLoggingEnabled) { 10466 Log.v(TAG, "PnoScanResultsCallback: " + "onRegisterSuccess"); 10467 } 10468 Binder.clearCallingIdentity(); 10469 mExecutor.execute(() -> mCallback.onRegisterSuccess()); 10470 } 10471 10472 @Override onRegisterFailed(int reason)10473 public void onRegisterFailed(int reason) { 10474 if (mVerboseLoggingEnabled) { 10475 Log.v(TAG, "PnoScanResultsCallback: " + "onRegisterFailed " + reason); 10476 } 10477 Binder.clearCallingIdentity(); 10478 mExecutor.execute(() -> mCallback.onRegisterFailed(reason)); 10479 } 10480 10481 @Override onRemoved(int reason)10482 public void onRemoved(int reason) { 10483 if (mVerboseLoggingEnabled) { 10484 Log.v(TAG, "PnoScanResultsCallback: " + "onRemoved"); 10485 } 10486 Binder.clearCallingIdentity(); 10487 mExecutor.execute(() -> mCallback.onRemoved(reason)); 10488 } 10489 } 10490 10491 /** 10492 * Callback proxy for {@link WifiConnectedNetworkScorer} objects. 10493 * 10494 * @hide 10495 */ 10496 private class WifiConnectedNetworkScorerProxy extends IWifiConnectedNetworkScorer.Stub { 10497 private Executor mExecutor; 10498 private WifiConnectedNetworkScorer mScorer; 10499 WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer)10500 WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer) { 10501 mExecutor = executor; 10502 mScorer = scorer; 10503 } 10504 10505 @Override onStart(@onNull WifiConnectedSessionInfo sessionInfo)10506 public void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) { 10507 if (mVerboseLoggingEnabled) { 10508 Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStart: sessionInfo=" + sessionInfo); 10509 } 10510 Binder.clearCallingIdentity(); 10511 mExecutor.execute(() -> mScorer.onStart(sessionInfo)); 10512 } 10513 10514 @Override onStop(int sessionId)10515 public void onStop(int sessionId) { 10516 if (mVerboseLoggingEnabled) { 10517 Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStop: sessionId=" + sessionId); 10518 } 10519 Binder.clearCallingIdentity(); 10520 mExecutor.execute(() -> mScorer.onStop(sessionId)); 10521 } 10522 10523 @Override onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl)10524 public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) { 10525 if (mVerboseLoggingEnabled) { 10526 Log.v(TAG, "WifiConnectedNetworkScorer: " 10527 + "onSetScoreUpdateObserver: observerImpl=" + observerImpl); 10528 } 10529 Binder.clearCallingIdentity(); 10530 mExecutor.execute(() -> mScorer.onSetScoreUpdateObserver( 10531 new ScoreUpdateObserverProxy(observerImpl))); 10532 } 10533 10534 @Override onNetworkSwitchAccepted( int sessionId, int targetNetworkId, @NonNull String targetBssid)10535 public void onNetworkSwitchAccepted( 10536 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10537 if (mVerboseLoggingEnabled) { 10538 Log.v(TAG, "WifiConnectedNetworkScorer: onNetworkSwitchAccepted:" 10539 + " sessionId=" + sessionId 10540 + " targetNetworkId=" + targetNetworkId 10541 + " targetBssid=" + targetBssid); 10542 } 10543 Binder.clearCallingIdentity(); 10544 mExecutor.execute(() -> mScorer.onNetworkSwitchAccepted( 10545 sessionId, targetNetworkId, targetBssid)); 10546 } 10547 @Override onNetworkSwitchRejected( int sessionId, int targetNetworkId, @NonNull String targetBssid)10548 public void onNetworkSwitchRejected( 10549 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10550 if (mVerboseLoggingEnabled) { 10551 Log.v(TAG, "WifiConnectedNetworkScorer: onNetworkSwitchRejected:" 10552 + " sessionId=" + sessionId 10553 + " targetNetworkId=" + targetNetworkId 10554 + " targetBssid=" + targetBssid); 10555 } 10556 Binder.clearCallingIdentity(); 10557 mExecutor.execute(() -> mScorer.onNetworkSwitchRejected( 10558 sessionId, targetNetworkId, targetBssid)); 10559 } 10560 } 10561 10562 /** 10563 * This API allows the caller to program up to 2 SSIDs for PNO scans. PNO scans are offloaded 10564 * to the Wi-Fi chip when the device is inactive (typically screen-off). 10565 * If the screen is currently off when this API is called, then a PNO scan including the 10566 * requested SSIDs will immediately get started. If the screen is on when this API is called, 10567 * the requested SSIDs will get included for PNO scans the next time the screen turns off. 10568 * <p> 10569 * Note, due to PNO being a limited resource, only one external PNO request is supported, and 10570 * calling this API will fail if an external PNO scan request is already registered by another 10571 * caller. If the caller that has already registered a callback calls this API again, the new 10572 * callback will override the previous one. 10573 * <p> 10574 * After this API is called, {@link PnoScanResultsCallback#onRegisterSuccess()} will be invoked 10575 * if the operation is successful, or {@link PnoScanResultsCallback#onRegisterFailed(int)} will 10576 * be invoked if the operation failed. 10577 * <p> 10578 * {@link PnoScanResultsCallback#onRemoved(int)} will be invoked to notify the caller when the 10579 * external PNO scan request is removed, which will happen when one of the following events 10580 * happen: 10581 * </p> 10582 * <ul> 10583 * <li>Upon finding any of the requested SSIDs through either a connectivity scan or PNO scan, 10584 * the matching ScanResults will be returned 10585 * via {@link PnoScanResultsCallback#onScanResultsAvailable(List)}, and the registered PNO 10586 * scan request will get automatically removed.</li> 10587 * <li>The external PNO scan request is removed by a call to 10588 * {@link #clearExternalPnoScanRequest()}</li> 10589 * </ul> 10590 * 10591 * @param ssids The list of SSIDs to request for PNO scan. 10592 * @param frequencies Provide as hint a list of up to 10 frequencies to be used for PNO scan. 10593 * Each frequency should be in MHz. For example 2412 and 5180 are valid 10594 * frequencies. {@link WifiInfo#getFrequency()} is a location where this 10595 * information could be obtained. If a null or empty array is provided, the 10596 * Wi-Fi framework will automatically decide the list of frequencies to scan. 10597 * @param executor The executor on which callback will be invoked. 10598 * @param callback For the calling application to receive results and status updates. 10599 * 10600 * @throws SecurityException if the caller does not have permission. 10601 * @throws IllegalArgumentException if the caller provided invalid inputs. 10602 * @throws UnsupportedOperationException if this API is not supported on this SDK version. 10603 * @hide 10604 */ 10605 @SystemApi 10606 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, 10607 REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}) 10608 @RequiresApi(Build.VERSION_CODES.TIRAMISU) setExternalPnoScanRequest(@onNull List<WifiSsid> ssids, @Nullable int[] frequencies, @NonNull @CallbackExecutor Executor executor, @NonNull PnoScanResultsCallback callback)10609 public void setExternalPnoScanRequest(@NonNull List<WifiSsid> ssids, 10610 @Nullable int[] frequencies, @NonNull @CallbackExecutor Executor executor, 10611 @NonNull PnoScanResultsCallback callback) { 10612 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 10613 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 10614 try { 10615 mService.setExternalPnoScanRequest(new Binder(), 10616 new PnoScanResultsCallbackProxy(executor, callback), 10617 ssids, frequencies == null ? new int[0] : frequencies, 10618 mContext.getOpPackageName(), mContext.getAttributionTag()); 10619 } catch (RemoteException e) { 10620 throw e.rethrowFromSystemServer(); 10621 } 10622 } 10623 10624 /** 10625 * Wi-Fi Preferred Network Offload (PNO) scanning offloads scanning to the chip to save power 10626 * when Wi-Fi is disconnected and the screen is off. See 10627 * {@link https://source.android.com/docs/core/connect/wifi-scan} for more details. 10628 * <p> 10629 * This API can be used to enable or disable PNO scanning. After boot, PNO scanning is enabled 10630 * by default. When PNO scanning is disabled, the Wi-Fi framework will not trigger scans at all 10631 * when the screen is off. This can be used to save power on devices with small batteries. 10632 * 10633 * @param enabled True - enable PNO scanning 10634 * False - disable PNO scanning 10635 * @param enablePnoScanAfterWifiToggle True - Wifi being enabled by 10636 * {@link #setWifiEnabled(boolean)} will re-enable PNO 10637 * scanning. 10638 * False - Wifi being enabled by 10639 * {@link #setWifiEnabled(boolean)} will not re-enable PNO 10640 * scanning. 10641 * 10642 * @throws SecurityException if the caller does not have permission. 10643 * @hide 10644 */ 10645 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 10646 @SystemApi 10647 @RequiresPermission( 10648 anyOf = {MANAGE_WIFI_NETWORK_SELECTION, NETWORK_SETTINGS, NETWORK_SETUP_WIZARD}) setPnoScanState(@noScanState int pnoScanState)10649 public void setPnoScanState(@PnoScanState int pnoScanState) { 10650 try { 10651 boolean enabled = false; 10652 boolean enablePnoScanAfterWifiToggle = false; 10653 switch (pnoScanState) { 10654 case PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT: 10655 break; 10656 case PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE: 10657 enablePnoScanAfterWifiToggle = true; 10658 break; 10659 case PNO_SCAN_STATE_ENABLED: 10660 enabled = true; 10661 break; 10662 default: 10663 throw new IllegalArgumentException("Invalid PnoScanState"); 10664 } 10665 mService.setPnoScanEnabled(enabled, enablePnoScanAfterWifiToggle, 10666 mContext.getOpPackageName()); 10667 } catch (RemoteException e) { 10668 throw e.rethrowFromSystemServer(); 10669 } 10670 } 10671 10672 /** 10673 * Wi-Fi Preferred Network Offload (PNO) scanning offloads scanning to the chip to save power 10674 * when Wi-Fi is disconnected and the screen is off. See 10675 * {@link https://source.android.com/docs/core/connect/wifi-scan} for more details. 10676 * <p> 10677 * This API can be used to enable or disable PNO scanning. After boot, PNO scanning is enabled 10678 * by default. When PNO scanning is disabled, the Wi-Fi framework will not trigger scans at all 10679 * when the screen is off. This can be used to save power on devices with small batteries. 10680 * 10681 * @param enabled True - enable PNO scanning 10682 * False - disable PNO scanning 10683 * @param enablePnoScanAfterWifiToggle True - Wifi being enabled by 10684 * {@link #setWifiEnabled(boolean)} will re-enable PNO 10685 * scanning. 10686 * False - Wifi being enabled by 10687 * {@link #setWifiEnabled(boolean)} will not re-enable PNO 10688 * scanning. 10689 * 10690 * @throws SecurityException if the caller does not have permission. 10691 * @hide 10692 */ 10693 @RequiresPermission( 10694 anyOf = {MANAGE_WIFI_NETWORK_SELECTION, NETWORK_SETTINGS, NETWORK_SETUP_WIZARD}) setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle)10695 public void setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle) { 10696 try { 10697 mService.setPnoScanEnabled(enabled, enablePnoScanAfterWifiToggle, 10698 mContext.getOpPackageName()); 10699 } catch (RemoteException e) { 10700 throw e.rethrowFromSystemServer(); 10701 } 10702 } 10703 10704 /** 10705 * Clear the current PNO scan request that's been set by the calling UID. Note, the call will 10706 * be no-op if the current PNO scan request is set by a different UID. 10707 * 10708 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 10709 * @hide 10710 */ 10711 @SystemApi 10712 @RequiresApi(Build.VERSION_CODES.TIRAMISU) clearExternalPnoScanRequest()10713 public void clearExternalPnoScanRequest() { 10714 try { 10715 mService.clearExternalPnoScanRequest(); 10716 } catch (RemoteException e) { 10717 throw e.rethrowFromSystemServer(); 10718 } 10719 } 10720 10721 /** 10722 * Returns information about the last caller of an API. 10723 * 10724 * @param apiType The type of API to request information for the last caller. 10725 * @param executor The executor on which callback will be invoked. 10726 * @param resultsCallback An asynchronous callback that will return 2 arguments. 10727 * {@code String} the name of the package that performed the last API 10728 * call. {@code Boolean} the value associated with the last API call. 10729 * 10730 * @throws SecurityException if the caller does not have permission. 10731 * @throws IllegalArgumentException if the caller provided invalid inputs. 10732 * @hide 10733 */ 10734 @SystemApi 10735 @RequiresPermission(anyOf = { 10736 android.Manifest.permission.NETWORK_SETTINGS, 10737 android.Manifest.permission.NETWORK_STACK, 10738 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) getLastCallerInfoForApi(@piType int apiType, @NonNull @CallbackExecutor Executor executor, @NonNull BiConsumer<String, Boolean> resultsCallback)10739 public void getLastCallerInfoForApi(@ApiType int apiType, 10740 @NonNull @CallbackExecutor Executor executor, 10741 @NonNull BiConsumer<String, Boolean> resultsCallback) { 10742 if (executor == null) { 10743 throw new IllegalArgumentException("executor can't be null"); 10744 } 10745 if (resultsCallback == null) { 10746 throw new IllegalArgumentException("resultsCallback can't be null"); 10747 } 10748 try { 10749 mService.getLastCallerInfoForApi(apiType, 10750 new ILastCallerListener.Stub() { 10751 @Override 10752 public void onResult(String packageName, boolean enabled) { 10753 Binder.clearCallingIdentity(); 10754 executor.execute(() -> { 10755 resultsCallback.accept(packageName, enabled); 10756 }); 10757 } 10758 }); 10759 } catch (RemoteException e) { 10760 throw e.rethrowFromSystemServer(); 10761 } 10762 } 10763 10764 /** 10765 * Set a callback for Wi-Fi connected network scorer. See {@link WifiConnectedNetworkScorer}. 10766 * Only a single scorer can be set. Caller will be invoked periodically by framework to inform 10767 * client about start and stop of Wi-Fi connection. Caller can clear a previously set scorer 10768 * using {@link clearWifiConnectedNetworkScorer()}. 10769 * 10770 * @param executor The executor on which callback will be invoked. 10771 * @param scorer Scorer for Wi-Fi network implemented by application. 10772 * @return true Scorer is set successfully. 10773 * 10774 * @hide 10775 */ 10776 @SystemApi 10777 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) setWifiConnectedNetworkScorer(@onNull @allbackExecutor Executor executor, @NonNull WifiConnectedNetworkScorer scorer)10778 public boolean setWifiConnectedNetworkScorer(@NonNull @CallbackExecutor Executor executor, 10779 @NonNull WifiConnectedNetworkScorer scorer) { 10780 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 10781 if (scorer == null) throw new IllegalArgumentException("scorer cannot be null"); 10782 if (mVerboseLoggingEnabled) { 10783 Log.v(TAG, "setWifiConnectedNetworkScorer: scorer=" + scorer); 10784 } 10785 try { 10786 return mService.setWifiConnectedNetworkScorer(new Binder(), 10787 new WifiConnectedNetworkScorerProxy(executor, scorer)); 10788 } catch (RemoteException e) { 10789 throw e.rethrowFromSystemServer(); 10790 } 10791 } 10792 10793 /** 10794 * Allow caller to clear a previously set scorer. After calling this method, 10795 * client will no longer receive information about start and stop of Wi-Fi connection. 10796 * 10797 * @hide 10798 */ 10799 @SystemApi 10800 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) clearWifiConnectedNetworkScorer()10801 public void clearWifiConnectedNetworkScorer() { 10802 if (mVerboseLoggingEnabled) { 10803 Log.v(TAG, "clearWifiConnectedNetworkScorer"); 10804 } 10805 try { 10806 mService.clearWifiConnectedNetworkScorer(); 10807 } catch (RemoteException e) { 10808 throw e.rethrowFromSystemServer(); 10809 } 10810 } 10811 10812 /** 10813 * Enable/disable wifi scan throttling from 3rd party apps. 10814 * 10815 * <p> 10816 * The throttling limits for apps are described in 10817 * <a href="Wi-Fi Scan Throttling"> 10818 * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a> 10819 * </p> 10820 * 10821 * @param enable true to allow scan throttling, false to disallow scan throttling. 10822 * @hide 10823 */ 10824 @SystemApi 10825 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setScanThrottleEnabled(boolean enable)10826 public void setScanThrottleEnabled(boolean enable) { 10827 try { 10828 mService.setScanThrottleEnabled(enable); 10829 } catch (RemoteException e) { 10830 throw e.rethrowFromSystemServer(); 10831 } 10832 } 10833 10834 /** 10835 * Get the persisted Wi-Fi scan throttle state. Defaults to true, unless changed by the user via 10836 * Developer options. 10837 * 10838 * <p> 10839 * The throttling limits for apps are described in 10840 * <a href="Wi-Fi Scan Throttling"> 10841 * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a> 10842 * </p> 10843 * 10844 * @return true to indicate that scan throttling is enabled, false to indicate that scan 10845 * throttling is disabled. 10846 */ 10847 @RequiresPermission(ACCESS_WIFI_STATE) isScanThrottleEnabled()10848 public boolean isScanThrottleEnabled() { 10849 try { 10850 return mService.isScanThrottleEnabled(); 10851 } catch (RemoteException e) { 10852 throw e.rethrowFromSystemServer(); 10853 } 10854 } 10855 10856 /** 10857 * Enable/disable wifi auto wakeup feature. 10858 * 10859 * <p> 10860 * The feature is described in 10861 * <a href="Wi-Fi Turn on automatically"> 10862 * https://source.android.com/devices/tech/connect/wifi-infrastructure 10863 * #turn_on_wi-fi_automatically 10864 * </a> 10865 * 10866 * @param enable true to enable, false to disable. 10867 * @hide 10868 */ 10869 @SystemApi 10870 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setAutoWakeupEnabled(boolean enable)10871 public void setAutoWakeupEnabled(boolean enable) { 10872 try { 10873 mService.setAutoWakeupEnabled(enable); 10874 } catch (RemoteException e) { 10875 throw e.rethrowFromSystemServer(); 10876 } 10877 } 10878 10879 /** 10880 * Get the persisted Wi-Fi auto wakeup feature state. Defaults to false, unless changed by the 10881 * user via Settings. 10882 * 10883 * <p> 10884 * The feature is described in 10885 * <a href="Wi-Fi Turn on automatically"> 10886 * https://source.android.com/devices/tech/connect/wifi-infrastructure 10887 * #turn_on_wi-fi_automatically 10888 * </a> 10889 * 10890 * @return true to indicate that wakeup feature is enabled, false to indicate that wakeup 10891 * feature is disabled. 10892 */ 10893 @RequiresPermission(ACCESS_WIFI_STATE) isAutoWakeupEnabled()10894 public boolean isAutoWakeupEnabled() { 10895 try { 10896 return mService.isAutoWakeupEnabled(); 10897 } catch (RemoteException e) { 10898 throw e.rethrowFromSystemServer(); 10899 } 10900 } 10901 10902 /** 10903 * Sets the state of carrier offload on merged or unmerged networks for specified subscription. 10904 * 10905 * <p> 10906 * When a subscription's carrier network offload is disabled, all network suggestions related to 10907 * this subscription will not be considered for auto join. 10908 * <p> 10909 * If calling app want disable all carrier network offload from a specified subscription, should 10910 * call this API twice to disable both merged and unmerged carrier network suggestions. 10911 * 10912 * @param subscriptionId See {@link SubscriptionInfo#getSubscriptionId()}. 10913 * @param merged True for carrier merged network, false otherwise. 10914 * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} 10915 * @param enabled True for enable carrier network offload, false otherwise. 10916 * @see #isCarrierNetworkOffloadEnabled(int, boolean) 10917 * @hide 10918 */ 10919 @SystemApi 10920 @RequiresPermission(anyOf = { 10921 android.Manifest.permission.NETWORK_SETTINGS, 10922 android.Manifest.permission.NETWORK_SETUP_WIZARD}) setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, boolean enabled)10923 public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, 10924 boolean enabled) { 10925 try { 10926 mService.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled); 10927 } catch (RemoteException e) { 10928 throw e.rethrowFromSystemServer(); 10929 } 10930 } 10931 10932 /** 10933 * Get the carrier network offload state for merged or unmerged networks for specified 10934 * subscription. 10935 * @param subscriptionId subscription ID see {@link SubscriptionInfo#getSubscriptionId()} 10936 * @param merged True for carrier merged network, false otherwise. 10937 * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} 10938 * @return True to indicate that carrier network offload is enabled, false otherwise. 10939 */ 10940 @RequiresPermission(ACCESS_WIFI_STATE) isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged)10941 public boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged) { 10942 try { 10943 return mService.isCarrierNetworkOffloadEnabled(subscriptionId, merged); 10944 } catch (RemoteException e) { 10945 throw e.rethrowFromSystemServer(); 10946 } 10947 } 10948 10949 /** 10950 * Interface for network suggestion user approval status change listener. 10951 * Should be implemented by applications and registered using 10952 * {@link #addSuggestionUserApprovalStatusListener(Executor, 10953 * SuggestionUserApprovalStatusListener)} ( 10954 */ 10955 public interface SuggestionUserApprovalStatusListener { 10956 10957 /** 10958 * Called when the user approval status of the App has changed. 10959 * @param status The current status code for the user approval. One of the 10960 * {@code STATUS_SUGGESTION_APPROVAL_} values. 10961 */ onUserApprovalStatusChange(@uggestionUserApprovalStatus int status)10962 void onUserApprovalStatusChange(@SuggestionUserApprovalStatus int status); 10963 } 10964 10965 private class SuggestionUserApprovalStatusListenerProxy extends 10966 ISuggestionUserApprovalStatusListener.Stub { 10967 private final Executor mExecutor; 10968 private final SuggestionUserApprovalStatusListener mListener; 10969 SuggestionUserApprovalStatusListenerProxy(@onNull Executor executor, @NonNull SuggestionUserApprovalStatusListener listener)10970 SuggestionUserApprovalStatusListenerProxy(@NonNull Executor executor, 10971 @NonNull SuggestionUserApprovalStatusListener listener) { 10972 mExecutor = executor; 10973 mListener = listener; 10974 } 10975 10976 @Override onUserApprovalStatusChange(int status)10977 public void onUserApprovalStatusChange(int status) { 10978 mExecutor.execute(() -> mListener.onUserApprovalStatusChange(status)); 10979 } 10980 10981 } 10982 10983 /** 10984 * Add a listener for Wi-Fi network suggestion user approval status. 10985 * See {@link SuggestionUserApprovalStatusListener}. 10986 * Caller will receive a callback immediately after adding a listener and when the user approval 10987 * status of the caller has changed. 10988 * Caller can remove a previously registered listener using 10989 * {@link WifiManager#removeSuggestionUserApprovalStatusListener( 10990 * SuggestionUserApprovalStatusListener)} 10991 * A caller can add multiple listeners to monitor the event. 10992 * @param executor The executor to execute the listener of the {@code listener} object. 10993 * @param listener listener for suggestion user approval status changes. 10994 */ 10995 @RequiresPermission(ACCESS_WIFI_STATE) addSuggestionUserApprovalStatusListener( @onNull @allbackExecutor Executor executor, @NonNull SuggestionUserApprovalStatusListener listener)10996 public void addSuggestionUserApprovalStatusListener( 10997 @NonNull @CallbackExecutor Executor executor, 10998 @NonNull SuggestionUserApprovalStatusListener listener) { 10999 if (listener == null) throw new NullPointerException("Listener cannot be null"); 11000 if (executor == null) throw new NullPointerException("Executor cannot be null"); 11001 Log.v(TAG, "addSuggestionUserApprovalStatusListener listener=" + listener 11002 + ", executor=" + executor); 11003 try { 11004 synchronized (sSuggestionUserApprovalStatusListenerMap) { 11005 ISuggestionUserApprovalStatusListener.Stub binderCallback = 11006 new SuggestionUserApprovalStatusListenerProxy(executor, listener); 11007 sSuggestionUserApprovalStatusListenerMap.put(System.identityHashCode(listener), 11008 binderCallback); 11009 mService.addSuggestionUserApprovalStatusListener(binderCallback, 11010 mContext.getOpPackageName()); 11011 } 11012 } catch (RemoteException e) { 11013 throw e.rethrowFromSystemServer(); 11014 } 11015 11016 } 11017 11018 /** 11019 * Allow callers to remove a previously registered listener using 11020 * {@link #addSuggestionUserApprovalStatusListener(Executor, 11021 * SuggestionUserApprovalStatusListener)}. After calling this method, 11022 * applications will no longer receive network suggestion user approval status change through 11023 * that listener. 11024 */ 11025 @RequiresPermission(ACCESS_WIFI_STATE) removeSuggestionUserApprovalStatusListener( @onNull SuggestionUserApprovalStatusListener listener)11026 public void removeSuggestionUserApprovalStatusListener( 11027 @NonNull SuggestionUserApprovalStatusListener listener) { 11028 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 11029 Log.v(TAG, "removeSuggestionUserApprovalStatusListener: listener=" + listener); 11030 try { 11031 synchronized (sSuggestionUserApprovalStatusListenerMap) { 11032 int listenerIdentifier = System.identityHashCode(listener); 11033 if (!sSuggestionUserApprovalStatusListenerMap.contains(listenerIdentifier)) { 11034 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 11035 return; 11036 } 11037 mService.removeSuggestionUserApprovalStatusListener( 11038 sSuggestionUserApprovalStatusListenerMap.get(listenerIdentifier), 11039 mContext.getOpPackageName()); 11040 sSuggestionUserApprovalStatusListenerMap.remove(listenerIdentifier); 11041 } 11042 } catch (RemoteException e) { 11043 throw e.rethrowFromSystemServer(); 11044 } 11045 } 11046 11047 /** 11048 * Indicates the start/end of an emergency scan request being processed by {@link WifiScanner}. 11049 * The wifi stack should ensure that the wifi chip remains on for the duration of the scan. 11050 * WifiScanner detects emergency scan requests via 11051 * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag. 11052 * 11053 * If the wifi stack is off (because location & wifi toggles are off) when this indication is 11054 * received, the wifi stack will temporarily move to a scan only mode. Since location toggle 11055 * is off, only scan with 11056 * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag set will be 11057 * allowed to be processed for this duration. 11058 * 11059 * @hide 11060 */ 11061 @RequiresPermission(android.Manifest.permission.NETWORK_STACK) setEmergencyScanRequestInProgress(boolean inProgress)11062 public void setEmergencyScanRequestInProgress(boolean inProgress) { 11063 try { 11064 mService.setEmergencyScanRequestInProgress(inProgress); 11065 } catch (RemoteException e) { 11066 throw e.rethrowFromSystemServer(); 11067 } 11068 } 11069 11070 /** 11071 * Enable or disable Wi-Fi scoring. Wi-Fi network status is evaluated by Wi-Fi scoring 11072 * {@link WifiScoreReport}. This API enables/disables Wi-Fi scoring to take action on network 11073 * selection. 11074 * 11075 * @param enabled {@code true} to enable, {@code false} to disable. 11076 * @return true The status of Wifi scoring is set successfully. 11077 * @hide 11078 */ 11079 @SystemApi 11080 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setWifiScoringEnabled(boolean enabled)11081 public boolean setWifiScoringEnabled(boolean enabled) { 11082 if (mVerboseLoggingEnabled) { 11083 Log.v(TAG, "setWifiScoringEnabled: " + enabled); 11084 } 11085 try { 11086 return mService.setWifiScoringEnabled(enabled); 11087 } catch (RemoteException e) { 11088 throw e.rethrowFromSystemServer(); 11089 } 11090 } 11091 11092 /** 11093 * Flush Passpoint ANQP cache, and clear pending ANQP requests. Allows the caller to reset the 11094 * Passpoint ANQP state, if required. 11095 * 11096 * Notes: 11097 * 1. Flushing the ANQP cache may cause delays in discovering and connecting to Passpoint 11098 * networks. 11099 * 2. Intended to be used by Device Owner (DO), Profile Owner (PO), Settings and provisioning 11100 * apps. 11101 */ 11102 @RequiresPermission(anyOf = { 11103 android.Manifest.permission.NETWORK_SETTINGS, 11104 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, 11105 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING 11106 }, conditional = true) flushPasspointAnqpCache()11107 public void flushPasspointAnqpCache() { 11108 try { 11109 mService.flushPasspointAnqpCache(mContext.getOpPackageName()); 11110 } catch (RemoteException e) { 11111 throw e.rethrowFromSystemServer(); 11112 } 11113 } 11114 11115 /** 11116 * Returns a list of {@link WifiAvailableChannel} for the specified band and operational 11117 * mode(s), that is allowed for the current regulatory domain. An empty list implies that there 11118 * are no available channels for use. 11119 * 11120 * Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*} 11121 * constant is limited to one of the band values specified below. Specifically, if the 5GHz 11122 * band is included then it must include the DFS channels - an exception will be thrown 11123 * otherwise. The caller should not make any assumptions about whether DFS channels are allowed. 11124 * This API will indicate whether DFS channels are allowed for the specified operation mode(s) 11125 * per device policy. 11126 * 11127 * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} 11128 * constants. 11129 * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED}=0 - no band specified; Looks for the 11130 * channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz 11131 * 2. {@code WifiScanner#WIFI_BAND_24_GHZ}=1 11132 * 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}=6 11133 * 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}=7 11134 * 5. {@code WifiScanner#WIFI_BAND_6_GHZ}=8 11135 * 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}=15 11136 * 7. {@code WifiScanner#WIFI_BAND_60_GHZ}=16 11137 * 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}=31 11138 * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants 11139 * e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE} 11140 * @return a list of {@link WifiAvailableChannel} 11141 * 11142 * @throws UnsupportedOperationException - if this API is not supported on this device 11143 * or IllegalArgumentException - if the band specified is not one among the list 11144 * of bands mentioned above. 11145 */ 11146 @RequiresApi(Build.VERSION_CODES.S) 11147 @NonNull 11148 @RequiresPermission(NEARBY_WIFI_DEVICES) getAllowedChannels( int band, @WifiAvailableChannel.OpMode int mode)11149 public List<WifiAvailableChannel> getAllowedChannels( 11150 int band, 11151 @WifiAvailableChannel.OpMode int mode) { 11152 if (!SdkLevel.isAtLeastS()) { 11153 throw new UnsupportedOperationException(); 11154 } 11155 try { 11156 Bundle extras = new Bundle(); 11157 if (SdkLevel.isAtLeastS()) { 11158 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 11159 mContext.getAttributionSource()); 11160 } 11161 return mService.getUsableChannels(band, mode, 11162 WifiAvailableChannel.FILTER_REGULATORY, mContext.getOpPackageName(), extras); 11163 } catch (RemoteException e) { 11164 throw e.rethrowFromSystemServer(); 11165 } 11166 } 11167 11168 /** 11169 * Returns a list of {@link WifiAvailableChannel} for the specified band and operational 11170 * mode(s) per the current regulatory domain and device-specific constraints such as concurrency 11171 * state and interference due to other radios. An empty list implies that there are no available 11172 * channels for use. 11173 * 11174 * Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*} 11175 * constant is limited to one of the band values specified below. Specifically, if the 5GHz 11176 * band is included then it must include the DFS channels - an exception will be thrown 11177 * otherwise. The caller should not make any assumptions about whether DFS channels are allowed. 11178 * This API will indicate whether DFS channels are allowed for the specified operation mode(s) 11179 * per device policy. 11180 * 11181 * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} 11182 * constants. 11183 * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED}=0 - no band specified; Looks for the 11184 * channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz 11185 * 2. {@code WifiScanner#WIFI_BAND_24_GHZ}=1 11186 * 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}=6 11187 * 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}=7 11188 * 5. {@code WifiScanner#WIFI_BAND_6_GHZ}=8 11189 * 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}=15 11190 * 7. {@code WifiScanner#WIFI_BAND_60_GHZ}=16 11191 * 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}=31 11192 * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants 11193 * e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE} 11194 * @return a list of {@link WifiAvailableChannel} 11195 * 11196 * @throws UnsupportedOperationException - if this API is not supported on this device 11197 * or IllegalArgumentException - if the band specified is not one among the list 11198 * of bands mentioned above. 11199 */ 11200 @RequiresApi(Build.VERSION_CODES.S) 11201 @NonNull 11202 @RequiresPermission(NEARBY_WIFI_DEVICES) getUsableChannels( int band, @WifiAvailableChannel.OpMode int mode)11203 public List<WifiAvailableChannel> getUsableChannels( 11204 int band, 11205 @WifiAvailableChannel.OpMode int mode) { 11206 if (!SdkLevel.isAtLeastS()) { 11207 throw new UnsupportedOperationException(); 11208 } 11209 try { 11210 Bundle extras = new Bundle(); 11211 if (SdkLevel.isAtLeastS()) { 11212 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 11213 mContext.getAttributionSource()); 11214 } 11215 return mService.getUsableChannels(band, mode, 11216 WifiAvailableChannel.getUsableFilter(), mContext.getOpPackageName(), extras); 11217 } catch (RemoteException e) { 11218 throw e.rethrowFromSystemServer(); 11219 } 11220 } 11221 11222 /** 11223 * If the device supports Wi-Fi Passpoint, the user can explicitly enable or disable it. 11224 * That status can be queried using this method. 11225 * @return {@code true} if Wi-Fi Passpoint is enabled 11226 * 11227 */ 11228 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) isWifiPasspointEnabled()11229 public boolean isWifiPasspointEnabled() { 11230 try { 11231 return mService.isWifiPasspointEnabled(); 11232 } catch (RemoteException e) { 11233 throw e.rethrowFromSystemServer(); 11234 } 11235 } 11236 11237 /** 11238 * Explicitly enable or disable Wi-Fi Passpoint as a global switch. 11239 * The global Passpoint enabling/disabling overrides individual configuration 11240 * enabling/disabling. 11241 * Passpoint global status can be queried by {@link WifiManager#isWifiPasspointEnabled }. 11242 * 11243 * @param enabled {@code true} to enable, {@code false} to disable. 11244 * @hide 11245 */ 11246 @SystemApi 11247 @RequiresPermission(anyOf = { 11248 android.Manifest.permission.NETWORK_SETTINGS, 11249 android.Manifest.permission.NETWORK_SETUP_WIZARD 11250 }) setWifiPasspointEnabled(boolean enabled)11251 public void setWifiPasspointEnabled(boolean enabled) { 11252 if (mVerboseLoggingEnabled) { 11253 Log.v(TAG, "setWifiPasspointEnabled: " + enabled); 11254 } 11255 try { 11256 mService.setWifiPasspointEnabled(enabled); 11257 } catch (RemoteException e) { 11258 throw e.rethrowFromSystemServer(); 11259 } 11260 } 11261 11262 /** 11263 * The device may support concurrent connections to multiple internet-providing Wi-Fi 11264 * networks (APs) - that is indicated by 11265 * {@link WifiManager#isStaConcurrencyForMultiInternetSupported()}. 11266 * This method indicates whether or not the feature is currently enabled. 11267 * A value of {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DISABLED} indicates that the feature 11268 * is disabled, a value of {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DBS_AP} or 11269 * {@link WifiManager#WIFI_MULTI_INTERNET_MODE_MULTI_AP} indicates that the feature is enabled. 11270 * 11271 * The app can register to receive the corresponding Wi-Fi networks using the 11272 * {@link ConnectivityManager#registerNetworkCallback(NetworkRequest, NetworkCallback)} API with 11273 * a {@link WifiNetworkSpecifier} configured using the 11274 * {@link WifiNetworkSpecifier.Builder#setBand(int)} method. 11275 */ 11276 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11277 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) getStaConcurrencyForMultiInternetMode()11278 public @WifiMultiInternetMode int getStaConcurrencyForMultiInternetMode() { 11279 try { 11280 return mService.getStaConcurrencyForMultiInternetMode(); 11281 } catch (RemoteException e) { 11282 throw e.rethrowFromSystemServer(); 11283 } 11284 } 11285 11286 /** 11287 * Check if the currently connected network meets the minimum required Wi-Fi security level set. 11288 * If not, the current network will be disconnected. 11289 * 11290 * @throws SecurityException if the caller does not have permission. 11291 * @hide 11292 */ 11293 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11294 @SystemApi 11295 @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) notifyMinimumRequiredWifiSecurityLevelChanged(int level)11296 public void notifyMinimumRequiredWifiSecurityLevelChanged(int level) { 11297 if (mVerboseLoggingEnabled) { 11298 Log.v(TAG, "notifyMinimumRequiredWifiSecurityLevelChanged"); 11299 } 11300 try { 11301 mService.notifyMinimumRequiredWifiSecurityLevelChanged(level); 11302 } catch (RemoteException e) { 11303 throw e.rethrowFromSystemServer(); 11304 } 11305 } 11306 11307 /** 11308 * Check if the currently connected network meets the Wi-Fi SSID policy set. 11309 * If not, the current network will be disconnected. 11310 * 11311 * @throws SecurityException if the caller does not have permission. 11312 * @hide 11313 */ 11314 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11315 @SystemApi 11316 @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) notifyWifiSsidPolicyChanged(@onNull WifiSsidPolicy policy)11317 public void notifyWifiSsidPolicyChanged(@NonNull WifiSsidPolicy policy) { 11318 if (mVerboseLoggingEnabled) { 11319 Log.v(TAG, "notifyWifiSsidPolicyChanged"); 11320 } 11321 try { 11322 if (policy != null) { 11323 mService.notifyWifiSsidPolicyChanged( 11324 policy.getPolicyType(), new ArrayList<>(policy.getSsids())); 11325 } 11326 } catch (RemoteException e) { 11327 throw e.rethrowFromSystemServer(); 11328 } 11329 } 11330 11331 /** 11332 * Configure whether or not concurrent multiple connections to internet-providing Wi-Fi 11333 * networks (AP) is enabled. 11334 * Use {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DISABLED} to disable, and either 11335 * {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DBS_AP} or 11336 * {@link WifiManager#WIFI_MULTI_INTERNET_MODE_MULTI_AP} to enable in different modes. 11337 * The {@link WifiManager#getStaConcurrencyForMultiInternetMode() } can be used to retrieve 11338 * the current mode. 11339 * 11340 * @param mode Multi internet mode. 11341 * @return true when the mode is set successfully, false when failed. 11342 * @hide 11343 */ 11344 @SystemApi 11345 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11346 @RequiresPermission(anyOf = { 11347 android.Manifest.permission.NETWORK_SETTINGS, 11348 android.Manifest.permission.NETWORK_SETUP_WIZARD 11349 }) setStaConcurrencyForMultiInternetMode(@ifiMultiInternetMode int mode)11350 public boolean setStaConcurrencyForMultiInternetMode(@WifiMultiInternetMode int mode) { 11351 if (mVerboseLoggingEnabled) { 11352 Log.v(TAG, "setStaConcurrencyForMultiInternetMode: " + mode); 11353 } 11354 try { 11355 return mService.setStaConcurrencyForMultiInternetMode(mode); 11356 } catch (RemoteException e) { 11357 throw e.rethrowFromSystemServer(); 11358 } 11359 } 11360 11361 /** 11362 * Intent action to launch a dialog from the WifiDialog app. 11363 * Must include EXTRA_DIALOG_ID, EXTRA_DIALOG_TYPE, and appropriate extras for the dialog type. 11364 * @hide 11365 */ 11366 public static final String ACTION_LAUNCH_DIALOG = 11367 "android.net.wifi.action.LAUNCH_DIALOG"; 11368 11369 /** 11370 * Intent action to dismiss an existing dialog from the WifiDialog app. 11371 * Must include EXTRA_DIALOG_ID. 11372 * @hide 11373 */ 11374 public static final String ACTION_DISMISS_DIALOG = 11375 "android.net.wifi.action.DISMISS_DIALOG"; 11376 11377 /** 11378 * Unknown DialogType. 11379 * @hide 11380 */ 11381 public static final int DIALOG_TYPE_UNKNOWN = 0; 11382 11383 /** 11384 * DialogType for a simple dialog. 11385 * @see {@link com.android.server.wifi.WifiDialogManager#createSimpleDialog} 11386 * @hide 11387 */ 11388 public static final int DIALOG_TYPE_SIMPLE = 1; 11389 11390 /** 11391 * DialogType for a P2P Invitation Sent dialog. 11392 * @see {@link com.android.server.wifi.WifiDialogManager#createP2pInvitationSentDialog} 11393 * @hide 11394 */ 11395 public static final int DIALOG_TYPE_P2P_INVITATION_SENT = 2; 11396 11397 /** 11398 * DialogType for a P2P Invitation Received dialog. 11399 * @see {@link com.android.server.wifi.WifiDialogManager#createP2pInvitationReceivedDialog} 11400 * @hide 11401 */ 11402 public static final int DIALOG_TYPE_P2P_INVITATION_RECEIVED = 3; 11403 11404 /** @hide */ 11405 @IntDef(prefix = { "DIALOG_TYPE_" }, value = { 11406 DIALOG_TYPE_UNKNOWN, 11407 DIALOG_TYPE_SIMPLE, 11408 DIALOG_TYPE_P2P_INVITATION_SENT, 11409 DIALOG_TYPE_P2P_INVITATION_RECEIVED, 11410 }) 11411 @Retention(RetentionPolicy.SOURCE) 11412 public @interface DialogType {} 11413 11414 /** 11415 * Dialog positive button was clicked. 11416 * @hide 11417 */ 11418 public static final int DIALOG_REPLY_POSITIVE = 0; 11419 11420 /** 11421 * Dialog negative button was clicked. 11422 * @hide 11423 */ 11424 public static final int DIALOG_REPLY_NEGATIVE = 1; 11425 11426 /** 11427 * Dialog neutral button was clicked. 11428 * @hide 11429 */ 11430 public static final int DIALOG_REPLY_NEUTRAL = 2; 11431 11432 /** 11433 * Dialog was cancelled. 11434 * @hide 11435 */ 11436 public static final int DIALOG_REPLY_CANCELLED = 3; 11437 11438 /** 11439 * Indication of a reply to a dialog. 11440 * See {@link WifiManager#replyToSimpleDialog(int, int)} 11441 * @hide 11442 */ 11443 @IntDef(prefix = { "DIALOG_TYPE_" }, value = { 11444 DIALOG_REPLY_POSITIVE, 11445 DIALOG_REPLY_NEGATIVE, 11446 DIALOG_REPLY_NEUTRAL, 11447 DIALOG_REPLY_CANCELLED, 11448 }) 11449 @Retention(RetentionPolicy.SOURCE) 11450 public @interface DialogReply {} 11451 11452 /** 11453 * Invalid dialog id for dialogs that are not currently active. 11454 * @hide 11455 */ 11456 public static final int INVALID_DIALOG_ID = -1; 11457 11458 /** 11459 * Extra int indicating the type of dialog to display. 11460 * @hide 11461 */ 11462 public static final String EXTRA_DIALOG_TYPE = "android.net.wifi.extra.DIALOG_TYPE"; 11463 11464 /** 11465 * Extra int indicating the ID of a dialog. The value must not be {@link #INVALID_DIALOG_ID}. 11466 * @hide 11467 */ 11468 public static final String EXTRA_DIALOG_ID = "android.net.wifi.extra.DIALOG_ID"; 11469 11470 /** 11471 * Extra String indicating the title of a simple dialog. 11472 * @hide 11473 */ 11474 public static final String EXTRA_DIALOG_TITLE = "android.net.wifi.extra.DIALOG_TITLE"; 11475 11476 /** 11477 * Extra String indicating the message of a simple dialog. 11478 * @hide 11479 */ 11480 public static final String EXTRA_DIALOG_MESSAGE = "android.net.wifi.extra.DIALOG_MESSAGE"; 11481 11482 /** 11483 * Extra String indicating the message URL of a simple dialog. 11484 * @hide 11485 */ 11486 public static final String EXTRA_DIALOG_MESSAGE_URL = 11487 "android.net.wifi.extra.DIALOG_MESSAGE_URL"; 11488 11489 /** 11490 * Extra String indicating the start index of a message URL span of a simple dialog. 11491 * @hide 11492 */ 11493 public static final String EXTRA_DIALOG_MESSAGE_URL_START = 11494 "android.net.wifi.extra.DIALOG_MESSAGE_URL_START"; 11495 11496 /** 11497 * Extra String indicating the end index of a message URL span of a simple dialog. 11498 * @hide 11499 */ 11500 public static final String EXTRA_DIALOG_MESSAGE_URL_END = 11501 "android.net.wifi.extra.DIALOG_MESSAGE_URL_END"; 11502 11503 /** 11504 * Extra String indicating the positive button text of a simple dialog. 11505 * @hide 11506 */ 11507 public static final String EXTRA_DIALOG_POSITIVE_BUTTON_TEXT = 11508 "android.net.wifi.extra.DIALOG_POSITIVE_BUTTON_TEXT"; 11509 11510 /** 11511 * Extra String indicating the negative button text of a simple dialog. 11512 * @hide 11513 */ 11514 public static final String EXTRA_DIALOG_NEGATIVE_BUTTON_TEXT = 11515 "android.net.wifi.extra.DIALOG_NEGATIVE_BUTTON_TEXT"; 11516 11517 /** 11518 * Extra String indicating the neutral button text of a simple dialog. 11519 * @hide 11520 */ 11521 public static final String EXTRA_DIALOG_NEUTRAL_BUTTON_TEXT = 11522 "android.net.wifi.extra.DIALOG_NEUTRAL_BUTTON_TEXT"; 11523 11524 /** 11525 * Extra long indicating the timeout in milliseconds of a dialog. 11526 * @hide 11527 */ 11528 public static final String EXTRA_DIALOG_TIMEOUT_MS = "android.net.wifi.extra.DIALOG_TIMEOUT_MS"; 11529 11530 /** 11531 * Extra String indicating a P2P device name for a P2P Invitation Sent/Received dialog. 11532 * @hide 11533 */ 11534 public static final String EXTRA_P2P_DEVICE_NAME = "android.net.wifi.extra.P2P_DEVICE_NAME"; 11535 11536 /** 11537 * Extra boolean indicating that a PIN is requested for a P2P Invitation Received dialog. 11538 * @hide 11539 */ 11540 public static final String EXTRA_P2P_PIN_REQUESTED = "android.net.wifi.extra.P2P_PIN_REQUESTED"; 11541 11542 /** 11543 * Extra String indicating the PIN to be displayed for a P2P Invitation Sent/Received dialog. 11544 * @hide 11545 */ 11546 public static final String EXTRA_P2P_DISPLAY_PIN = "android.net.wifi.extra.P2P_DISPLAY_PIN"; 11547 11548 /** 11549 * Extra boolean indicating ACTION_CLOSE_SYSTEM_DIALOGS should not close the Wi-Fi dialogs. 11550 * @hide 11551 */ 11552 public static final String EXTRA_CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI = 11553 "android.net.wifi.extra.CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI"; 11554 11555 /** 11556 * Returns a set of packages that aren't DO or PO but should be able to manage WiFi networks. 11557 * @hide 11558 */ 11559 @SystemApi 11560 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) 11561 @NonNull getOemPrivilegedWifiAdminPackages()11562 public Set<String> getOemPrivilegedWifiAdminPackages() { 11563 try { 11564 return new ArraySet<>(mService.getOemPrivilegedWifiAdminPackages()); 11565 } catch (RemoteException e) { 11566 throw e.rethrowFromSystemServer(); 11567 } 11568 } 11569 11570 /** 11571 * Method for WifiDialog to notify the framework of a reply to a simple dialog. 11572 * @param dialogId id of the replying dialog. 11573 * @param reply reply of the dialog. 11574 * @hide 11575 */ replyToSimpleDialog(int dialogId, @DialogReply int reply)11576 public void replyToSimpleDialog(int dialogId, @DialogReply int reply) { 11577 if (mVerboseLoggingEnabled) { 11578 Log.v(TAG, "replyToWifiEnableRequestDialog: dialogId=" + dialogId 11579 + " reply=" + reply); 11580 } 11581 try { 11582 mService.replyToSimpleDialog(dialogId, reply); 11583 } catch (RemoteException e) { 11584 throw e.rethrowFromSystemServer(); 11585 } 11586 } 11587 11588 /** 11589 * Method for WifiDialog to notify the framework of a reply to a P2P Invitation Received dialog. 11590 * @param dialogId id of the replying dialog. 11591 * @param accepted Whether the invitation was accepted. 11592 * @param optionalPin PIN of the reply, or {@code null} if none was supplied. 11593 * @hide 11594 */ replyToP2pInvitationReceivedDialog( int dialogId, boolean accepted, @Nullable String optionalPin)11595 public void replyToP2pInvitationReceivedDialog( 11596 int dialogId, boolean accepted, @Nullable String optionalPin) { 11597 if (mVerboseLoggingEnabled) { 11598 Log.v(TAG, "replyToP2pInvitationReceivedDialog: " 11599 + "dialogId=" + dialogId 11600 + ", accepted=" + accepted 11601 + ", pin=" + optionalPin); 11602 } 11603 try { 11604 mService.replyToP2pInvitationReceivedDialog(dialogId, accepted, optionalPin); 11605 } catch (RemoteException e) { 11606 throw e.rethrowFromSystemServer(); 11607 } 11608 } 11609 11610 /** 11611 * Specify a list of DHCP options to use for any network whose SSID is specified and which 11612 * transmits vendor-specific information elements (VSIEs) using the specified Organizationally 11613 * Unique Identifier (OUI). If the AP transmits VSIEs for multiple specified OUIs then all 11614 * matching DHCP options will be used. The allowlist for DHCP options in 11615 * {@link android.net.ip.IpClient} gates whether the DHCP options will actually be used. 11616 * When DHCP options are used: if the option value {@link android.net.DhcpOption#getValue()} 11617 * is null, the option type {@link android.net.DhcpOption#getType()} will be put in the 11618 * Parameter Request List in the DHCP packets; otherwise, the option will be included in the 11619 * options section in the DHCP packets. Use {@link #removeCustomDhcpOptions(Object, Object)} 11620 * to remove the specified DHCP options. 11621 * 11622 * @param ssid the network SSID. 11623 * @param oui the 3-byte OUI. 11624 * @param options the list of {@link android.net.DhcpOption}. 11625 * 11626 * @hide 11627 */ 11628 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 11629 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11630 @RequiresPermission(anyOf = { 11631 android.Manifest.permission.NETWORK_SETTINGS, 11632 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 11633 }) addCustomDhcpOptions(@onNull WifiSsid ssid, @NonNull byte[] oui, @NonNull List<DhcpOption> options)11634 public void addCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui, 11635 @NonNull List<DhcpOption> options) { 11636 try { 11637 mService.addCustomDhcpOptions(ssid, oui, options); 11638 } catch (RemoteException e) { 11639 throw e.rethrowFromSystemServer(); 11640 } 11641 } 11642 11643 /** 11644 * Remove custom DHCP options specified by {@link #addCustomDhcpOptions(Object, Object, List)}. 11645 * 11646 * @param ssid the network SSID. 11647 * @param oui the 3-byte OUI. 11648 * 11649 * @hide 11650 */ 11651 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 11652 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11653 @RequiresPermission(anyOf = { 11654 android.Manifest.permission.NETWORK_SETTINGS, 11655 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 11656 }) removeCustomDhcpOptions(@onNull WifiSsid ssid, @NonNull byte[] oui)11657 public void removeCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui) { 11658 try { 11659 mService.removeCustomDhcpOptions(ssid, oui); 11660 } catch (RemoteException e) { 11661 throw e.rethrowFromSystemServer(); 11662 } 11663 } 11664 11665 /** 11666 * Wi-Fi interface of type STA (station/client Wi-Fi infrastructure device). 11667 */ 11668 public static final int WIFI_INTERFACE_TYPE_STA = 0; 11669 11670 /** 11671 * Wi-Fi interface of type AP (access point Wi-Fi infrastructure device). 11672 */ 11673 public static final int WIFI_INTERFACE_TYPE_AP = 1; 11674 11675 /** 11676 * Wi-Fi interface of type Wi-Fi Aware (aka NAN). 11677 */ 11678 public static final int WIFI_INTERFACE_TYPE_AWARE = 2; 11679 11680 /** 11681 * Wi-Fi interface of type Wi-Fi Direct (aka P2P). 11682 */ 11683 public static final int WIFI_INTERFACE_TYPE_DIRECT = 3; 11684 11685 /** @hide */ 11686 @IntDef(prefix = { "WIFI_INTERFACE_TYPE_" }, value = { 11687 WIFI_INTERFACE_TYPE_STA, 11688 WIFI_INTERFACE_TYPE_AP, 11689 WIFI_INTERFACE_TYPE_AWARE, 11690 WIFI_INTERFACE_TYPE_DIRECT, 11691 }) 11692 @Retention(RetentionPolicy.SOURCE) 11693 public @interface WifiInterfaceType {} 11694 11695 /** 11696 * Class describing an impact of interface creation - returned by 11697 * {@link #reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}. Due to Wi-Fi 11698 * concurrency limitations certain interfaces may have to be torn down. Each of these 11699 * interfaces was requested by a set of applications who could potentially be impacted. 11700 * 11701 * This class contain the information for a single interface: the interface type with 11702 * {@link InterfaceCreationImpact#getInterfaceType()} and the set of impacted packages 11703 * with {@link InterfaceCreationImpact#getPackages()}. 11704 */ 11705 public static class InterfaceCreationImpact { 11706 private final int mInterfaceType; 11707 private final Set<String> mPackages; 11708 InterfaceCreationImpact(@ifiInterfaceType int interfaceType, @NonNull Set<String> packages)11709 public InterfaceCreationImpact(@WifiInterfaceType int interfaceType, 11710 @NonNull Set<String> packages) { 11711 mInterfaceType = interfaceType; 11712 mPackages = packages; 11713 } 11714 11715 /** 11716 * @return The interface type which will be torn down to make room for the interface 11717 * requested in {@link #reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}. 11718 */ getInterfaceType()11719 public @WifiInterfaceType int getInterfaceType() { 11720 return mInterfaceType; 11721 } 11722 11723 /** 11724 * @return The list of potentially impacted packages due to tearing down the interface 11725 * specified in {@link #getInterfaceType()}. 11726 */ getPackages()11727 public @NonNull Set<String> getPackages() { 11728 return mPackages; 11729 } 11730 11731 @Override hashCode()11732 public int hashCode() { 11733 return Objects.hash(mInterfaceType, mPackages); 11734 } 11735 11736 @Override equals(Object that)11737 public boolean equals(Object that) { 11738 if (this == that) return true; 11739 if (!(that instanceof InterfaceCreationImpact)) return false; 11740 InterfaceCreationImpact thatInterfaceCreationImpact = (InterfaceCreationImpact) that; 11741 11742 return this.mInterfaceType == thatInterfaceCreationImpact.mInterfaceType 11743 && Objects.equals(this.mPackages, thatInterfaceCreationImpact.mPackages); 11744 } 11745 } 11746 11747 /** 11748 * Queries the framework to determine whether the specified interface can be created, and if 11749 * so - what other interfaces would be torn down by the framework to allow this creation if 11750 * it were requested. The result is returned via the specified {@link BiConsumer} callback 11751 * which returns two arguments: 11752 * <li>First argument: a {@code boolean} - indicating whether or not the interface can be 11753 * created.</li> 11754 * <li>Second argument: a {@code Set<InterfaceCreationImpact>} - if the interface can be 11755 * created (first argument is {@code true} then this is the set of interface types which 11756 * will be removed and the packages which requested them. Possibly an empty set. If the 11757 * first argument is {@code false}, then an empty set will be returned here.</li> 11758 * <p> 11759 * Interfaces, input and output, are specified using the {@code WIFI_INTERFACE_*} constants: 11760 * {@link #WIFI_INTERFACE_TYPE_STA}, {@link #WIFI_INTERFACE_TYPE_AP}, 11761 * {@link #WIFI_INTERFACE_TYPE_AWARE}, or {@link #WIFI_INTERFACE_TYPE_DIRECT}. 11762 * <p> 11763 * This method does not actually create the interface. That operation is handled by the 11764 * framework when a particular service method is called. E.g. a Wi-Fi Direct interface may be 11765 * created when various methods of {@link android.net.wifi.p2p.WifiP2pManager} are called, 11766 * similarly for Wi-Fi Aware and {@link android.net.wifi.aware.WifiAwareManager}. 11767 * <p> 11768 * Note: the information returned via this method is the current snapshot of the system. It may 11769 * change due to actions of the framework or other apps. 11770 * 11771 * @param interfaceType The interface type whose possible creation is being queried. 11772 * @param requireNewInterface Indicates that the query is for a new interface of the specified 11773 * type - an existing interface won't meet the query. Some 11774 * operations (such as Wi-Fi Direct and Wi-Fi Aware are a shared 11775 * resource and so may not need a new interface). 11776 * @param executor An {@link Executor} on which to return the result. 11777 * @param resultCallback The asynchronous callback which will return two argument: a 11778 * {@code boolean} (whether the interface can be created), and a 11779 * {@code Set<InterfaceCreationImpact>} (a set of {@link InterfaceCreationImpact}: 11780 * interfaces which will be destroyed when the interface is created 11781 * and the packages which requested them and thus may be impacted). 11782 */ 11783 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11784 @RequiresPermission(allOf = {android.Manifest.permission.MANAGE_WIFI_INTERFACES, 11785 ACCESS_WIFI_STATE}) reportCreateInterfaceImpact(@ifiInterfaceType int interfaceType, boolean requireNewInterface, @NonNull @CallbackExecutor Executor executor, @NonNull BiConsumer<Boolean, Set<InterfaceCreationImpact>> resultCallback)11786 public void reportCreateInterfaceImpact(@WifiInterfaceType int interfaceType, 11787 boolean requireNewInterface, 11788 @NonNull @CallbackExecutor Executor executor, 11789 @NonNull BiConsumer<Boolean, Set<InterfaceCreationImpact>> resultCallback) { 11790 Objects.requireNonNull(executor, "Non-null executor required"); 11791 Objects.requireNonNull(resultCallback, "Non-null resultCallback required"); 11792 try { 11793 mService.reportCreateInterfaceImpact(mContext.getOpPackageName(), interfaceType, 11794 requireNewInterface, new IInterfaceCreationInfoCallback.Stub() { 11795 @Override 11796 public void onResults(boolean canCreate, int[] interfacesToDelete, 11797 String[] packagesForInterfaces) { 11798 Binder.clearCallingIdentity(); 11799 if ((interfacesToDelete == null && packagesForInterfaces != null) 11800 || (interfacesToDelete != null 11801 && packagesForInterfaces == null) || (canCreate && ( 11802 interfacesToDelete == null || interfacesToDelete.length 11803 != packagesForInterfaces.length))) { 11804 Log.e(TAG, 11805 "reportImpactToCreateIfaceRequest: Invalid callback " 11806 + "parameters - canCreate=" 11807 + canCreate + ", interfacesToDelete=" 11808 + Arrays.toString(interfacesToDelete) 11809 + ", worksourcesForInterfaces=" 11810 + Arrays.toString(packagesForInterfaces)); 11811 return; 11812 } 11813 11814 final Set<InterfaceCreationImpact> finalSet = 11815 (canCreate && interfacesToDelete.length > 0) ? new ArraySet<>() 11816 : Collections.emptySet(); 11817 if (canCreate) { 11818 for (int i = 0; i < interfacesToDelete.length; ++i) { 11819 finalSet.add( 11820 new InterfaceCreationImpact(interfacesToDelete[i], 11821 packagesForInterfaces[i] == null 11822 ? Collections.emptySet() 11823 : new ArraySet<>( 11824 packagesForInterfaces[i] 11825 .split(",")))); 11826 } 11827 } 11828 executor.execute(() -> resultCallback.accept(canCreate, finalSet)); 11829 } 11830 }); 11831 } catch (RemoteException e) { 11832 throw e.rethrowFromSystemServer(); 11833 } 11834 } 11835 11836 /** 11837 * Returns the max number of channels that is allowed to be set on a 11838 * {@link WifiNetworkSpecifier}. 11839 * @see WifiNetworkSpecifier.Builder#setPreferredChannelsFrequenciesMhz(int[]) 11840 * 11841 * @return The max number of channels can be set on a request. 11842 */ 11843 getMaxNumberOfChannelsPerNetworkSpecifierRequest()11844 public int getMaxNumberOfChannelsPerNetworkSpecifierRequest() { 11845 try { 11846 return mService.getMaxNumberOfChannelsPerRequest(); 11847 } catch (RemoteException e) { 11848 throw e.rethrowFromSystemServer(); 11849 } 11850 } 11851 11852 /** 11853 * Add a list of new application-initiated QoS policies. 11854 * 11855 * Note: Policies are managed using a policy ID, which can be retrieved using 11856 * {@link QosPolicyParams#getPolicyId()}. This ID can be used when removing a policy via 11857 * {@link #removeQosPolicies(int[])}. The caller is in charge of assigning and managing 11858 * the policy IDs for any requested policies. 11859 * 11860 * Note: Policies with duplicate IDs are not allowed. To update an existing policy, first 11861 * remove it using {@link #removeQosPolicies(int[])}, and then re-add it using this API. 11862 * 11863 * Note: All policies in a single request must have the same {@link QosPolicyParams.Direction}. 11864 * 11865 * Note: Support for the {@link QosPolicyParams#DIRECTION_UPLINK} direction is added in 11866 * {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}. For earlier releases, 11867 * only the {@link QosPolicyParams#DIRECTION_DOWNLINK} direction is supported. 11868 * 11869 * @param policyParamsList List of {@link QosPolicyParams} objects describing the requested 11870 * policies. Must have a maximum length of 11871 * {@link #getMaxNumberOfPoliciesPerQosRequest()}. 11872 * @param executor The executor on which callback will be invoked. 11873 * @param resultsCallback An asynchronous callback that will return a list of integer status 11874 * codes from {@link QosRequestStatus}. Result list will be the same 11875 * length as the input list, and each status code will correspond to 11876 * the policy at that index in the input list. 11877 * 11878 * @throws SecurityException if caller does not have the required permissions. 11879 * @throws NullPointerException if the caller provided a null input. 11880 * @throws UnsupportedOperationException if the feature is not enabled. 11881 * @throws IllegalArgumentException if the input list is invalid. 11882 * @hide 11883 */ 11884 @SystemApi 11885 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11886 @RequiresPermission(anyOf = { 11887 android.Manifest.permission.NETWORK_SETTINGS, 11888 MANAGE_WIFI_NETWORK_SELECTION 11889 }) addQosPolicies(@onNull List<QosPolicyParams> policyParamsList, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<List<Integer>> resultsCallback)11890 public void addQosPolicies(@NonNull List<QosPolicyParams> policyParamsList, 11891 @NonNull @CallbackExecutor Executor executor, 11892 @NonNull Consumer<List<Integer>> resultsCallback) { 11893 Objects.requireNonNull(policyParamsList, "policyParamsList cannot be null"); 11894 Objects.requireNonNull(executor, "executor cannot be null"); 11895 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 11896 try { 11897 mService.addQosPolicies(policyParamsList, new Binder(), mContext.getOpPackageName(), 11898 new IListListener.Stub() { 11899 @Override 11900 public void onResult(List value) { 11901 Binder.clearCallingIdentity(); 11902 executor.execute(() -> { 11903 resultsCallback.accept(value); 11904 }); 11905 } 11906 }); 11907 } catch (RemoteException e) { 11908 throw e.rethrowFromSystemServer(); 11909 } 11910 } 11911 11912 /** 11913 * Remove a list of existing application-initiated QoS policies, previously added via 11914 * {@link #addQosPolicies(List, Executor, Consumer)}. 11915 * 11916 * Note: Policies are identified by their policy IDs, which are assigned by the caller. The ID 11917 * for a given policy can be retrieved using {@link QosPolicyParams#getPolicyId()}. 11918 * 11919 * @param policyIdList List of policy IDs corresponding to the policies to remove. Must have 11920 * a maximum length of {@link #getMaxNumberOfPoliciesPerQosRequest()}. 11921 * @throws SecurityException if caller does not have the required permissions. 11922 * @throws NullPointerException if the caller provided a null input. 11923 * @throws IllegalArgumentException if the input list is invalid. 11924 * @hide 11925 */ 11926 @SystemApi 11927 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11928 @RequiresPermission(anyOf = { 11929 android.Manifest.permission.NETWORK_SETTINGS, 11930 MANAGE_WIFI_NETWORK_SELECTION 11931 }) removeQosPolicies(@onNull int[] policyIdList)11932 public void removeQosPolicies(@NonNull int[] policyIdList) { 11933 Objects.requireNonNull(policyIdList, "policyIdList cannot be null"); 11934 try { 11935 mService.removeQosPolicies(policyIdList, mContext.getOpPackageName()); 11936 } catch (RemoteException e) { 11937 throw e.rethrowFromSystemServer(); 11938 } 11939 } 11940 11941 /** 11942 * Remove all application-initiated QoS policies requested by this caller, 11943 * previously added via {@link #addQosPolicies(List, Executor, Consumer)}. 11944 * 11945 * @throws SecurityException if caller does not have the required permissions. 11946 * @hide 11947 */ 11948 @SystemApi 11949 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11950 @RequiresPermission(anyOf = { 11951 android.Manifest.permission.NETWORK_SETTINGS, 11952 MANAGE_WIFI_NETWORK_SELECTION 11953 }) removeAllQosPolicies()11954 public void removeAllQosPolicies() { 11955 try { 11956 mService.removeAllQosPolicies(mContext.getOpPackageName()); 11957 } catch (RemoteException e) { 11958 throw e.rethrowFromSystemServer(); 11959 } 11960 } 11961 11962 /** 11963 * Set the link layer stats polling interval, in milliseconds. 11964 * 11965 * @param intervalMs a non-negative integer, for the link layer stats polling interval 11966 * in milliseconds. 11967 * To set a fixed interval, use a positive value. 11968 * For automatic handling of the interval, use value 0 11969 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 11970 * @throws SecurityException if the caller does not have permission. 11971 * @throws IllegalArgumentException if input is invalid. 11972 * @hide 11973 */ 11974 @SystemApi 11975 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11976 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) setLinkLayerStatsPollingInterval(@ntRange from = 0) int intervalMs)11977 public void setLinkLayerStatsPollingInterval(@IntRange (from = 0) int intervalMs) { 11978 try { 11979 mService.setLinkLayerStatsPollingInterval(intervalMs); 11980 } catch (RemoteException e) { 11981 throw e.rethrowFromSystemServer(); 11982 } 11983 } 11984 11985 /** 11986 * Get the link layer stats polling interval, in milliseconds. 11987 * 11988 * @param executor The executor on which callback will be invoked. 11989 * @param resultsCallback An asynchronous callback that will return current 11990 * link layer stats polling interval in milliseconds. 11991 * 11992 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 11993 * @throws SecurityException if the caller does not have permission. 11994 * @throws NullPointerException if the caller provided invalid inputs. 11995 * @hide 11996 */ 11997 @SystemApi 11998 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11999 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) getLinkLayerStatsPollingInterval(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)12000 public void getLinkLayerStatsPollingInterval(@NonNull @CallbackExecutor Executor executor, 12001 @NonNull Consumer<Integer> resultsCallback) { 12002 Objects.requireNonNull(executor, "executor cannot be null"); 12003 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12004 try { 12005 mService.getLinkLayerStatsPollingInterval( 12006 new IIntegerListener.Stub() { 12007 @Override 12008 public void onResult(int value) { 12009 Binder.clearCallingIdentity(); 12010 executor.execute(() -> { 12011 resultsCallback.accept(value); 12012 }); 12013 } 12014 }); 12015 } catch (RemoteException e) { 12016 throw e.rethrowFromSystemServer(); 12017 } 12018 } 12019 12020 /** 12021 * This API allows a privileged application to set Multi-Link Operation mode. 12022 * 12023 * Multi-link operation (MLO) will allow Wi-Fi devices to operate on multiple links at the same 12024 * time through a single connection, aiming to support applications that require lower latency, 12025 * and higher capacity. Chip vendors have algorithms that run on the chip to use available links 12026 * based on incoming traffic and various inputs. This API allows system application to give a 12027 * suggestion to such algorithms on its preference using {@link MloMode}. 12028 * 12029 * 12030 * @param mode Refer {@link MloMode} for supported modes. 12031 * @param executor The executor on which callback will be invoked. 12032 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 12033 * whether the MLO mode is successfully set or not. 12034 * @throws IllegalArgumentException if mode value is not in {@link MloMode}. 12035 * @throws NullPointerException if the caller provided a null input. 12036 * @throws SecurityException if caller does not have the required permissions. 12037 * @throws UnsupportedOperationException if the set operation is not supported on this SDK. 12038 * @hide 12039 */ 12040 @SystemApi 12041 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12042 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) setMloMode(@loMode int mode, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)12043 public void setMloMode(@MloMode int mode, @NonNull @CallbackExecutor Executor executor, 12044 @NonNull Consumer<Boolean> resultsCallback) { 12045 12046 if (mode < MLO_MODE_DEFAULT || mode > MLO_MODE_LOW_POWER) { 12047 throw new IllegalArgumentException("invalid mode: " + mode); 12048 } 12049 Objects.requireNonNull(executor, "executor cannot be null"); 12050 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12051 try { 12052 mService.setMloMode(mode, new IBooleanListener.Stub() { 12053 @Override 12054 public void onResult(boolean value) { 12055 Binder.clearCallingIdentity(); 12056 executor.execute(() -> { 12057 resultsCallback.accept(value); 12058 }); 12059 } 12060 }); 12061 } catch (RemoteException e) { 12062 throw e.rethrowFromSystemServer(); 12063 } 12064 } 12065 12066 /** 12067 * This API allows a privileged application to get Multi-Link Operation mode. Refer 12068 * {@link WifiManager#setMloMode(int, Executor, Consumer)} for more details. 12069 * 12070 * @param executor The executor on which callback will be invoked. 12071 * @param resultsCallback An asynchronous callback that will return current MLO mode. Returns 12072 * {@link MloMode#MLO_MODE_DEFAULT} if information is not available, 12073 * e.g. if the driver/firmware doesn't provide this information. 12074 * @throws NullPointerException if the caller provided a null input. 12075 * @throws SecurityException if caller does not have the required permissions. 12076 * @throws UnsupportedOperationException if the get operation is not supported on this SDK. 12077 * @hide 12078 */ 12079 @SystemApi 12080 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12081 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getMloMode(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)12082 public void getMloMode(@NonNull @CallbackExecutor Executor executor, 12083 @NonNull Consumer<Integer> resultsCallback) { 12084 Objects.requireNonNull(executor, "executor cannot be null"); 12085 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12086 try { 12087 mService.getMloMode(new IIntegerListener.Stub() { 12088 @Override 12089 public void onResult(int value) { 12090 Binder.clearCallingIdentity(); 12091 executor.execute(() -> { 12092 resultsCallback.accept(value); 12093 }); 12094 } 12095 }); 12096 } catch (RemoteException e) { 12097 throw e.rethrowFromSystemServer(); 12098 } 12099 } 12100 12101 /** 12102 * Get the maximum number of links supported by the chip for MLO association. e.g. if the Wi-Fi 12103 * chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous Transmit and 12104 * Receive) with following capabilities, 12105 * - Max MLO assoc link count = 3. 12106 * - Max MLO STR link count = 2. See 12107 * {@link WifiManager#getMaxMloStrLinkCount(Executor, Consumer)} 12108 * One of the possible configuration is - STR (2.4 GHz , eMLSR(5 GHz, 6 GHz)), provided the 12109 * radio combination of the chip supports it. 12110 * 12111 * @param executor The executor on which callback will be invoked. 12112 * @param resultsCallback An asynchronous callback that will return maximum MLO association link 12113 * count supported by the chip or -1 if error or not available. 12114 * @throws NullPointerException if the caller provided a null input. 12115 * @throws SecurityException if caller does not have the required permissions. 12116 * @throws UnsupportedOperationException if the get operation is not supported on this SDK. 12117 * @hide 12118 */ 12119 @SystemApi 12120 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12121 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12122 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getMaxMloAssociationLinkCount(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)12123 public void getMaxMloAssociationLinkCount(@NonNull @CallbackExecutor Executor executor, 12124 @NonNull Consumer<Integer> resultsCallback) { 12125 Objects.requireNonNull(executor, "executor cannot be null"); 12126 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12127 try { 12128 Bundle extras = new Bundle(); 12129 if (SdkLevel.isAtLeastS()) { 12130 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12131 mContext.getAttributionSource()); 12132 } 12133 mService.getMaxMloAssociationLinkCount(new IIntegerListener.Stub() { 12134 @Override 12135 public void onResult(int value) { 12136 Binder.clearCallingIdentity(); 12137 executor.execute(() -> { 12138 resultsCallback.accept(value); 12139 }); 12140 } 12141 }, extras); 12142 } catch (RemoteException e) { 12143 throw e.rethrowFromSystemServer(); 12144 } 12145 } 12146 12147 /** 12148 * Get the maximum number of STR links used in Multi-Link Operation. The maximum number of STR 12149 * links used for MLO can be different from the number of radios supported by the chip. e.g. if 12150 * the Wi-Fi chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous 12151 * Transmit and Receive) with following capabilities, 12152 * - Max MLO assoc link count = 3. See 12153 * {@link WifiManager#getMaxMloAssociationLinkCount(Executor, Consumer)}. 12154 * - Max MLO STR link count = 2. 12155 * One of the possible configuration is - STR (2.4 GHz, eMLSR(5 GHz, 6 GHz)), provided the radio 12156 * combination of the chip supports it. 12157 * 12158 * @param executor The executor on which callback will be invoked. 12159 * @param resultsCallback An asynchronous callback that will return maximum STR link count 12160 * supported by the chip in MLO mode or -1 if error or not available. 12161 * @throws NullPointerException if the caller provided a null input. 12162 * @throws SecurityException if caller does not have the required permissions. 12163 * @throws UnsupportedOperationException if the get operation is not supported on this SDK 12164 * @hide 12165 */ 12166 @SystemApi 12167 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12168 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12169 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getMaxMloStrLinkCount(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)12170 public void getMaxMloStrLinkCount(@NonNull @CallbackExecutor Executor executor, 12171 @NonNull Consumer<Integer> resultsCallback) { 12172 Objects.requireNonNull(executor, "executor cannot be null"); 12173 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12174 try { 12175 Bundle extras = new Bundle(); 12176 if (SdkLevel.isAtLeastS()) { 12177 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12178 mContext.getAttributionSource()); 12179 } 12180 mService.getMaxMloStrLinkCount(new IIntegerListener.Stub() { 12181 @Override 12182 public void onResult(int value) { 12183 Binder.clearCallingIdentity(); 12184 executor.execute(() -> { 12185 resultsCallback.accept(value); 12186 }); 12187 } 12188 }, extras); 12189 } catch (RemoteException e) { 12190 throw e.rethrowFromSystemServer(); 12191 } 12192 } 12193 12194 /** 12195 * Get the set of band combinations supported simultaneously by the Wi-Fi Chip. 12196 * 12197 * Note: This method returns simultaneous band operation combination and not multichannel 12198 * concurrent operation (MCC) combination. 12199 * 12200 * @param executor The executor on which callback will be invoked. 12201 * @param resultsCallback An asynchronous callback that will return a list of possible 12202 * simultaneous band combinations supported by the chip or empty list if 12203 * not available. Band value is defined in {@link WifiScanner.WifiBand}. 12204 * @throws NullPointerException if the caller provided a null input. 12205 * @throws SecurityException if caller does not have the required permissions. 12206 * @throws UnsupportedOperationException if the get operation is not supported on this SDK. 12207 * @hide 12208 */ 12209 @SystemApi 12210 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12211 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12212 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getSupportedSimultaneousBandCombinations( @onNull @allbackExecutor Executor executor, @NonNull Consumer<List<int[]>> resultsCallback)12213 public void getSupportedSimultaneousBandCombinations( 12214 @NonNull @CallbackExecutor Executor executor, 12215 @NonNull Consumer<List<int[]>> resultsCallback) { 12216 Objects.requireNonNull(executor, "executor cannot be null"); 12217 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12218 try { 12219 Bundle extras = new Bundle(); 12220 if (SdkLevel.isAtLeastS()) { 12221 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12222 mContext.getAttributionSource()); 12223 } 12224 mService.getSupportedSimultaneousBandCombinations(new IWifiBandsListener.Stub() { 12225 @Override 12226 public void onResult(WifiBands[] supportedBands) { 12227 Binder.clearCallingIdentity(); 12228 List<int[]> bandCombinations = new ArrayList<>(); 12229 for (WifiBands wifiBands : supportedBands) { 12230 bandCombinations.add(wifiBands.bands); 12231 } 12232 executor.execute(() -> { 12233 resultsCallback.accept(bandCombinations); 12234 }); 12235 } 12236 }, extras); 12237 } catch (RemoteException e) { 12238 throw e.rethrowFromSystemServer(); 12239 } 12240 } 12241 12242 /** 12243 * This API allows a privileged application to set whether or not this device allows 12244 * connections to Wi-Fi WEP networks. 12245 * 12246 * Note: The WEP connections may not work even if caller invokes this method with {@code true} 12247 * because device may NOT support connections to Wi-Fi WEP networks. 12248 * See: {@link #isWepSupported()}. 12249 * 12250 * @param isAllowed whether or not the user allow connections to Wi-Fi WEP networks. 12251 * @throws SecurityException if the caller does not have permission. 12252 * @hide 12253 */ 12254 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12255 @SystemApi 12256 @RequiresPermission(anyOf = { 12257 android.Manifest.permission.NETWORK_SETTINGS, 12258 android.Manifest.permission.NETWORK_SETUP_WIZARD 12259 }) setWepAllowed(boolean isAllowed)12260 public void setWepAllowed(boolean isAllowed) { 12261 try { 12262 mService.setWepAllowed(isAllowed); 12263 } catch (RemoteException e) { 12264 throw e.rethrowFromSystemServer(); 12265 } 12266 } 12267 12268 /** 12269 * Query whether or not this device is configured to allow connections to Wi-Fi WEP networks. 12270 * @see #setWepAllowed(boolean) 12271 * 12272 * Note: The WEP connections may not work even if this method returns {@code true} in the 12273 * result callback because device may NOT support connections to Wi-Fi WEP networks. 12274 * See: {@link #isWepSupported()}. 12275 * 12276 * @param executor The executor on which callback will be invoked. 12277 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 12278 * whether wep network support is enabled/disabled. 12279 * 12280 * @throws SecurityException if the caller does not have permission. 12281 * @hide 12282 */ 12283 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12284 @SystemApi 12285 @RequiresPermission(anyOf = { 12286 android.Manifest.permission.NETWORK_SETTINGS, 12287 android.Manifest.permission.NETWORK_SETUP_WIZARD 12288 }) queryWepAllowed(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)12289 public void queryWepAllowed(@NonNull @CallbackExecutor Executor executor, 12290 @NonNull Consumer<Boolean> resultsCallback) { 12291 Objects.requireNonNull(executor, "executor cannot be null"); 12292 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12293 try { 12294 mService.queryWepAllowed( 12295 new IBooleanListener.Stub() { 12296 @Override 12297 public void onResult(boolean value) { 12298 Binder.clearCallingIdentity(); 12299 executor.execute(() -> { 12300 resultsCallback.accept(value); 12301 }); 12302 } 12303 }); 12304 } catch (RemoteException e) { 12305 throw e.rethrowFromSystemServer(); 12306 } 12307 } 12308 12309 /** 12310 * Enable Mirrored Stream Classification Service (MSCS) and configure using 12311 * the provided configuration values. 12312 * 12313 * If MSCS has already been enabled/configured, this will override the 12314 * existing configuration. 12315 * 12316 * Refer to Section 11.25.3 of the IEEE 802.11-2020 standard for more information. 12317 * 12318 * @param mscsParams {@link MscsParams} object containing the configuration parameters. 12319 * @hide 12320 */ 12321 @SystemApi 12322 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12323 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12324 @RequiresPermission(anyOf = {MANAGE_WIFI_NETWORK_SELECTION}) enableMscs(@onNull MscsParams mscsParams)12325 public void enableMscs(@NonNull MscsParams mscsParams) { 12326 Objects.requireNonNull(mscsParams); 12327 try { 12328 mService.enableMscs(mscsParams); 12329 } catch (RemoteException e) { 12330 throw e.rethrowFromSystemServer(); 12331 } 12332 } 12333 12334 /** 12335 * Disable Mirrored Stream Classification Service (MSCS). 12336 * 12337 * If MSCS is enabled/configured, this will send a remove request to the AP. 12338 * 12339 * Refer to Section 11.25.3 of the IEEE 802.11-2020 standard for more information. 12340 * @hide 12341 */ 12342 @SystemApi 12343 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12344 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12345 @RequiresPermission(anyOf = {MANAGE_WIFI_NETWORK_SELECTION}) disableMscs()12346 public void disableMscs() { 12347 try { 12348 mService.disableMscs(); 12349 } catch (RemoteException e) { 12350 throw e.rethrowFromSystemServer(); 12351 } 12352 } 12353 12354 /** 12355 * Do not send the DHCP hostname to open networks. 12356 */ 12357 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12358 public static final int FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN = 1 << 0; 12359 12360 /** 12361 * Do not send the DHCP hostname to secure network. 12362 */ 12363 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12364 public static final int FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE = 1 << 1; 12365 12366 /** @hide */ 12367 @IntDef(flag = true, prefix = { "FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_" }, value = { 12368 FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN, 12369 FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE, 12370 }) 12371 @Retention(RetentionPolicy.SOURCE) 12372 public @interface SendDhcpHostnameRestriction {} 12373 12374 /** 12375 * Sets the global restrictions on which networks to send the device hostname to during DHCP. 12376 * 12377 * @param restriction Bitmask of {@link SendDhcpHostnameRestriction}, or none to indicate no 12378 * restriction. 12379 * @throws IllegalArgumentException if input is invalid 12380 * @throws SecurityException if the calling app is not a Device Owner (DO), or a privileged app 12381 * that has one of the permissions required by this API. 12382 */ 12383 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12384 @RequiresPermission(anyOf = { 12385 android.Manifest.permission.NETWORK_SETTINGS, 12386 android.Manifest.permission.NETWORK_SETUP_WIZARD 12387 }) setSendDhcpHostnameRestriction(@endDhcpHostnameRestriction int restriction)12388 public void setSendDhcpHostnameRestriction(@SendDhcpHostnameRestriction int restriction) { 12389 try { 12390 mService.setSendDhcpHostnameRestriction(mContext.getOpPackageName(), restriction); 12391 } catch (RemoteException e) { 12392 throw e.rethrowFromSystemServer(); 12393 } 12394 } 12395 12396 /** 12397 * Query the global restriction on which networks to send the device hostname to during DHCP. 12398 * @see #setSendDhcpHostnameRestriction(int) 12399 * 12400 * @param executor The executor on which callback will be invoked. 12401 * @param resultsCallback An asynchronous callback that will return a bitmask of 12402 * {@link SendDhcpHostnameRestriction}. 12403 * 12404 * @throws SecurityException if the calling app is not a Device Owner (DO), or a privileged app 12405 * that has one of the permissions required by this API. 12406 */ 12407 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12408 @RequiresPermission(anyOf = { 12409 android.Manifest.permission.NETWORK_SETTINGS, 12410 android.Manifest.permission.NETWORK_SETUP_WIZARD 12411 }) querySendDhcpHostnameRestriction(@onNull @allbackExecutor Executor executor, @NonNull IntConsumer resultsCallback)12412 public void querySendDhcpHostnameRestriction(@NonNull @CallbackExecutor Executor executor, 12413 @NonNull IntConsumer resultsCallback) { 12414 Objects.requireNonNull(executor, "executor cannot be null"); 12415 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12416 try { 12417 mService.querySendDhcpHostnameRestriction(mContext.getOpPackageName(), 12418 new IIntegerListener.Stub() { 12419 @Override 12420 public void onResult(int value) { 12421 Binder.clearCallingIdentity(); 12422 executor.execute(() -> { 12423 resultsCallback.accept(value); 12424 }); 12425 } 12426 }); 12427 } catch (RemoteException e) { 12428 throw e.rethrowFromSystemServer(); 12429 } 12430 } 12431 12432 /** 12433 * @return true if this device supports Aggressive roaming mode 12434 * {@link #setPerSsidRoamingMode(WifiSsid, int)} 12435 */ 12436 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) isAggressiveRoamingModeSupported()12437 public boolean isAggressiveRoamingModeSupported() { 12438 return isFeatureSupported(WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); 12439 } 12440 12441 /** 12442 * This API allows a privileged application to set roaming mode per SSID. 12443 * 12444 * Available for DO/COPE apps. 12445 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 12446 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 12447 * 12448 * @param ssid SSID to be mapped to apply roaming policy 12449 * @param roamingMode refer {@link RoamingMode} for supported modes. 12450 * @throws IllegalArgumentException if mode value is not in {@link RoamingMode}. 12451 * @throws NullPointerException if the caller provided a null input. 12452 * @throws SecurityException if caller does not have the required permission. 12453 * @throws UnsupportedOperationException if the set operation is not supported on this SDK or 12454 * if the feature is not available 12455 * {@link #isAggressiveRoamingModeSupported()}. 12456 */ 12457 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12458 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12459 @SuppressLint("RequiresPermission") setPerSsidRoamingMode(@onNull WifiSsid ssid, @RoamingMode int roamingMode)12460 public void setPerSsidRoamingMode(@NonNull WifiSsid ssid, @RoamingMode int roamingMode) { 12461 if (roamingMode < ROAMING_MODE_NONE || roamingMode > ROAMING_MODE_AGGRESSIVE) { 12462 throw new IllegalArgumentException("invalid roaming mode: " + roamingMode); 12463 } 12464 Objects.requireNonNull(ssid, "ssid cannot be null"); 12465 try { 12466 mService.setPerSsidRoamingMode(ssid, roamingMode, mContext.getOpPackageName()); 12467 } catch (RemoteException e) { 12468 throw e.rethrowFromSystemServer(); 12469 } 12470 } 12471 12472 /** 12473 * This API allows a privileged application to remove roaming mode policy 12474 * configured using the {@link #setPerSsidRoamingMode(WifiSsid, int)}. 12475 * 12476 * Available for DO/COPE apps. 12477 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 12478 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 12479 * 12480 * @param ssid SSID to be removed from the roaming mode policy. 12481 * @throws NullPointerException if the caller provided a null input. 12482 * @throws SecurityException if caller does not have the required permission. 12483 * @throws UnsupportedOperationException if the set operation is not supported on this SDK or 12484 * if the feature is not available 12485 * {@link #isAggressiveRoamingModeSupported()}. 12486 */ 12487 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12488 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12489 @SuppressLint("RequiresPermission") removePerSsidRoamingMode(@onNull WifiSsid ssid)12490 public void removePerSsidRoamingMode(@NonNull WifiSsid ssid) { 12491 Objects.requireNonNull(ssid, "ssid cannot be null"); 12492 try { 12493 mService.removePerSsidRoamingMode(ssid, mContext.getOpPackageName()); 12494 } catch (RemoteException e) { 12495 throw e.rethrowFromSystemServer(); 12496 } 12497 } 12498 12499 /** 12500 * This API allows a privileged application to get roaming mode policies 12501 * configured using the {@link #setPerSsidRoamingMode(WifiSsid, int)}. 12502 * 12503 * Available for DO/COPE apps. 12504 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 12505 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 12506 * 12507 * @param executor The executor on which callback will be invoked. 12508 * @param resultsCallback An asynchronous callback that will return the corresponding 12509 * roaming policies for the API caller. 12510 * @throws SecurityException if caller does not have the required permission. 12511 * @throws UnsupportedOperationException if the get operation is not supported on this SDK or 12512 * if the feature is not available 12513 * {@link #isAggressiveRoamingModeSupported()}. 12514 */ 12515 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12516 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12517 @SuppressLint("RequiresPermission") getPerSsidRoamingModes(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Map<String, Integer>> resultsCallback)12518 public void getPerSsidRoamingModes(@NonNull @CallbackExecutor Executor executor, 12519 @NonNull Consumer<Map<String, Integer>> resultsCallback) { 12520 Objects.requireNonNull(executor, "executor cannot be null"); 12521 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12522 try { 12523 mService.getPerSsidRoamingModes(mContext.getOpPackageName(), new IMapListener.Stub() { 12524 @Override 12525 public void onResult(Map roamingPolicies) { 12526 Binder.clearCallingIdentity(); 12527 executor.execute(() -> { 12528 resultsCallback.accept(roamingPolicies); 12529 }); 12530 } 12531 }); 12532 } catch (RemoteException e) { 12533 throw e.rethrowFromSystemServer(); 12534 } 12535 } 12536 12537 /** 12538 * Bundle key to check target wake time requester mode supported or not 12539 * @hide 12540 */ 12541 @SystemApi 12542 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12543 public static final String TWT_CAPABILITIES_KEY_BOOLEAN_TWT_REQUESTER = 12544 "key_requester"; 12545 12546 /** 12547 * Bundle key to get minimum wake duration supported in microseconds 12548 * @hide 12549 */ 12550 @SystemApi 12551 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12552 public static final String TWT_CAPABILITIES_KEY_INT_MIN_WAKE_DURATION_MICROS = 12553 "key_min_wake_duration"; 12554 /** 12555 * Bundle key to get maximum wake duration supported in microseconds 12556 * @hide 12557 */ 12558 @SystemApi 12559 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12560 public static final String TWT_CAPABILITIES_KEY_INT_MAX_WAKE_DURATION_MICROS = 12561 "key_max_wake_duration"; 12562 /** 12563 * Bundle key to get minimum wake interval supported in microseconds 12564 * @hide 12565 */ 12566 @SystemApi 12567 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12568 public static final String TWT_CAPABILITIES_KEY_LONG_MIN_WAKE_INTERVAL_MICROS = 12569 "key_min_wake_interval"; 12570 /** 12571 * Bundle key to get maximum wake interval supported in microseconds 12572 * @hide 12573 */ 12574 @SystemApi 12575 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12576 public static final String TWT_CAPABILITIES_KEY_LONG_MAX_WAKE_INTERVAL_MICROS = 12577 "key_max_wake_interval"; 12578 12579 /** @hide */ 12580 @StringDef(prefix = { "TWT_CAPABILITIES_KEY_"}, value = { 12581 TWT_CAPABILITIES_KEY_BOOLEAN_TWT_REQUESTER, 12582 TWT_CAPABILITIES_KEY_INT_MIN_WAKE_DURATION_MICROS, 12583 TWT_CAPABILITIES_KEY_INT_MAX_WAKE_DURATION_MICROS, 12584 TWT_CAPABILITIES_KEY_LONG_MIN_WAKE_INTERVAL_MICROS, 12585 TWT_CAPABILITIES_KEY_LONG_MAX_WAKE_INTERVAL_MICROS, 12586 }) 12587 @Retention(RetentionPolicy.SOURCE) 12588 public @interface TwtCapabilities {} 12589 12590 /** 12591 * Get target wake time (TWT) capabilities of the primary station interface. 12592 * 12593 * Note: Target wake time feature is only supported for primary station. If Wi-Fi is off or the 12594 * capability is not available the asynchronous callback will be called with the bundle 12595 * with values { false, -1, -1, -1, -1 }. 12596 * 12597 * @param executor Executor to execute listener callback 12598 * @param resultCallback An asynchronous callback that will return a bundle for target wake time 12599 * capabilities. See {@link TwtCapabilities} for the string keys for 12600 * the bundle. 12601 * @throws SecurityException if the caller does not have permission. 12602 * @throws NullPointerException if the caller provided null inputs. 12603 * @throws UnsupportedOperationException if the API is not supported. 12604 * @hide 12605 */ 12606 @SystemApi 12607 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12608 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) 12609 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) getTwtCapabilities(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Bundle> resultCallback)12610 public void getTwtCapabilities(@NonNull @CallbackExecutor Executor executor, 12611 @NonNull Consumer<Bundle> resultCallback) { 12612 Objects.requireNonNull(executor, "executor cannot be null"); 12613 Objects.requireNonNull(resultCallback, "resultCallback cannot be null"); 12614 if (!SdkLevel.isAtLeastV()) { 12615 throw new UnsupportedOperationException(); 12616 } 12617 try { 12618 Bundle extras = new Bundle(); 12619 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12620 mContext.getAttributionSource()); 12621 mService.getTwtCapabilities( 12622 new ITwtCapabilitiesListener.Stub() { 12623 @Override 12624 public void onResult(Bundle value) { 12625 Binder.clearCallingIdentity(); 12626 executor.execute(() -> { 12627 resultCallback.accept(value); 12628 }); 12629 } 12630 }, extras); 12631 } catch (RemoteException e) { 12632 throw e.rethrowFromSystemServer(); 12633 } 12634 } 12635 12636 private class TwtCallbackProxy extends ITwtCallback.Stub { 12637 private final Executor mExecutor; 12638 private final TwtSessionCallback mCallback; 12639 TwtCallbackProxy(Executor executor, TwtSessionCallback callback)12640 private TwtCallbackProxy(Executor executor, TwtSessionCallback callback) { 12641 mExecutor = executor; 12642 mCallback = callback; 12643 } 12644 12645 @Override onFailure(@wtSessionCallback.TwtErrorCode int errorCode)12646 public void onFailure(@TwtSessionCallback.TwtErrorCode int errorCode) 12647 throws RemoteException { 12648 if (mVerboseLoggingEnabled) { 12649 Log.v(TAG, "TwtCallbackProxy: onFailure(errorCode = " + errorCode + " )"); 12650 } 12651 Binder.clearCallingIdentity(); 12652 mExecutor.execute(() -> mCallback.onFailure(errorCode)); 12653 } 12654 12655 @Override onTeardown(@wtSessionCallback.TwtReasonCode int reasonCode)12656 public void onTeardown(@TwtSessionCallback.TwtReasonCode int reasonCode) 12657 throws RemoteException { 12658 if (mVerboseLoggingEnabled) { 12659 Log.v(TAG, "TwtCallbackProxy: onTeardown(errorCode = " + reasonCode + " )"); 12660 } 12661 Binder.clearCallingIdentity(); 12662 mExecutor.execute(() -> mCallback.onTeardown(reasonCode)); 12663 } 12664 12665 @Override onCreate(int wakeDuration, long wakeInterval, int mloLinkId, int owner, int sessionId)12666 public void onCreate(int wakeDuration, long wakeInterval, int mloLinkId, int owner, 12667 int sessionId) throws RemoteException { 12668 if (mVerboseLoggingEnabled) { 12669 Log.v(TAG, "TwtCallbackProxy: onCreate " + sessionId); 12670 } 12671 12672 WifiTwtSession wifiTwtSession = new WifiTwtSession(WifiManager.this, wakeDuration, 12673 wakeInterval, mloLinkId, owner, sessionId); 12674 Binder.clearCallingIdentity(); 12675 mExecutor.execute(() -> mCallback.onCreate(wifiTwtSession)); 12676 } 12677 } 12678 12679 /** 12680 * Set up a TWT session with a TWT responder capable AP. Only supported for primary connected 12681 * station which is a TWT requester. See {@link #getTwtCapabilities(Executor, Consumer)} and 12682 * {@link ScanResult#isTwtResponder()} to check station and AP support. 12683 * 12684 * Following callbacks are invoked, 12685 * - {@link TwtSessionCallback#onFailure(int)} upon error with error code. 12686 * - {@link TwtSessionCallback#onCreate(TwtSession)} upon TWT session creation. 12687 * - {@link TwtSessionCallback#onTeardown(int)} upon TWT session teardown. 12688 * 12689 * Note: {@link #getTwtCapabilities(Executor, Consumer)} gives {@link TwtCapabilities} which can 12690 * be used to fill in the valid TWT wake interval and duration ranges for {@link TwtRequest}. 12691 * 12692 * @param twtRequest TWT request 12693 * @param executor Executor to execute listener callback on 12694 * @param callback Callback to register 12695 * @throws SecurityException if the caller does not have permission. 12696 * @throws NullPointerException if the caller provided null inputs. 12697 * @throws UnsupportedOperationException if the API is not supported. 12698 * @hide 12699 */ 12700 @SystemApi 12701 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12702 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) 12703 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) setupTwtSession(@onNull TwtRequest twtRequest, @NonNull @CallbackExecutor Executor executor, @NonNull TwtSessionCallback callback)12704 public void setupTwtSession(@NonNull TwtRequest twtRequest, 12705 @NonNull @CallbackExecutor Executor executor, @NonNull TwtSessionCallback callback) { 12706 Objects.requireNonNull(executor, "executor cannot be null"); 12707 Objects.requireNonNull(callback, "callback cannot be null"); 12708 Objects.requireNonNull(twtRequest, "twtRequest cannot be null"); 12709 if (!SdkLevel.isAtLeastV()) { 12710 throw new UnsupportedOperationException(); 12711 } 12712 try { 12713 ITwtCallback.Stub binderCallback = new TwtCallbackProxy(executor, callback); 12714 Bundle extras = new Bundle(); 12715 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12716 mContext.getAttributionSource()); 12717 mService.setupTwtSession(twtRequest, binderCallback, extras); 12718 } catch (RemoteException e) { 12719 throw e.rethrowFromSystemServer(); 12720 } 12721 } 12722 12723 /** 12724 * Get stats of the target wake time session. 12725 * 12726 * Note: For Internal use only. Expected to be called through 12727 * {@link TwtSession#getStats(Executor, Consumer)}. If the command fails, -1 will be returned 12728 * for all stats values. 12729 * 12730 * @param sessionId TWT session id 12731 * @param executor The executor on which callback will be invoked. 12732 * @param resultCallback The asynchronous callback that will return bundle with key string 12733 * {@link TwtSession.TwtStats}. 12734 * 12735 * @throws SecurityException if the caller does not have permission. 12736 * @throws NullPointerException if the caller provided null inputs. 12737 * @throws UnsupportedOperationException if the API is not supported or primary station is 12738 * not connected. 12739 * @hide 12740 */ getStatsTwtSession(@onNull int sessionId, @NonNull Executor executor, @NonNull Consumer<Bundle> resultCallback)12741 public void getStatsTwtSession(@NonNull int sessionId, @NonNull Executor executor, 12742 @NonNull Consumer<Bundle> resultCallback) { 12743 Objects.requireNonNull(executor, "executor cannot be null"); 12744 Objects.requireNonNull(resultCallback, "resultsCallback cannot be null"); 12745 if (!SdkLevel.isAtLeastV()) { 12746 throw new UnsupportedOperationException(); 12747 } 12748 try { 12749 Bundle extras = new Bundle(); 12750 if (SdkLevel.isAtLeastS()) { 12751 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12752 mContext.getAttributionSource()); 12753 } 12754 mService.getStatsTwtSession(sessionId, 12755 new ITwtStatsListener.Stub() { 12756 @Override 12757 public void onResult(Bundle value) { 12758 Binder.clearCallingIdentity(); 12759 executor.execute(() -> { 12760 resultCallback.accept(value); 12761 }); 12762 } 12763 }, extras); 12764 } catch (RemoteException e) { 12765 throw e.rethrowFromSystemServer(); 12766 } 12767 } 12768 12769 /** 12770 * Teardown the target wake time session. Only owner can teardown the session. 12771 * 12772 * Note: For internal use only. Expected to be called through 12773 * {@link TwtSessionCallback#onTeardown(int)}. 12774 * 12775 * @param sessionId TWT session id 12776 * @throws SecurityException if the caller does not have permission. 12777 * @throws UnsupportedOperationException if the API is not supported or primary station is not 12778 * connected. 12779 * @hide 12780 */ teardownTwtSession(int sessionId)12781 public void teardownTwtSession(int sessionId) { 12782 if (!SdkLevel.isAtLeastV()) { 12783 throw new UnsupportedOperationException(); 12784 } 12785 try { 12786 Bundle extras = new Bundle(); 12787 if (SdkLevel.isAtLeastS()) { 12788 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12789 mContext.getAttributionSource()); 12790 } 12791 mService.teardownTwtSession(sessionId, extras); 12792 } catch (RemoteException e) { 12793 throw e.rethrowFromSystemServer(); 12794 } 12795 } 12796 12797 /** 12798 * Allows a privileged application to set whether or not this device allows 12799 * device-to-device connections when infra STA is disabled. Callers can use 12800 * {@link #queryD2dAllowedWhenInfraStaDisabled(Executor, Consumer)} to check the currently 12801 * set value. 12802 * 12803 * Note: This functionality is supported only when the device support device-to-device 12804 * when infra STA is disabled. Use {@link #isD2dSupportedWhenInfraStaDisabled()} to 12805 * know if device supported device-to-device when infra STA is disabled. 12806 * 12807 * @param isAllowed whether or not the device allows to device-to-device connectivity when 12808 * infra STA is disabled. 12809 * @throws SecurityException if the caller does not have permission. 12810 * @hide 12811 */ 12812 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12813 @SystemApi 12814 @RequiresPermission(anyOf = { 12815 android.Manifest.permission.NETWORK_SETTINGS, 12816 android.Manifest.permission.NETWORK_SETUP_WIZARD 12817 }) 12818 @RequiresApi(Build.VERSION_CODES.TIRAMISU) setD2dAllowedWhenInfraStaDisabled(boolean isAllowed)12819 public void setD2dAllowedWhenInfraStaDisabled(boolean isAllowed) { 12820 try { 12821 mService.setD2dAllowedWhenInfraStaDisabled(isAllowed); 12822 } catch (RemoteException e) { 12823 throw e.rethrowFromSystemServer(); 12824 } 12825 } 12826 12827 /** 12828 * Query whether or not this device is configured to allow D2d connection when 12829 * infra STA is disabled. 12830 * see: {@link #setD2dAllowedWhenInfraStaDisabled(boolean)}. 12831 * 12832 * 12833 * @param executor The executor on which callback will be invoked. 12834 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 12835 * whether device-to-device connection is allowed or disallowed 12836 * when infra STA is disabled. 12837 * @hide 12838 */ 12839 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12840 @SystemApi queryD2dAllowedWhenInfraStaDisabled(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)12841 public void queryD2dAllowedWhenInfraStaDisabled(@NonNull @CallbackExecutor Executor executor, 12842 @NonNull Consumer<Boolean> resultsCallback) { 12843 Objects.requireNonNull(executor, "executor cannot be null"); 12844 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12845 try { 12846 mService.queryD2dAllowedWhenInfraStaDisabled( 12847 new IBooleanListener.Stub() { 12848 @Override 12849 public void onResult(boolean value) { 12850 Binder.clearCallingIdentity(); 12851 executor.execute(() -> { 12852 resultsCallback.accept(value); 12853 }); 12854 } 12855 }); 12856 } catch (RemoteException e) { 12857 throw e.rethrowFromSystemServer(); 12858 } 12859 } 12860 } 12861