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.content.pm.PackageManager; 50 import android.net.ConnectivityManager; 51 import android.net.ConnectivityManager.NetworkCallback; 52 import android.net.DhcpInfo; 53 import android.net.DhcpOption; 54 import android.net.LinkProperties; 55 import android.net.MacAddress; 56 import android.net.Network; 57 import android.net.NetworkCapabilities; 58 import android.net.NetworkRequest; 59 import android.net.NetworkStack; 60 import android.net.TetheringManager; 61 import android.net.Uri; 62 import android.net.wifi.hotspot2.IProvisioningCallback; 63 import android.net.wifi.hotspot2.OsuProvider; 64 import android.net.wifi.hotspot2.PasspointConfiguration; 65 import android.net.wifi.hotspot2.ProvisioningCallback; 66 import android.net.wifi.p2p.WifiP2pConfig; 67 import android.net.wifi.p2p.WifiP2pDiscoveryConfig; 68 import android.net.wifi.p2p.WifiP2pManager; 69 import android.net.wifi.twt.TwtRequest; 70 import android.net.wifi.twt.TwtSession; 71 import android.net.wifi.twt.TwtSessionCallback; 72 import android.net.wifi.util.Environment; 73 import android.os.Binder; 74 import android.os.Build; 75 import android.os.Bundle; 76 import android.os.Handler; 77 import android.os.IBinder; 78 import android.os.Looper; 79 import android.os.Parcel; 80 import android.os.Parcelable; 81 import android.os.RemoteException; 82 import android.os.WorkSource; 83 import android.os.connectivity.WifiActivityEnergyInfo; 84 import android.security.advancedprotection.AdvancedProtectionFeature; 85 import android.security.advancedprotection.AdvancedProtectionManager; 86 import android.telephony.SubscriptionInfo; 87 import android.text.TextUtils; 88 import android.util.ArraySet; 89 import android.util.CloseGuard; 90 import android.util.Log; 91 import android.util.Pair; 92 import android.util.SparseArray; 93 94 import androidx.annotation.RequiresApi; 95 96 import com.android.internal.annotations.GuardedBy; 97 import com.android.internal.annotations.VisibleForTesting; 98 import com.android.modules.utils.HandlerExecutor; 99 import com.android.modules.utils.ParceledListSlice; 100 import com.android.modules.utils.StringParceledListSlice; 101 import com.android.modules.utils.build.SdkLevel; 102 import com.android.wifi.flags.Flags; 103 104 import java.lang.annotation.Retention; 105 import java.lang.annotation.RetentionPolicy; 106 import java.lang.ref.Reference; 107 import java.lang.ref.WeakReference; 108 import java.net.InetAddress; 109 import java.time.Duration; 110 import java.util.ArrayList; 111 import java.util.Arrays; 112 import java.util.Collections; 113 import java.util.HashMap; 114 import java.util.List; 115 import java.util.Map; 116 import java.util.Objects; 117 import java.util.Set; 118 import java.util.StringTokenizer; 119 import java.util.concurrent.Executor; 120 import java.util.function.BiConsumer; 121 import java.util.function.Consumer; 122 import java.util.function.IntConsumer; 123 124 /** 125 * This class provides the primary API for managing all aspects of Wi-Fi 126 * connectivity. 127 * <p> 128 * On releases before {@link android.os.Build.VERSION_CODES#N}, this object 129 * should only be obtained from an {@linkplain Context#getApplicationContext() 130 * application context}, and not from any other derived context to avoid memory 131 * leaks within the calling process. 132 * <p> 133 * It deals with several categories of items: 134 * </p> 135 * <ul> 136 * <li>The list of configured networks. The list can be viewed and updated, and 137 * attributes of individual entries can be modified.</li> 138 * <li>The currently active Wi-Fi network, if any. Connectivity can be 139 * established or torn down, and dynamic information about the state of the 140 * network can be queried.</li> 141 * <li>Results of access point scans, containing enough information to make 142 * decisions about what access point to connect to.</li> 143 * <li>It defines the names of various Intent actions that are broadcast upon 144 * any sort of change in Wi-Fi state. 145 * </ul> 146 * <p> 147 * This is the API to use when performing Wi-Fi specific operations. To perform 148 * operations that pertain to network connectivity at an abstract level, use 149 * {@link android.net.ConnectivityManager}. 150 * </p> 151 */ 152 @SystemService(Context.WIFI_SERVICE) 153 public class WifiManager { 154 155 private static final String TAG = "WifiManager"; 156 157 /** 158 * Local networks should not be modified by B&R since the user may have 159 * updated it with the latest configurations. 160 * @hide 161 */ 162 @ChangeId 163 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2) 164 public static final long NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE = 234793325L; 165 166 // Supplicant error codes: 167 /** 168 * The error code if there was a problem authenticating. 169 * @deprecated This is no longer supported. 170 */ 171 @Deprecated 172 public static final int ERROR_AUTHENTICATING = 1; 173 174 /** 175 * The reason code if there is no error during authentication. 176 * It could also imply that there no authentication in progress, 177 * this reason code also serves as a reset value. 178 * @deprecated This is no longer supported. 179 * @hide 180 */ 181 @Deprecated 182 public static final int ERROR_AUTH_FAILURE_NONE = 0; 183 184 /** 185 * The reason code if there was a timeout authenticating. 186 * @deprecated This is no longer supported. 187 * @hide 188 */ 189 @Deprecated 190 public static final int ERROR_AUTH_FAILURE_TIMEOUT = 1; 191 192 /** 193 * The reason code if there was a wrong password while 194 * authenticating. 195 * @deprecated This is no longer supported. 196 * @hide 197 */ 198 @Deprecated 199 public static final int ERROR_AUTH_FAILURE_WRONG_PSWD = 2; 200 201 /** 202 * The reason code if there was EAP failure while 203 * authenticating. 204 * @deprecated This is no longer supported. 205 * @hide 206 */ 207 @Deprecated 208 public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3; 209 210 /** @hide */ 211 public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM = 256; 212 213 /** @hide */ 214 public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM = 1024; 215 216 /** 217 * Reason code if all of the network suggestions were successfully added or removed. 218 */ 219 public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; 220 221 /** 222 * Reason code if there was an internal error in the platform while processing the addition or 223 * removal of suggestions. 224 */ 225 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1; 226 227 /** 228 * Reason code if the user has disallowed "android:change_wifi_state" app-ops from the app. 229 * @see android.app.AppOpsManager#unsafeCheckOp(String, int, String). 230 */ 231 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED = 2; 232 233 /** 234 * Reason code if one or more of the network suggestions added already exists in platform's 235 * database. 236 * Note: this code will not be returned with Android 11 as in-place modification is allowed, 237 * please check {@link #addNetworkSuggestions(List)}. 238 * @see WifiNetworkSuggestion#equals(Object) 239 */ 240 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 3; 241 242 /** 243 * Reason code if the number of network suggestions provided by the app crosses the max 244 * threshold set per app. 245 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} if 246 * the total size exceeds the limit. 247 * @see #getMaxNumberOfNetworkSuggestionsPerApp() 248 */ 249 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 4; 250 251 /** 252 * Reason code if one or more of the network suggestions removed does not exist in platform's 253 * database. 254 * The framework won't remove any suggestions if one or more of suggestions provided 255 * by {@link #removeNetworkSuggestions(List)} does not exist in database. 256 * @see WifiNetworkSuggestion#equals(Object) 257 */ 258 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5; 259 260 /** 261 * Reason code if one or more of the network suggestions added is not allowed. 262 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} 263 * if one or more of them is not allowed. 264 * This error may be caused by suggestion is using SIM-based encryption method, but calling app 265 * is not carrier privileged. 266 */ 267 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED = 6; 268 269 /** 270 * Reason code if one or more of the network suggestions added is invalid. Framework will reject 271 * all the suggestions in the list. 272 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} 273 * if one or more of them is invalid. 274 * Please use {@link WifiNetworkSuggestion.Builder} to create network suggestions. 275 */ 276 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID = 7; 277 278 /** 279 * Reason code if {@link android.os.UserManager#DISALLOW_ADD_WIFI_CONFIG} user restriction 280 * is set and calling app is restricted by device admin. 281 */ 282 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN = 8; 283 284 /** @hide */ 285 @IntDef(prefix = { "STATUS_NETWORK_SUGGESTIONS_" }, value = { 286 STATUS_NETWORK_SUGGESTIONS_SUCCESS, 287 STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, 288 STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED, 289 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE, 290 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP, 291 STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, 292 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED, 293 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, 294 STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN, 295 }) 296 @Retention(RetentionPolicy.SOURCE) 297 public @interface NetworkSuggestionsStatusCode {} 298 299 /** 300 * Reason code if suggested network connection attempt failed with an unknown failure. 301 */ 302 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN = 0; 303 /** 304 * Reason code if suggested network connection attempt failed with association failure. 305 */ 306 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION = 1; 307 /** 308 * Reason code if suggested network connection attempt failed with an authentication failure. 309 */ 310 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION = 2; 311 /** 312 * Reason code if suggested network connection attempt failed with an IP provision failure. 313 */ 314 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING = 3; 315 316 /** @hide */ 317 @IntDef(prefix = {"STATUS_SUGGESTION_CONNECTION_FAILURE_"}, 318 value = {STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN, 319 STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION, 320 STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION, 321 STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING 322 }) 323 @Retention(RetentionPolicy.SOURCE) 324 public @interface SuggestionConnectionStatusCode {} 325 326 /** 327 * Reason code if local-only network connection attempt failed with an unknown failure. 328 */ 329 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_UNKNOWN = 0; 330 /** 331 * Reason code if local-only network connection attempt failed with association failure. 332 */ 333 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_ASSOCIATION = 1; 334 /** 335 * Reason code if local-only network connection attempt failed with an authentication failure. 336 */ 337 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION = 2; 338 /** 339 * Reason code if local-only network connection attempt failed with an IP provisioning failure. 340 */ 341 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING = 3; 342 /** 343 * Reason code if local-only network connection attempt failed with AP not in range. 344 */ 345 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND = 4; 346 /** 347 * Reason code if local-only network connection attempt failed with AP not responding. 348 */ 349 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE = 5; 350 /** 351 * Reason code if local-only network request rejected by the user. 352 */ 353 @FlaggedApi(Flags.FLAG_LOCAL_ONLY_CONNECTION_OPTIMIZATION) 354 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_USER_REJECT = 6; 355 356 /** @hide */ 357 @IntDef(prefix = {"STATUS_LOCAL_ONLY_CONNECTION_FAILURE_"}, 358 value = {STATUS_LOCAL_ONLY_CONNECTION_FAILURE_UNKNOWN, 359 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_ASSOCIATION, 360 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION, 361 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING, 362 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND, 363 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE, 364 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_USER_REJECT 365 }) 366 @Retention(RetentionPolicy.SOURCE) 367 public @interface LocalOnlyConnectionStatusCode {} 368 369 /** 370 * Status code if suggestion approval status is unknown, an App which hasn't made any 371 * suggestions will get this code. 372 */ 373 public static final int STATUS_SUGGESTION_APPROVAL_UNKNOWN = 0; 374 375 /** 376 * Status code if the calling app is still pending user approval for suggestions. 377 */ 378 public static final int STATUS_SUGGESTION_APPROVAL_PENDING = 1; 379 380 /** 381 * Status code if the calling app got the user approval for suggestions. 382 */ 383 public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER = 2; 384 385 /** 386 * Status code if the calling app suggestions were rejected by the user. 387 */ 388 public static final int STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER = 3; 389 390 /** 391 * Status code if the calling app was approved by virtue of being a carrier privileged app. 392 * 393 * @see android.telephony.TelephonyManager#hasCarrierPrivileges() 394 */ 395 public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE = 4; 396 397 /** @hide */ 398 @IntDef(prefix = {"STATUS_SUGGESTION_APPROVAL_"}, 399 value = {STATUS_SUGGESTION_APPROVAL_UNKNOWN, 400 STATUS_SUGGESTION_APPROVAL_PENDING, 401 STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER, 402 STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER, 403 STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE 404 }) 405 @Retention(RetentionPolicy.SOURCE) 406 public @interface SuggestionUserApprovalStatus {} 407 408 /** 409 * Disable PNO scan until device reboot. 410 * @hide 411 */ 412 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 413 @SystemApi 414 public static final int PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT = 0; 415 416 /** 417 * Disable PNO scan until device reboot or Wi-Fi is toggled. 418 * @hide 419 */ 420 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 421 @SystemApi 422 public static final int PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE = 1; 423 424 /** 425 * Enable PNO scan. 426 * @hide 427 */ 428 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 429 @SystemApi 430 public static final int PNO_SCAN_STATE_ENABLED = 2; 431 432 /** @hide */ 433 @IntDef(prefix = {"PNO_SCAN_STATE_"}, 434 value = {PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT, 435 PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE, 436 PNO_SCAN_STATE_ENABLED 437 }) 438 @Retention(RetentionPolicy.SOURCE) 439 public @interface PnoScanState {} 440 441 /** 442 * If one of the removed suggestions is currently connected, that network will be disconnected 443 * after a short delay as opposed to immediately (which will be done by 444 * {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT}). The {@link ConnectivityManager} may call the 445 * {@link NetworkCallback#onLosing(Network, int)} on such networks. 446 */ 447 public static final int ACTION_REMOVE_SUGGESTION_LINGER = 1; 448 449 /** 450 * If one of the removed suggestions is currently connected, trigger an immediate disconnect 451 * after suggestions removal 452 */ 453 public static final int ACTION_REMOVE_SUGGESTION_DISCONNECT = 2; 454 455 /** @hide */ 456 @IntDef(prefix = {"ACTION_REMOVE_SUGGESTION_"}, 457 value = {ACTION_REMOVE_SUGGESTION_LINGER, 458 ACTION_REMOVE_SUGGESTION_DISCONNECT 459 }) 460 @Retention(RetentionPolicy.SOURCE) 461 public @interface ActionAfterRemovingSuggestion {} 462 463 /** 464 * Only available on Android S or later. 465 * @hide 466 **/ 467 public static final String EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE = 468 "EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE"; 469 470 /** 471 * Broadcast intent action indicating whether Wi-Fi scanning is currently available. 472 * Available extras: 473 * - {@link #EXTRA_SCAN_AVAILABLE} 474 */ 475 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 476 public static final String ACTION_WIFI_SCAN_AVAILABILITY_CHANGED = 477 "android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED"; 478 479 /** 480 * A boolean extra indicating whether scanning is currently available. 481 * Sent in the broadcast {@link #ACTION_WIFI_SCAN_AVAILABILITY_CHANGED}. 482 * Its value is true if scanning is currently available, false otherwise. 483 */ 484 public static final String EXTRA_SCAN_AVAILABLE = "android.net.wifi.extra.SCAN_AVAILABLE"; 485 486 /** 487 * Broadcast intent action indicating that the credential of a Wi-Fi network 488 * has been changed. One extra provides the ssid of the network. Another 489 * extra provides the event type, whether the credential is saved or forgot. 490 * @hide 491 */ 492 @SystemApi 493 public static final String WIFI_CREDENTIAL_CHANGED_ACTION = 494 "android.net.wifi.WIFI_CREDENTIAL_CHANGED"; 495 /** @hide */ 496 @SystemApi 497 public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et"; 498 /** @hide */ 499 @SystemApi 500 public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid"; 501 /** @hide */ 502 @SystemApi 503 public static final int WIFI_CREDENTIAL_SAVED = 0; 504 /** @hide */ 505 @SystemApi 506 public static final int WIFI_CREDENTIAL_FORGOT = 1; 507 508 /** @hide */ 509 @SystemApi 510 public static final int PASSPOINT_HOME_NETWORK = 0; 511 512 /** @hide */ 513 @SystemApi 514 public static final int PASSPOINT_ROAMING_NETWORK = 1; 515 516 /** @hide */ 517 @Retention(RetentionPolicy.SOURCE) 518 @IntDef(value = { 519 API_SCANNING_ENABLED, 520 API_WIFI_ENABLED, 521 API_SOFT_AP, 522 API_TETHERED_HOTSPOT, 523 API_AUTOJOIN_GLOBAL, 524 API_SET_SCAN_SCHEDULE, 525 API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY, 526 API_SET_NETWORK_SELECTION_CONFIG, 527 API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG, 528 API_ADD_NETWORK, 529 API_UPDATE_NETWORK, 530 API_ALLOW_AUTOJOIN, 531 API_CONNECT_CONFIG, 532 API_CONNECT_NETWORK_ID, 533 API_DISABLE_NETWORK, 534 API_ENABLE_NETWORK, 535 API_FORGET, 536 API_SAVE, 537 API_START_SCAN, 538 API_START_LOCAL_ONLY_HOTSPOT, 539 API_P2P_DISCOVER_PEERS, 540 API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS, 541 API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY, 542 API_P2P_STOP_PEER_DISCOVERY, 543 API_P2P_CONNECT, 544 API_P2P_CANCEL_CONNECT, 545 API_P2P_CREATE_GROUP, 546 API_P2P_CREATE_GROUP_P2P_CONFIG, 547 API_P2P_REMOVE_GROUP, 548 API_P2P_START_LISTENING, 549 API_P2P_STOP_LISTENING, 550 API_P2P_SET_CHANNELS, 551 API_WIFI_SCANNER_START_SCAN, 552 API_SET_TDLS_ENABLED, 553 API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS, 554 API_P2P_DISCOVER_PEERS_WITH_CONFIG_PARAMS 555 }) 556 public @interface ApiType {} 557 558 /** 559 * A constant used in 560 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 561 * Tracks usage of {@link WifiScanner#setScanningEnabled(boolean)} 562 * @hide 563 */ 564 @SystemApi 565 public static final int API_SCANNING_ENABLED = 1; 566 /** 567 * A constant used in 568 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 569 * Tracks usage of {@link WifiManager#setWifiEnabled(boolean)} . 570 * @hide 571 */ 572 @SystemApi 573 public static final int API_WIFI_ENABLED = 2; 574 /** 575 * A constant used in 576 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 577 * Tracks usage of {@link WifiManager#startSoftAp(WifiConfiguration)} and 578 * {@link WifiManager#stopSoftAp()}. 579 * @hide 580 */ 581 @SystemApi 582 public static final int API_SOFT_AP = 3; 583 /** 584 * A constant used in 585 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 586 * Tracks usage of {@link WifiManager#startTetheredHotspot(SoftApConfiguration)}. 587 * @hide 588 */ 589 @SystemApi 590 public static final int API_TETHERED_HOTSPOT = 4; 591 /** 592 * A constant used in 593 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 594 * Tracks usage of {@link WifiManager#allowAutojoinGlobal(boolean)}. 595 * @hide 596 */ 597 @SystemApi 598 public static final int API_AUTOJOIN_GLOBAL = 5; 599 /** 600 * A constant used in 601 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 602 * Tracks usage of {@link WifiManager#setScreenOnScanSchedule(List)}. 603 * @hide 604 */ 605 @SystemApi 606 public static final int API_SET_SCAN_SCHEDULE = 6; 607 608 /** 609 * A constant used in 610 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 611 * Tracks usage of {@link WifiManager#setOneShotScreenOnConnectivityScanDelayMillis(int)}. 612 * @hide 613 */ 614 @SystemApi 615 public static final int API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY = 7; 616 617 /** 618 * A constant used in 619 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 620 * Tracks usage of 621 * {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)} 622 * @hide 623 */ 624 @SystemApi 625 public static final int API_SET_NETWORK_SELECTION_CONFIG = 8; 626 627 /** 628 * A constant used in 629 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 630 * Tracks usage of 631 * {@link WifiManager#setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} 632 * @hide 633 */ 634 @SystemApi 635 public static final int API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG = 9; 636 637 /** 638 * A constant used in 639 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 640 * Tracks usage of 641 * {@link WifiManager#addNetwork(WifiConfiguration)} 642 * @hide 643 */ 644 @SystemApi 645 public static final int API_ADD_NETWORK = 10; 646 647 /** 648 * A constant used in 649 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 650 * Tracks usage of 651 * {@link WifiManager#updateNetwork(WifiConfiguration)} 652 * @hide 653 */ 654 @SystemApi 655 public static final int API_UPDATE_NETWORK = 11; 656 657 /** 658 * A constant used in 659 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 660 * Tracks usage of 661 * {@link WifiManager#allowAutojoin(int, boolean)} 662 * @hide 663 */ 664 @SystemApi 665 public static final int API_ALLOW_AUTOJOIN = 12; 666 667 /** 668 * A constant used in 669 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 670 * Tracks usage of 671 * {@link WifiManager#connect(WifiConfiguration, ActionListener)} 672 * @hide 673 */ 674 @SystemApi 675 public static final int API_CONNECT_CONFIG = 13; 676 677 /** 678 * A constant used in 679 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 680 * Tracks usage of 681 * {@link WifiManager#connect(int, ActionListener)} 682 * @hide 683 */ 684 @SystemApi 685 public static final int API_CONNECT_NETWORK_ID = 14; 686 687 /** 688 * A constant used in 689 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 690 * Tracks usage of 691 * {@link WifiManager#disableNetwork(int)} 692 * @hide 693 */ 694 @SystemApi 695 public static final int API_DISABLE_NETWORK = 15; 696 697 /** 698 * A constant used in 699 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 700 * Tracks usage of 701 * {@link WifiManager#enableNetwork(int, boolean)} 702 * @hide 703 */ 704 @SystemApi 705 public static final int API_ENABLE_NETWORK = 16; 706 707 /** 708 * A constant used in 709 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 710 * Tracks usage of 711 * {@link WifiManager#forget(int, ActionListener)} 712 * @hide 713 */ 714 @SystemApi 715 public static final int API_FORGET = 17; 716 717 /** 718 * A constant used in 719 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 720 * Tracks usage of 721 * {@link WifiManager#save(WifiConfiguration, ActionListener)} 722 * @hide 723 */ 724 @SystemApi 725 public static final int API_SAVE = 18; 726 727 /** 728 * A constant used in 729 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 730 * Tracks usage of 731 * {@link WifiManager#startScan()} 732 * @hide 733 */ 734 @SystemApi 735 public static final int API_START_SCAN = 19; 736 737 /** 738 * A constant used in 739 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 740 * Tracks usage of 741 * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} 742 * @hide 743 */ 744 @SystemApi 745 public static final int API_START_LOCAL_ONLY_HOTSPOT = 20; 746 747 /** 748 * A constant used in 749 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 750 * Tracks usage of 751 * {@link WifiP2pManager#discoverPeers(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 752 * @hide 753 */ 754 @SystemApi 755 public static final int API_P2P_DISCOVER_PEERS = 21; 756 757 /** 758 * A constant used in 759 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 760 * Tracks usage of 761 * {@link WifiP2pManager#discoverPeersOnSocialChannels(WifiP2pManager.Channel, 762 * WifiP2pManager.ActionListener)} 763 * @hide 764 */ 765 @SystemApi 766 public static final int API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS = 22; 767 768 /** 769 * A constant used in 770 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 771 * Tracks usage of 772 * {@link WifiP2pManager#discoverPeersOnSpecificFrequency(WifiP2pManager.Channel, int, 773 * WifiP2pManager.ActionListener)} 774 * @hide 775 */ 776 @SystemApi 777 public static final int API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY = 23; 778 779 /** 780 * A constant used in 781 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 782 * Tracks usage of 783 * {@link WifiP2pManager#stopPeerDiscovery(WifiP2pManager.Channel, 784 * WifiP2pManager.ActionListener)} 785 * @hide 786 */ 787 @SystemApi 788 public static final int API_P2P_STOP_PEER_DISCOVERY = 24; 789 790 /** 791 * A constant used in 792 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 793 * Tracks usage of 794 * {@link WifiP2pManager#connect(WifiP2pManager.Channel, WifiP2pConfig, 795 * WifiP2pManager.ActionListener)} 796 * @hide 797 */ 798 @SystemApi 799 public static final int API_P2P_CONNECT = 25; 800 801 /** 802 * A constant used in 803 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 804 * Tracks usage of 805 * {@link WifiP2pManager#cancelConnect(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 806 * @hide 807 */ 808 @SystemApi 809 public static final int API_P2P_CANCEL_CONNECT = 26; 810 811 /** 812 * A constant used in 813 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 814 * Tracks usage of 815 * {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 816 * @hide 817 */ 818 @SystemApi 819 public static final int API_P2P_CREATE_GROUP = 27; 820 821 /** 822 * A constant used in 823 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 824 * Tracks usage of 825 * {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pConfig, 826 * WifiP2pManager.ActionListener)} 827 * @hide 828 */ 829 @SystemApi 830 public static final int API_P2P_CREATE_GROUP_P2P_CONFIG = 28; 831 832 /** 833 * A constant used in 834 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 835 * Tracks usage of 836 * {@link WifiP2pManager#removeGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 837 * @hide 838 */ 839 @SystemApi 840 public static final int API_P2P_REMOVE_GROUP = 29; 841 842 /** 843 * A constant used in 844 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 845 * Tracks usage of 846 * {@link WifiP2pManager#startListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 847 * @hide 848 */ 849 @SystemApi 850 public static final int API_P2P_START_LISTENING = 30; 851 852 /** 853 * A constant used in 854 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 855 * Tracks usage of 856 * {@link WifiP2pManager#stopListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 857 * @hide 858 */ 859 @SystemApi 860 public static final int API_P2P_STOP_LISTENING = 31; 861 862 /** 863 * A constant used in 864 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 865 * Tracks usage of 866 * {@link WifiP2pManager#setWifiP2pChannels(WifiP2pManager.Channel, int, int, 867 * WifiP2pManager.ActionListener)} 868 * @hide 869 */ 870 @SystemApi 871 public static final int API_P2P_SET_CHANNELS = 32; 872 873 /** 874 * A constant used in 875 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 876 * Tracks usage of 877 * {@link WifiScanner#startScan(WifiScanner.ScanSettings, WifiScanner.ScanListener)} 878 * @hide 879 */ 880 @SystemApi 881 public static final int API_WIFI_SCANNER_START_SCAN = 33; 882 883 /** 884 * A constant used in 885 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 886 * Tracks usage of 887 * {@link WifiManager#setTdlsEnabled(InetAddress, boolean)} and 888 * {@link WifiManager#setTdlsEnabled(InetAddress, boolean, Executor, Consumer)} 889 * @hide 890 */ 891 @SystemApi 892 public static final int API_SET_TDLS_ENABLED = 34; 893 894 /** 895 * A constant used in 896 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 897 * Tracks usage of 898 * {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean)} and 899 * {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)} 900 * @hide 901 */ 902 @SystemApi 903 public static final int API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS = 35; 904 905 /** 906 * A constant used in {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 907 * Tracks usage of {@link WifiManager#setPnoScanState(int)} 908 * 909 * @hide 910 */ 911 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 912 @SystemApi 913 public static final int API_SET_PNO_SCAN_ENABLED = 36; 914 915 /** 916 * A constant used in {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 917 * Tracks usage of {@link WifiP2pManager#discoverPeersWithConfigParams( 918 * WifiP2pManager.Channel, WifiP2pDiscoveryConfig, WifiP2pManager.ActionListener)} 919 * 920 * @hide 921 */ 922 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 923 @SystemApi 924 public static final int API_P2P_DISCOVER_PEERS_WITH_CONFIG_PARAMS = 37; 925 926 /** 927 * Used internally to keep track of boundary. 928 * @hide 929 */ 930 public static final int API_MAX = 38; 931 932 /** 933 * Broadcast intent action indicating that a Passpoint provider icon has been received. 934 * 935 * Included extras: 936 * {@link #EXTRA_BSSID_LONG} 937 * {@link #EXTRA_FILENAME} 938 * {@link #EXTRA_ICON} 939 * 940 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 941 * 942 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 943 * components will be launched. 944 * 945 * @hide 946 */ 947 public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; 948 /** 949 * BSSID of an AP in long representation. The {@link #EXTRA_BSSID} contains BSSID in 950 * String representation. 951 * 952 * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}. 953 * 954 * @hide 955 */ 956 public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; 957 /** 958 * Icon data. 959 * 960 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into 961 * {@link android.graphics.drawable.Icon}. 962 * 963 * @hide 964 */ 965 public static final String EXTRA_ICON = "android.net.wifi.extra.ICON"; 966 /** 967 * Name of a file. 968 * 969 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 970 * 971 * @hide 972 */ 973 public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; 974 975 /** 976 * Broadcast intent action indicating a Passpoint OSU Providers List element has been received. 977 * 978 * Included extras: 979 * {@link #EXTRA_BSSID_LONG} 980 * {@link #EXTRA_ANQP_ELEMENT_DATA} 981 * 982 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 983 * 984 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 985 * components will be launched. 986 * 987 * @hide 988 */ 989 public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = 990 "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; 991 /** 992 * Raw binary data of an ANQP (Access Network Query Protocol) element. 993 * 994 * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}. 995 * 996 * @hide 997 */ 998 public static final String EXTRA_ANQP_ELEMENT_DATA = 999 "android.net.wifi.extra.ANQP_ELEMENT_DATA"; 1000 1001 /** 1002 * Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received. 1003 * 1004 * Included extras: 1005 * {@link #EXTRA_BSSID_LONG} 1006 * {@link #EXTRA_ESS} 1007 * {@link #EXTRA_DELAY} 1008 * {@link #EXTRA_URL} 1009 * 1010 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 1011 * 1012 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 1013 * components will be launched. 1014 * 1015 * @hide 1016 */ 1017 public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT = 1018 "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; 1019 /** 1020 * Flag indicating BSS (Basic Service Set) or ESS (Extended Service Set). This will be set to 1021 * {@code true} for ESS. 1022 * 1023 * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}. 1024 * 1025 * @hide 1026 */ 1027 public static final String EXTRA_ESS = "android.net.wifi.extra.ESS"; 1028 /** 1029 * Delay in seconds. 1030 * 1031 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 1032 * 1033 * @hide 1034 */ 1035 public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; 1036 1037 /** 1038 * Broadcast intent action indicating a Passpoint subscription remediation frame has been 1039 * received. 1040 * 1041 * Included extras: 1042 * {@link #EXTRA_BSSID_LONG} 1043 * {@link #EXTRA_SUBSCRIPTION_REMEDIATION_METHOD} 1044 * {@link #EXTRA_URL} 1045 * 1046 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 1047 * 1048 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 1049 * components will be launched. 1050 * 1051 * @hide 1052 */ 1053 public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = 1054 "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; 1055 /** 1056 * The protocol supported by the subscription remediation server. The possible values are: 1057 * 0 - OMA DM 1058 * 1 - SOAP XML SPP 1059 * 1060 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 1061 * 1062 * @hide 1063 */ 1064 public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = 1065 "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; 1066 1067 /** 1068 * Activity Action: Receiver should launch Passpoint OSU (Online Sign Up) view. 1069 * Included extras: 1070 * 1071 * {@link #EXTRA_OSU_NETWORK}: {@link Network} instance associated with OSU AP. 1072 * {@link #EXTRA_URL}: String representation of a server URL used for OSU process. 1073 * 1074 * @hide 1075 */ 1076 @SystemApi 1077 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1078 public static final String ACTION_PASSPOINT_LAUNCH_OSU_VIEW = 1079 "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW"; 1080 1081 /** 1082 * The lookup key for a {@link android.net.Network} associated with a Passpoint OSU server. 1083 * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast. 1084 * 1085 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 1086 * 1087 * @hide 1088 */ 1089 @SystemApi 1090 public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK"; 1091 1092 /** 1093 * String representation of an URL for Passpoint OSU. 1094 * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast. 1095 * 1096 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 1097 * 1098 * @hide 1099 */ 1100 @SystemApi 1101 public static final String EXTRA_URL = "android.net.wifi.extra.URL"; 1102 1103 /** 1104 * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, 1105 * enabling, disabling, or unknown. One extra provides this state as an int. 1106 * Another extra provides the previous state, if available. No network-related 1107 * permissions are required to subscribe to this broadcast. 1108 * 1109 * <p class="note">This broadcast is not delivered to manifest receivers in 1110 * applications that target API version 26 or later. 1111 * 1112 * @see #EXTRA_WIFI_STATE 1113 * @see #EXTRA_PREVIOUS_WIFI_STATE 1114 */ 1115 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1116 public static final String WIFI_STATE_CHANGED_ACTION = 1117 "android.net.wifi.WIFI_STATE_CHANGED"; 1118 /** 1119 * The lookup key for an int that indicates whether Wi-Fi is enabled, 1120 * disabled, enabling, disabling, or unknown. Retrieve it with 1121 * {@link android.content.Intent#getIntExtra(String,int)}. 1122 * 1123 * @see #WIFI_STATE_DISABLED 1124 * @see #WIFI_STATE_DISABLING 1125 * @see #WIFI_STATE_ENABLED 1126 * @see #WIFI_STATE_ENABLING 1127 * @see #WIFI_STATE_UNKNOWN 1128 */ 1129 public static final String EXTRA_WIFI_STATE = "wifi_state"; 1130 /** 1131 * The previous Wi-Fi state. 1132 * 1133 * @see #EXTRA_WIFI_STATE 1134 */ 1135 public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; 1136 1137 /** @hide */ 1138 @IntDef(flag = false, prefix = { "WIFI_STATE_" }, value = { 1139 WIFI_STATE_DISABLING, 1140 WIFI_STATE_DISABLED, 1141 WIFI_STATE_ENABLING, 1142 WIFI_STATE_ENABLED, 1143 WIFI_STATE_UNKNOWN, 1144 }) 1145 @Retention(RetentionPolicy.SOURCE) 1146 public @interface WifiState {} 1147 1148 /** 1149 * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if 1150 * it finishes successfully. 1151 * 1152 * @see #WIFI_STATE_CHANGED_ACTION 1153 * @see #getWifiState() 1154 */ 1155 public static final int WIFI_STATE_DISABLING = 0; 1156 /** 1157 * Wi-Fi is disabled. 1158 * 1159 * @see #WIFI_STATE_CHANGED_ACTION 1160 * @see #getWifiState() 1161 */ 1162 public static final int WIFI_STATE_DISABLED = 1; 1163 /** 1164 * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if 1165 * it finishes successfully. 1166 * 1167 * @see #WIFI_STATE_CHANGED_ACTION 1168 * @see #getWifiState() 1169 */ 1170 public static final int WIFI_STATE_ENABLING = 2; 1171 /** 1172 * Wi-Fi is enabled. 1173 * 1174 * @see #WIFI_STATE_CHANGED_ACTION 1175 * @see #getWifiState() 1176 */ 1177 public static final int WIFI_STATE_ENABLED = 3; 1178 /** 1179 * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling 1180 * or disabling. 1181 * 1182 * @see #WIFI_STATE_CHANGED_ACTION 1183 * @see #getWifiState() 1184 */ 1185 public static final int WIFI_STATE_UNKNOWN = 4; 1186 1187 /** 1188 * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled, 1189 * enabling, disabling, or failed. 1190 * 1191 * @hide 1192 */ 1193 @SystemApi 1194 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 1195 public static final String WIFI_AP_STATE_CHANGED_ACTION = 1196 "android.net.wifi.WIFI_AP_STATE_CHANGED"; 1197 1198 /** 1199 * The lookup key for an int that indicates whether Wi-Fi AP is enabled, 1200 * disabled, enabling, disabling, or failed. Retrieve it with 1201 * {@link android.content.Intent#getIntExtra(String,int)}. 1202 * 1203 * @see #WIFI_AP_STATE_DISABLED 1204 * @see #WIFI_AP_STATE_DISABLING 1205 * @see #WIFI_AP_STATE_ENABLED 1206 * @see #WIFI_AP_STATE_ENABLING 1207 * @see #WIFI_AP_STATE_FAILED 1208 * 1209 * @hide 1210 */ 1211 @SystemApi 1212 public static final String EXTRA_WIFI_AP_STATE = "wifi_state"; 1213 1214 /** 1215 * An extra containing the int error code for Soft AP start failure. 1216 * Can be obtained from the {@link #WIFI_AP_STATE_CHANGED_ACTION} using 1217 * {@link android.content.Intent#getIntExtra}. 1218 * This extra will only be attached if {@link #EXTRA_WIFI_AP_STATE} is 1219 * attached and is equal to {@link #WIFI_AP_STATE_FAILED}. 1220 * 1221 * The error code will be one of: 1222 * {@link #SAP_START_FAILURE_GENERAL}, 1223 * {@link #SAP_START_FAILURE_NO_CHANNEL}, 1224 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION} 1225 * {@link #SAP_START_FAILURE_USER_REJECTED} 1226 * 1227 * @hide 1228 */ 1229 @SystemApi 1230 public static final String EXTRA_WIFI_AP_FAILURE_REASON = 1231 "android.net.wifi.extra.WIFI_AP_FAILURE_REASON"; 1232 /** 1233 * The previous Wi-Fi state. 1234 * 1235 * @see #EXTRA_WIFI_AP_STATE 1236 * 1237 * @hide 1238 */ 1239 @SystemApi 1240 public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; 1241 /** 1242 * The lookup key for a String extra that stores the interface name used for the Soft AP. 1243 * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. 1244 * Retrieve its value with {@link android.content.Intent#getStringExtra(String)}. 1245 * 1246 * @hide 1247 */ 1248 @SystemApi 1249 public static final String EXTRA_WIFI_AP_INTERFACE_NAME = 1250 "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME"; 1251 /** 1252 * The lookup key for an int extra that stores the intended IP mode for this Soft AP. 1253 * One of {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}. 1254 * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. 1255 * Retrieve its value with {@link android.content.Intent#getIntExtra(String, int)}. 1256 * 1257 * @hide 1258 */ 1259 @SystemApi 1260 public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE"; 1261 1262 /** @hide */ 1263 @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = { 1264 WIFI_AP_STATE_DISABLING, 1265 WIFI_AP_STATE_DISABLED, 1266 WIFI_AP_STATE_ENABLING, 1267 WIFI_AP_STATE_ENABLED, 1268 WIFI_AP_STATE_FAILED, 1269 }) 1270 @Retention(RetentionPolicy.SOURCE) 1271 public @interface WifiApState {} 1272 1273 /** 1274 * Wi-Fi AP is currently being disabled. The state will change to 1275 * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully. 1276 * 1277 * @see #WIFI_AP_STATE_CHANGED_ACTION 1278 * @see #getWifiApState() 1279 * 1280 * @hide 1281 */ 1282 @SystemApi 1283 public static final int WIFI_AP_STATE_DISABLING = 10; 1284 /** 1285 * Wi-Fi AP is disabled. 1286 * 1287 * @see #WIFI_AP_STATE_CHANGED_ACTION 1288 * @see #getWifiState() 1289 * 1290 * @hide 1291 */ 1292 @SystemApi 1293 public static final int WIFI_AP_STATE_DISABLED = 11; 1294 /** 1295 * Wi-Fi AP is currently being enabled. The state will change to 1296 * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully. 1297 * 1298 * @see #WIFI_AP_STATE_CHANGED_ACTION 1299 * @see #getWifiApState() 1300 * 1301 * @hide 1302 */ 1303 @SystemApi 1304 public static final int WIFI_AP_STATE_ENABLING = 12; 1305 /** 1306 * Wi-Fi AP is enabled. 1307 * 1308 * @see #WIFI_AP_STATE_CHANGED_ACTION 1309 * @see #getWifiApState() 1310 * 1311 * @hide 1312 */ 1313 @SystemApi 1314 public static final int WIFI_AP_STATE_ENABLED = 13; 1315 /** 1316 * Wi-Fi AP is in a failed state. This state will occur when an error occurs during 1317 * enabling or disabling 1318 * 1319 * @see #WIFI_AP_STATE_CHANGED_ACTION 1320 * @see #getWifiApState() 1321 * 1322 * @hide 1323 */ 1324 @SystemApi 1325 public static final int WIFI_AP_STATE_FAILED = 14; 1326 1327 /** @hide */ 1328 @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = { 1329 SAP_START_FAILURE_GENERAL, 1330 SAP_START_FAILURE_NO_CHANNEL, 1331 SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION, 1332 SAP_START_FAILURE_USER_REJECTED, 1333 }) 1334 @Retention(RetentionPolicy.SOURCE) 1335 public @interface SapStartFailure {} 1336 1337 /** 1338 * All other reasons for AP start failure besides {@link #SAP_START_FAILURE_NO_CHANNEL}, 1339 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}, and 1340 * {@link #SAP_START_FAILURE_USER_REJECTED}. 1341 * 1342 * @hide 1343 */ 1344 @SystemApi 1345 public static final int SAP_START_FAILURE_GENERAL= 0; 1346 1347 /** 1348 * If Wi-Fi AP start failed, this reason code means that no legal channel exists on user 1349 * selected band due to regulatory constraints. 1350 * 1351 * @hide 1352 */ 1353 @SystemApi 1354 public static final int SAP_START_FAILURE_NO_CHANNEL = 1; 1355 1356 /** 1357 * If Wi-Fi AP start failed, this reason code means that the specified configuration 1358 * is not supported by the current HAL version. 1359 * 1360 * @hide 1361 */ 1362 @SystemApi 1363 public static final int SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION = 2; 1364 1365 /** 1366 * If Wi-Fi AP start failed, this reason code means that the user was asked for confirmation to 1367 * create the AP and the user declined. 1368 * 1369 * @hide 1370 */ 1371 @SystemApi 1372 public static final int SAP_START_FAILURE_USER_REJECTED = 3; 1373 1374 /** @hide */ 1375 @IntDef(flag = false, prefix = { "SAP_CLIENT_BLOCKED_REASON_" }, value = { 1376 SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER, 1377 SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS, 1378 }) 1379 @Retention(RetentionPolicy.SOURCE) 1380 public @interface SapClientBlockedReason {} 1381 1382 /** 1383 * If Soft Ap client is blocked, this reason code means that client doesn't exist in the 1384 * specified configuration {@link SoftApConfiguration.Builder#setBlockedClientList(List)} 1385 * and {@link SoftApConfiguration.Builder#setAllowedClientList(List)} 1386 * and the {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)} 1387 * is configured as well. 1388 * @hide 1389 */ 1390 @SystemApi 1391 public static final int SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER = 0; 1392 1393 /** 1394 * If Soft Ap client is blocked, this reason code means that no more clients can be 1395 * associated to this AP since it reached maximum capacity. The maximum capacity is 1396 * the minimum of {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} and 1397 * {@link SoftApCapability#getMaxSupportedClients} which get from 1398 * {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)}. 1399 * 1400 * @hide 1401 */ 1402 @SystemApi 1403 public static final int SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS = 1; 1404 1405 /** 1406 * Client disconnected for unspecified reason. This could for example be because the AP is being 1407 * shut down. 1408 * @hide 1409 */ 1410 public static final int SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED = 2; 1411 1412 /** @hide */ 1413 @Retention(RetentionPolicy.SOURCE) 1414 @IntDef(prefix = {"IFACE_IP_MODE_"}, value = { 1415 IFACE_IP_MODE_UNSPECIFIED, 1416 IFACE_IP_MODE_CONFIGURATION_ERROR, 1417 IFACE_IP_MODE_TETHERED, 1418 IFACE_IP_MODE_LOCAL_ONLY}) 1419 public @interface IfaceIpMode {} 1420 1421 /** 1422 * Interface IP mode unspecified. 1423 * 1424 * @see #updateInterfaceIpState(String, int) 1425 * 1426 * @hide 1427 */ 1428 @SystemApi 1429 public static final int IFACE_IP_MODE_UNSPECIFIED = -1; 1430 1431 /** 1432 * Interface IP mode for configuration error. 1433 * 1434 * @see #updateInterfaceIpState(String, int) 1435 * 1436 * @hide 1437 */ 1438 @SystemApi 1439 public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; 1440 1441 /** 1442 * Interface IP mode for tethering. 1443 * 1444 * @see #updateInterfaceIpState(String, int) 1445 * 1446 * @hide 1447 */ 1448 @SystemApi 1449 public static final int IFACE_IP_MODE_TETHERED = 1; 1450 1451 /** 1452 * Interface IP mode for Local Only Hotspot. 1453 * 1454 * @see #updateInterfaceIpState(String, int) 1455 * 1456 * @hide 1457 */ 1458 @SystemApi 1459 public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; 1460 1461 /** 1462 * Broadcast intent action indicating that the wifi network settings 1463 * had been reset. 1464 * 1465 * Note: This intent is sent as a directed broadcast to each manifest registered receiver. 1466 * Intent will not be received by dynamically registered receivers. 1467 * @hide 1468 */ 1469 @SystemApi 1470 @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) 1471 public static final String ACTION_NETWORK_SETTINGS_RESET = 1472 "android.net.wifi.action.NETWORK_SETTINGS_RESET"; 1473 1474 /** 1475 * Broadcast intent action indicating that the wifi network profiles provisioned 1476 * may need refresh. 1477 * 1478 * Note: This intent is sent as a directed broadcast to each manifest registered receiver; 1479 * And restricted to those apps which have the NETWORK_CARRIER_PROVISIONING permission. 1480 * Intent will not be received by dynamically registered receivers. 1481 * @hide 1482 */ 1483 @SystemApi 1484 @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) 1485 public static final String ACTION_REFRESH_USER_PROVISIONING = 1486 "android.net.wifi.action.REFRESH_USER_PROVISIONING"; 1487 1488 /** 1489 * Broadcast intent action indicating that a connection to the supplicant has 1490 * been established (and it is now possible 1491 * to perform Wi-Fi operations) or the connection to the supplicant has been 1492 * lost. One extra provides the connection state as a boolean, where {@code true} 1493 * means CONNECTED. 1494 * @deprecated This is no longer supported. 1495 * @see #EXTRA_SUPPLICANT_CONNECTED 1496 */ 1497 @Deprecated 1498 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1499 public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = 1500 "android.net.wifi.supplicant.CONNECTION_CHANGE"; 1501 /** 1502 * The lookup key for a boolean that indicates whether a connection to 1503 * the supplicant daemon has been gained or lost. {@code true} means 1504 * a connection now exists. 1505 * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. 1506 * @deprecated This is no longer supported. 1507 */ 1508 @Deprecated 1509 public static final String EXTRA_SUPPLICANT_CONNECTED = "connected"; 1510 /** 1511 * Broadcast intent action indicating that the state of Wi-Fi connectivity 1512 * has changed. An extra provides the new state 1513 * in the form of a {@link android.net.NetworkInfo} object. No network-related 1514 * permissions are required to subscribe to this broadcast. 1515 * 1516 * <p class="note">This broadcast is not delivered to manifest receivers in 1517 * applications that target API version 26 or later. 1518 * @see #EXTRA_NETWORK_INFO 1519 */ 1520 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1521 public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"; 1522 /** 1523 * The lookup key for a {@link android.net.NetworkInfo} object associated with the 1524 * Wi-Fi network. Retrieve with 1525 * {@link android.content.Intent#getParcelableExtra(String)}. 1526 */ 1527 public static final String EXTRA_NETWORK_INFO = "networkInfo"; 1528 /** 1529 * The lookup key for a String giving the BSSID of the access point to which 1530 * we are connected. No longer used. 1531 */ 1532 @Deprecated 1533 public static final String EXTRA_BSSID = "bssid"; 1534 /** 1535 * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the 1536 * information about the access point to which we are connected. 1537 * No longer used. 1538 */ 1539 @Deprecated 1540 public static final String EXTRA_WIFI_INFO = "wifiInfo"; 1541 /** 1542 * Broadcast intent action indicating that the state of establishing a connection to 1543 * an access point has changed.One extra provides the new 1544 * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and 1545 * is not generally the most useful thing to look at if you are just interested in 1546 * the overall state of connectivity. 1547 * @see #EXTRA_NEW_STATE 1548 * @see #EXTRA_SUPPLICANT_ERROR 1549 * @deprecated This is no longer supported. 1550 */ 1551 @Deprecated 1552 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1553 public static final String SUPPLICANT_STATE_CHANGED_ACTION = 1554 "android.net.wifi.supplicant.STATE_CHANGE"; 1555 /** 1556 * The lookup key for a {@link SupplicantState} describing the new state 1557 * Retrieve with 1558 * {@link android.content.Intent#getParcelableExtra(String)}. 1559 * @deprecated This is no longer supported. 1560 */ 1561 @Deprecated 1562 public static final String EXTRA_NEW_STATE = "newState"; 1563 1564 /** 1565 * The lookup key for a {@link SupplicantState} describing the supplicant 1566 * error code if any 1567 * Retrieve with 1568 * {@link android.content.Intent#getIntExtra(String, int)}. 1569 * @see #ERROR_AUTHENTICATING 1570 * @deprecated This is no longer supported. 1571 */ 1572 @Deprecated 1573 public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; 1574 1575 /** 1576 * The lookup key for a {@link SupplicantState} describing the supplicant 1577 * error reason if any 1578 * Retrieve with 1579 * {@link android.content.Intent#getIntExtra(String, int)}. 1580 * @see #ERROR_AUTH_FAILURE_#REASON_CODE 1581 * @deprecated This is no longer supported. 1582 * @hide 1583 */ 1584 @Deprecated 1585 public static final String EXTRA_SUPPLICANT_ERROR_REASON = "supplicantErrorReason"; 1586 1587 /** 1588 * Broadcast intent action indicating that the configured networks changed. 1589 * This can be as a result of adding/updating/deleting a network. 1590 * <br /> 1591 * {@link #EXTRA_CHANGE_REASON} contains whether the configuration was added/changed/removed. 1592 * {@link #EXTRA_WIFI_CONFIGURATION} is never set beginning in 1593 * {@link android.os.Build.VERSION_CODES#R}. 1594 * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set for backwards compatibility reasons, but 1595 * its value is always true beginning in {@link android.os.Build.VERSION_CODES#R}, even if only 1596 * a single network changed. 1597 * <br /> 1598 * The {@link android.Manifest.permission#ACCESS_WIFI_STATE ACCESS_WIFI_STATE} permission is 1599 * required to receive this broadcast. 1600 * 1601 * @hide 1602 */ 1603 @SystemApi 1604 public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = 1605 "android.net.wifi.CONFIGURED_NETWORKS_CHANGE"; 1606 /** 1607 * The lookup key for a {@link android.net.wifi.WifiConfiguration} object representing 1608 * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION} 1609 * broadcast is sent. 1610 * @deprecated This extra is never set beginning in {@link android.os.Build.VERSION_CODES#R}, 1611 * regardless of the target SDK version. Use {@link #getConfiguredNetworks} to get the full list 1612 * of configured networks. 1613 * @hide 1614 */ 1615 @Deprecated 1616 @SystemApi 1617 public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; 1618 /** 1619 * Multiple network configurations have changed. 1620 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 1621 * @deprecated This extra's value is always true beginning in 1622 * {@link android.os.Build.VERSION_CODES#R}, regardless of the target SDK version. 1623 * @hide 1624 */ 1625 @Deprecated 1626 @SystemApi 1627 public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges"; 1628 /** 1629 * The lookup key for an integer indicating the reason a Wi-Fi network configuration 1630 * has changed. One of {@link #CHANGE_REASON_ADDED}, {@link #CHANGE_REASON_REMOVED}, 1631 * {@link #CHANGE_REASON_CONFIG_CHANGE}. 1632 * 1633 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 1634 * @hide 1635 */ 1636 @SystemApi 1637 public static final String EXTRA_CHANGE_REASON = "changeReason"; 1638 /** 1639 * The configuration is new and was added. 1640 * @hide 1641 */ 1642 @SystemApi 1643 public static final int CHANGE_REASON_ADDED = 0; 1644 /** 1645 * The configuration was removed and is no longer present in the system's list of 1646 * configured networks. 1647 * @hide 1648 */ 1649 @SystemApi 1650 public static final int CHANGE_REASON_REMOVED = 1; 1651 /** 1652 * The configuration has changed as a result of explicit action or because the system 1653 * took an automated action such as disabling a malfunctioning configuration. 1654 * @hide 1655 */ 1656 @SystemApi 1657 public static final int CHANGE_REASON_CONFIG_CHANGE = 2; 1658 /** 1659 * An access point scan has completed, and results are available. 1660 * Call {@link #getScanResults()} to obtain the results. 1661 * The broadcast intent may contain an extra field with the key {@link #EXTRA_RESULTS_UPDATED} 1662 * and a {@code boolean} value indicating if the scan was successful. 1663 */ 1664 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1665 public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; 1666 1667 /** 1668 * Lookup key for a {@code boolean} extra in intent {@link #SCAN_RESULTS_AVAILABLE_ACTION} 1669 * representing if the scan was successful or not. 1670 * Scans may fail for multiple reasons, these may include: 1671 * <ol> 1672 * <li>An app requested too many scans in a certain period of time. 1673 * This may lead to additional scan request rejections via "scan throttling" for both 1674 * foreground and background apps. 1675 * Note: Apps holding android.Manifest.permission.NETWORK_SETTINGS permission are 1676 * exempted from scan throttling. 1677 * </li> 1678 * <li>The device is idle and scanning is disabled.</li> 1679 * <li>Wifi hardware reported a scan failure.</li> 1680 * </ol> 1681 * @return true scan was successful, results are updated 1682 * @return false scan was not successful, results haven't been updated since previous scan 1683 */ 1684 public static final String EXTRA_RESULTS_UPDATED = "resultsUpdated"; 1685 1686 /** 1687 * A batch of access point scans has been completed and the results areavailable. 1688 * Call {@link #getBatchedScanResults()} to obtain the results. 1689 * @deprecated This API is nolonger supported. 1690 * Use {@link WifiScanner} API 1691 * @hide 1692 */ 1693 @Deprecated 1694 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1695 public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION = 1696 "android.net.wifi.BATCHED_RESULTS"; 1697 1698 /** 1699 * The RSSI (signal strength) has changed. 1700 * 1701 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 1702 * @see #EXTRA_NEW_RSSI 1703 */ 1704 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1705 public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; 1706 /** 1707 * The lookup key for an {@code int} giving the new RSSI in dBm. 1708 */ 1709 public static final String EXTRA_NEW_RSSI = "newRssi"; 1710 1711 /** 1712 * @see #ACTION_LINK_CONFIGURATION_CHANGED 1713 * @hide 1714 */ 1715 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1716 public static final String LINK_CONFIGURATION_CHANGED_ACTION = 1717 "android.net.wifi.LINK_CONFIGURATION_CHANGED"; 1718 1719 /** 1720 * Broadcast intent action indicating that the link configuration changed on wifi. 1721 * <br /> No permissions are required to listen to this broadcast. 1722 * @hide 1723 */ 1724 @SystemApi 1725 public static final String ACTION_LINK_CONFIGURATION_CHANGED = 1726 // should be android.net.wifi.action.LINK_CONFIGURATION_CHANGED, but due to 1727 // @UnsupportedAppUsage leaving it as android.net.wifi.LINK_CONFIGURATION_CHANGED. 1728 LINK_CONFIGURATION_CHANGED_ACTION; 1729 1730 /** 1731 * The lookup key for a {@link android.net.LinkProperties} object associated with the 1732 * Wi-Fi network. 1733 * Included in the {@link #ACTION_LINK_CONFIGURATION_CHANGED} broadcast. 1734 * 1735 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 1736 * 1737 * @deprecated this extra is no longer populated. 1738 * 1739 * @hide 1740 */ 1741 @Deprecated 1742 @SystemApi 1743 public static final String EXTRA_LINK_PROPERTIES = "android.net.wifi.extra.LINK_PROPERTIES"; 1744 1745 /** 1746 * The lookup key for a {@link android.net.NetworkCapabilities} object associated with the 1747 * Wi-Fi network. Retrieve with 1748 * {@link android.content.Intent#getParcelableExtra(String)}. 1749 * @hide 1750 */ 1751 public static final String EXTRA_NETWORK_CAPABILITIES = "networkCapabilities"; 1752 1753 /** 1754 * The network IDs of the configured networks could have changed. 1755 */ 1756 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1757 public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; 1758 1759 /** 1760 * Activity Action: Show a system activity that allows the user to enable 1761 * scans to be available even with Wi-Fi turned off. 1762 * 1763 * <p>Notification of the result of this activity is posted using the 1764 * {@link android.app.Activity#onActivityResult} callback. The 1765 * <code>resultCode</code> 1766 * will be {@link android.app.Activity#RESULT_OK} if scan always mode has 1767 * been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user 1768 * has rejected the request or an error has occurred. 1769 */ 1770 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1771 public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = 1772 "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; 1773 1774 /** 1775 * Activity Action: Pick a Wi-Fi network to connect to. 1776 * <p>Input: Nothing. 1777 * <p>Output: Nothing. 1778 */ 1779 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1780 public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; 1781 1782 /** 1783 * Activity Action: Receiver should show UI to get user approval to enable WiFi. 1784 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 1785 * the name of the app requesting the action. 1786 * <p>Output: Nothing. 1787 * <p>No permissions are required to send this action. 1788 * @hide 1789 */ 1790 @SystemApi 1791 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1792 public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE"; 1793 1794 /** 1795 * Activity Action: Receiver should show UI to get user approval to disable WiFi. 1796 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 1797 * the name of the app requesting the action. 1798 * <p>Output: Nothing. 1799 * <p>No permissions are required to send this action. 1800 * @hide 1801 */ 1802 @SystemApi 1803 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1804 public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; 1805 1806 /** 1807 * Directed broadcast intent action indicating that the device has connected to one of the 1808 * network suggestions provided by the app. This will be sent post connection to a network 1809 * which was created with {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired( 1810 * boolean)} 1811 * flag set. 1812 * <p> 1813 * Note: The broadcast is sent to the app only if it holds 1814 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission. 1815 * 1816 * @see #EXTRA_NETWORK_SUGGESTION 1817 */ 1818 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1819 public static final String ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION = 1820 "android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION"; 1821 /** 1822 * Sent as as a part of {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} that holds 1823 * an instance of {@link WifiNetworkSuggestion} corresponding to the connected network. 1824 */ 1825 public static final String EXTRA_NETWORK_SUGGESTION = 1826 "android.net.wifi.extra.NETWORK_SUGGESTION"; 1827 1828 /** 1829 * Internally used Wi-Fi lock mode representing the case were no locks are held. 1830 * @hide 1831 */ 1832 public static final int WIFI_MODE_NO_LOCKS_HELD = 0; 1833 1834 /** 1835 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 1836 * and will behave normally, i.e., it will attempt to automatically 1837 * establish a connection to a remembered access point that is 1838 * within range, and will do periodic scans if there are remembered 1839 * access points but none are in range. 1840 * 1841 * @deprecated This API is non-functional and will have no impact. 1842 */ 1843 @Deprecated 1844 public static final int WIFI_MODE_FULL = 1; 1845 1846 /** 1847 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 1848 * but the only operation that will be supported is initiation of 1849 * scans, and the subsequent reporting of scan results. No attempts 1850 * will be made to automatically connect to remembered access points, 1851 * nor will periodic scans be automatically performed looking for 1852 * remembered access points. Scans must be explicitly requested by 1853 * an application in this mode. 1854 * 1855 * @deprecated This API is non-functional and will have no impact. 1856 */ 1857 @Deprecated 1858 public static final int WIFI_MODE_SCAN_ONLY = 2; 1859 1860 /** 1861 * In this Wi-Fi lock mode, Wi-Fi will not go to power save. 1862 * This results in operating with low packet latency. 1863 * The lock is only active when the device is connected to an access point. 1864 * The lock is active even when the device screen is off or the acquiring application is 1865 * running in the background. 1866 * This mode will consume more power and hence should be used only 1867 * when there is a need for this tradeoff. 1868 * <p> 1869 * An example use case is when a voice connection needs to be 1870 * kept active even after the device screen goes off. 1871 * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the 1872 * duration of the voice call may improve the call quality. 1873 * <p> 1874 * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_HIGH_PERF} 1875 * lock will have no impact. 1876 * 1877 * @deprecated The {@code WIFI_MODE_FULL_HIGH_PERF} is deprecated and is automatically replaced 1878 * with {@link #WIFI_MODE_FULL_LOW_LATENCY} with all the restrictions documented on that lock. 1879 * I.e. any request to the {@code WIFI_MODE_FULL_HIGH_PERF} will now obtain a 1880 * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock instead. 1881 * Deprecation is due to the impact of {@code WIFI_MODE_FULL_HIGH_PERF} on power dissipation. 1882 * The {@link #WIFI_MODE_FULL_LOW_LATENCY} provides much of the same desired functionality with 1883 * less impact on power dissipation. 1884 */ 1885 @Deprecated 1886 public static final int WIFI_MODE_FULL_HIGH_PERF = 3; 1887 1888 /** 1889 * In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency. 1890 * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock has the following limitations: 1891 * <ol> 1892 * <li>The lock is only active when the device is connected to an access point.</li> 1893 * <li>The lock is only active when the screen is on.</li> 1894 * <li>The lock is only active when the acquiring app is running in the foreground.</li> 1895 * </ol> 1896 * Low latency mode optimizes for reduced packet latency, 1897 * and as a result other performance measures may suffer when there are trade-offs to make: 1898 * <ol> 1899 * <li>Battery life may be reduced.</li> 1900 * <li>Throughput may be reduced.</li> 1901 * <li>Frequency of Wi-Fi scanning may be reduced. This may result in: </li> 1902 * <ul> 1903 * <li>The device may not roam or switch to the AP with highest signal quality.</li> 1904 * <li>Location accuracy may be reduced.</li> 1905 * </ul> 1906 * </ol> 1907 * <p> 1908 * Example use cases are real time gaming or virtual reality applications where 1909 * low latency is a key factor for user experience. 1910 * <p> 1911 * Note: For an app which acquires both {@link #WIFI_MODE_FULL_LOW_LATENCY} and 1912 * {@link #WIFI_MODE_FULL_HIGH_PERF} locks, {@link #WIFI_MODE_FULL_LOW_LATENCY} 1913 * lock will be effective when app is running in foreground and screen is on, 1914 * while the {@link #WIFI_MODE_FULL_HIGH_PERF} lock will take effect otherwise. 1915 */ 1916 public static final int WIFI_MODE_FULL_LOW_LATENCY = 4; 1917 1918 1919 /** Anything worse than or equal to this will show 0 bars. */ 1920 @UnsupportedAppUsage 1921 private static final int MIN_RSSI = -100; 1922 1923 /** Anything better than or equal to this will show the max bars. */ 1924 @UnsupportedAppUsage 1925 private static final int MAX_RSSI = -55; 1926 1927 /** 1928 * Number of RSSI levels used in the framework to initiate {@link #RSSI_CHANGED_ACTION} 1929 * broadcast, where each level corresponds to a range of RSSI values. 1930 * The {@link #RSSI_CHANGED_ACTION} broadcast will only fire if the RSSI 1931 * change is significant enough to change the RSSI signal level. 1932 * @hide 1933 */ 1934 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1935 public static final int RSSI_LEVELS = 5; 1936 1937 //TODO (b/146346676): This needs to be removed, not used in the code. 1938 /** 1939 * Auto settings in the driver. The driver could choose to operate on both 1940 * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band. 1941 * @hide 1942 */ 1943 @UnsupportedAppUsage 1944 public static final int WIFI_FREQUENCY_BAND_AUTO = 0; 1945 1946 /** 1947 * Operation on 5 GHz alone 1948 * @hide 1949 */ 1950 @UnsupportedAppUsage 1951 public static final int WIFI_FREQUENCY_BAND_5GHZ = 1; 1952 1953 /** 1954 * Operation on 2.4 GHz alone 1955 * @hide 1956 */ 1957 @UnsupportedAppUsage 1958 public static final int WIFI_FREQUENCY_BAND_2GHZ = 2; 1959 1960 /** @hide */ 1961 public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false; 1962 1963 /** 1964 * Maximum number of active locks we allow. 1965 * This limit was added to prevent apps from creating a ridiculous number 1966 * of locks and crashing the system by overflowing the global ref table. 1967 */ 1968 private static final int MAX_ACTIVE_LOCKS = 50; 1969 1970 /** Indicates an invalid SSID. */ 1971 public static final String UNKNOWN_SSID = "<unknown ssid>"; 1972 1973 /** @hide */ 1974 public static final MacAddress ALL_ZEROS_MAC_ADDRESS = 1975 MacAddress.fromString("00:00:00:00:00:00"); 1976 1977 /** @hide */ 1978 @IntDef(flag = false, prefix = { "WIFI_MULTI_INTERNET_MODE_" }, value = { 1979 WIFI_MULTI_INTERNET_MODE_DISABLED, 1980 WIFI_MULTI_INTERNET_MODE_DBS_AP, 1981 WIFI_MULTI_INTERNET_MODE_MULTI_AP, 1982 }) 1983 @Retention(RetentionPolicy.SOURCE) 1984 public @interface WifiMultiInternetMode {} 1985 1986 /** 1987 * Wi-Fi simultaneous connection to multiple internet-providing Wi-Fi networks (APs) is 1988 * disabled. 1989 * 1990 * @see #getStaConcurrencyForMultiInternetMode() 1991 * 1992 */ 1993 public static final int WIFI_MULTI_INTERNET_MODE_DISABLED = 0; 1994 /** 1995 * Wi-Fi simultaneous connection to multiple internet-providing Wi-FI networks (APs) is enabled 1996 * and restricted to a single network on different bands (e.g. a DBS AP). 1997 * 1998 * @see #getStaConcurrencyForMultiInternetMode() 1999 * 2000 */ 2001 public static final int WIFI_MULTI_INTERNET_MODE_DBS_AP = 1; 2002 /** 2003 * Wi-Fi simultaneous connection to multiple internet-providing Wi-Fi networks (APs) is enabled. 2004 * The device can connect to any networks/APs - it is just restricted to using different bands 2005 * for individual connections. 2006 * 2007 * @see #getStaConcurrencyForMultiInternetMode() 2008 * 2009 */ 2010 public static final int WIFI_MULTI_INTERNET_MODE_MULTI_AP = 2; 2011 2012 /** 2013 * The bundle key string for the channel frequency in MHz. 2014 * See {@link #getChannelData(Executor, Consumer)} 2015 */ 2016 public static final String CHANNEL_DATA_KEY_FREQUENCY_MHZ = "CHANNEL_DATA_KEY_FREQUENCY_MHZ"; 2017 /** 2018 * The bundle key for the number of APs found on the corresponding channel specified by 2019 * {@link WifiManager#CHANNEL_DATA_KEY_FREQUENCY_MHZ}. 2020 * See {@link #getChannelData(Executor, Consumer)} 2021 */ 2022 public static final String CHANNEL_DATA_KEY_NUM_AP = "CHANNEL_DATA_KEY_NUM_AP"; 2023 2024 /** 2025 * This policy is being tracked by the Wifi service. 2026 * Indicates success for {@link #addQosPolicies(List, Executor, Consumer)}. 2027 * @hide 2028 */ 2029 @SystemApi 2030 public static final int QOS_REQUEST_STATUS_TRACKING = 0; 2031 2032 /** 2033 * A policy with the same policy ID is already being tracked. 2034 * @hide 2035 */ 2036 @SystemApi 2037 public static final int QOS_REQUEST_STATUS_ALREADY_ACTIVE = 1; 2038 2039 /** 2040 * There are insufficient resources to handle this request at this time. 2041 * @hide 2042 */ 2043 @SystemApi 2044 public static final int QOS_REQUEST_STATUS_INSUFFICIENT_RESOURCES = 2; 2045 2046 /** 2047 * The parameters in the policy request are invalid. 2048 * @hide 2049 */ 2050 @SystemApi 2051 public static final int QOS_REQUEST_STATUS_INVALID_PARAMETERS = 3; 2052 2053 /** 2054 * An unspecified failure occurred while processing this request. 2055 * @hide 2056 */ 2057 @SystemApi 2058 public static final int QOS_REQUEST_STATUS_FAILURE_UNKNOWN = 4; 2059 2060 /** @hide */ 2061 @Retention(RetentionPolicy.SOURCE) 2062 @IntDef(prefix = {"QOS_REQUEST_STATUS_"}, value = { 2063 QOS_REQUEST_STATUS_TRACKING, 2064 QOS_REQUEST_STATUS_ALREADY_ACTIVE, 2065 QOS_REQUEST_STATUS_INSUFFICIENT_RESOURCES, 2066 QOS_REQUEST_STATUS_INVALID_PARAMETERS, 2067 QOS_REQUEST_STATUS_FAILURE_UNKNOWN}) 2068 public @interface QosRequestStatus {} 2069 2070 /** 2071 * Maximum number of policies that can be included in a QoS add/remove request. 2072 */ 2073 private static final int MAX_POLICIES_PER_QOS_REQUEST = 16; 2074 2075 /** 2076 * Get the maximum number of policies that can be included in a request to 2077 * {@link #addQosPolicies(List, Executor, Consumer)} or {@link #removeQosPolicies(int[])}. 2078 * @hide 2079 */ 2080 @SystemApi getMaxNumberOfPoliciesPerQosRequest()2081 public static int getMaxNumberOfPoliciesPerQosRequest() { 2082 return MAX_POLICIES_PER_QOS_REQUEST; 2083 } 2084 2085 /* Number of currently active WifiLocks and MulticastLocks */ 2086 @UnsupportedAppUsage 2087 private int mActiveLockCount; 2088 2089 private Context mContext; 2090 @UnsupportedAppUsage 2091 IWifiManager mService; 2092 private final int mTargetSdkVersion; 2093 2094 private Looper mLooper; 2095 private boolean mVerboseLoggingEnabled = false; 2096 2097 private final Object mLock = new Object(); // lock guarding access to the following vars 2098 @GuardedBy("mLock") 2099 private LocalOnlyHotspotCallbackProxy mLOHSCallbackProxy; 2100 @GuardedBy("mLock") 2101 private LocalOnlyHotspotObserverProxy mLOHSObserverProxy; 2102 2103 private static final SparseArray<IOnWifiUsabilityStatsListener> 2104 sOnWifiUsabilityStatsListenerMap = new SparseArray(); 2105 private static final SparseArray<ISuggestionConnectionStatusListener> 2106 sSuggestionConnectionStatusListenerMap = new SparseArray(); 2107 private static final SparseArray<ISuggestionUserApprovalStatusListener> 2108 sSuggestionUserApprovalStatusListenerMap = new SparseArray(); 2109 private static final SparseArray<IWifiVerboseLoggingStatusChangedListener> 2110 sWifiVerboseLoggingStatusChangedListenerMap = new SparseArray(); 2111 private static final SparseArray<INetworkRequestMatchCallback> 2112 sNetworkRequestMatchCallbackMap = new SparseArray(); 2113 private static final SparseArray<ITrafficStateCallback> 2114 sTrafficStateCallbackMap = new SparseArray(); 2115 private static final SparseArray<ISoftApCallback> sSoftApCallbackMap = new SparseArray(); 2116 private static final SparseArray<IOnWifiDriverCountryCodeChangedListener> 2117 sActiveCountryCodeChangedCallbackMap = new SparseArray(); 2118 private static final SparseArray<ISoftApCallback> 2119 sLocalOnlyHotspotSoftApCallbackMap = new SparseArray(); 2120 private static final SparseArray<ILocalOnlyConnectionStatusListener> 2121 sLocalOnlyConnectionStatusListenerMap = new SparseArray(); 2122 private static final SparseArray<IWifiNetworkStateChangedListener> 2123 sOnWifiNetworkStateChangedListenerMap = new SparseArray<>(); 2124 private static final SparseArray<IWifiLowLatencyLockListener> 2125 sWifiLowLatencyLockListenerMap = new SparseArray<>(); 2126 private static final SparseArray<IWifiStateChangedListener> 2127 sWifiStateChangedListenerMap = new SparseArray<>(); 2128 2129 /** 2130 * Multi-link operation (MLO) will allow Wi-Fi devices to operate on multiple links at the same 2131 * time through a single connection, aiming to support applications that require lower latency, 2132 * and higher capacity. Chip vendors have algorithms that run on the chip to use available links 2133 * based on incoming traffic and various inputs. Below is a list of Multi-Link Operation modes 2134 * that applications can suggest to be accommodated in the algorithm. 2135 * 2136 * The default MLO mode is for chip vendors to use algorithms to select the optimum links to 2137 * operate on, without any guidance from the calling app. 2138 * 2139 * @hide 2140 */ 2141 @SystemApi 2142 public static final int MLO_MODE_DEFAULT = 0; 2143 2144 /** 2145 * Low latency mode for Multi-link operation. In this mode, the chip vendor's algorithm 2146 * should select MLO links that will achieve low latency. 2147 * 2148 * @hide 2149 */ 2150 @SystemApi 2151 public static final int MLO_MODE_LOW_LATENCY = 1; 2152 2153 /** 2154 * High throughput mode for Multi-link operation. In this mode, the chip vendor's algorithm 2155 * should select MLO links that will achieve higher throughput. 2156 * 2157 * @hide 2158 */ 2159 @SystemApi 2160 public static final int MLO_MODE_HIGH_THROUGHPUT = 2; 2161 2162 /** 2163 * Low power mode for Multi-link operation. In this mode, the chip vendor's algorithm 2164 * should select MLO links that will achieve low power. 2165 * 2166 * @hide 2167 */ 2168 @SystemApi 2169 public static final int MLO_MODE_LOW_POWER = 3; 2170 2171 /** @hide */ 2172 @Retention(RetentionPolicy.SOURCE) 2173 @IntDef(prefix = {"MLO_MODE_"}, value = { 2174 MLO_MODE_DEFAULT, 2175 MLO_MODE_LOW_LATENCY, 2176 MLO_MODE_HIGH_THROUGHPUT, 2177 MLO_MODE_LOW_POWER}) 2178 public @interface MloMode { 2179 } 2180 2181 /** 2182 * Roaming is disabled. 2183 */ 2184 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 2185 public static final int ROAMING_MODE_NONE = 0; 2186 2187 /** 2188 * Chipset has roaming trigger capability based on the score calculated 2189 * using multiple parameters. If device is configured to this mode then it 2190 * will be using chipset's normal (default) roaming. 2191 */ 2192 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 2193 public static final int ROAMING_MODE_NORMAL = 1; 2194 2195 /** 2196 * Allows the device to roam more quickly than the normal roaming mode. 2197 * Used in cases such as where APs are installed in a high density. 2198 */ 2199 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 2200 public static final int ROAMING_MODE_AGGRESSIVE = 2; 2201 2202 /** 2203 * @hide 2204 */ 2205 @Retention(RetentionPolicy.SOURCE) 2206 @IntDef(prefix = {"ROAMING_MODE_"}, value = { 2207 ROAMING_MODE_NONE, 2208 ROAMING_MODE_NORMAL, 2209 ROAMING_MODE_AGGRESSIVE}) 2210 public @interface RoamingMode { 2211 } 2212 2213 /** 2214 * Create a new WifiManager instance. 2215 * Applications will almost always want to use 2216 * {@link android.content.Context#getSystemService Context.getSystemService} to retrieve 2217 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. 2218 * 2219 * @param context the application context 2220 * @param service the Binder interface 2221 * @hide - hide this because it takes in a parameter of type IWifiManager, which 2222 * is a system private class. 2223 */ WifiManager(@onNull Context context, @NonNull IWifiManager service)2224 public WifiManager(@NonNull Context context, @NonNull IWifiManager service) { 2225 mContext = context; 2226 mService = service; 2227 mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; 2228 updateVerboseLoggingEnabledFromService(); 2229 } 2230 2231 /** 2232 * Return a list of all the networks configured for the current foreground 2233 * user. 2234 * 2235 * Not all fields of WifiConfiguration are returned. Only the following 2236 * fields are filled in: 2237 * <ul> 2238 * <li>networkId</li> 2239 * <li>SSID</li> 2240 * <li>BSSID</li> 2241 * <li>priority</li> 2242 * <li>allowedProtocols</li> 2243 * <li>allowedKeyManagement</li> 2244 * <li>allowedAuthAlgorithms</li> 2245 * <li>allowedPairwiseCiphers</li> 2246 * <li>allowedGroupCiphers</li> 2247 * <li>status</li> 2248 * </ul> 2249 * @return a list of network configurations in the form of a list 2250 * of {@link WifiConfiguration} objects. 2251 * 2252 * @deprecated 2253 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2254 * mechanism to trigger connection to a Wi-Fi network. 2255 * b) See {@link #addNetworkSuggestions(List)}, 2256 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2257 * when auto-connecting to wifi. 2258 * <b>Compatibility Note:</b> For applications targeting 2259 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return an 2260 * empty list. 2261 * <p> 2262 * Deprecation Exemptions: 2263 * <ul> 2264 * <li>Device Owner (DO), Profile Owner (PO) and system apps will have access to the full list. 2265 * <li>Callers with Carrier privilege will receive a restricted list only containing 2266 * configurations which they created. 2267 * </ul> 2268 */ 2269 @Deprecated 2270 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) getConfiguredNetworks()2271 public List<WifiConfiguration> getConfiguredNetworks() { 2272 try { 2273 ParceledListSlice<WifiConfiguration> parceledList = 2274 mService.getConfiguredNetworks(mContext.getOpPackageName(), 2275 mContext.getAttributionTag(), false); 2276 if (parceledList == null) { 2277 return Collections.emptyList(); 2278 } 2279 return parceledList.getList(); 2280 } catch (RemoteException e) { 2281 throw e.rethrowFromSystemServer(); 2282 } 2283 } 2284 2285 /** 2286 * Return a list of all the networks previously configured by the calling app. Can 2287 * be called by Device Owner (DO), Profile Owner (PO), Callers with Carrier privilege and 2288 * system apps. 2289 * 2290 * @return a list of network configurations in the form of a list 2291 * of {@link WifiConfiguration} objects. 2292 * @throws SecurityException if the caller is not allowed to call this API 2293 */ 2294 @RequiresPermission(ACCESS_WIFI_STATE) 2295 @NonNull getCallerConfiguredNetworks()2296 public List<WifiConfiguration> getCallerConfiguredNetworks() { 2297 try { 2298 ParceledListSlice<WifiConfiguration> parceledList = 2299 mService.getConfiguredNetworks(mContext.getOpPackageName(), 2300 mContext.getAttributionTag(), true); 2301 if (parceledList == null) { 2302 return Collections.emptyList(); 2303 } 2304 return parceledList.getList(); 2305 } catch (RemoteException e) { 2306 throw e.rethrowFromSystemServer(); 2307 } 2308 } 2309 2310 2311 /** 2312 * Applications targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later need to have 2313 * the following permissions: {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}, 2314 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and 2315 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. 2316 * Applications targeting {@link Build.VERSION_CODES#S} or prior SDK levels need to have the 2317 * following permissions: {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, 2318 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 2319 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. 2320 * <p> See {@link #getPrivilegedConnectedNetwork()} to get the WifiConfiguration for only the 2321 * connected network that's providing internet by default. 2322 * 2323 * @hide 2324 **/ 2325 @SystemApi 2326 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, NEARBY_WIFI_DEVICES, ACCESS_WIFI_STATE, 2327 READ_WIFI_CREDENTIAL}, 2328 conditional = true) getPrivilegedConfiguredNetworks()2329 public List<WifiConfiguration> getPrivilegedConfiguredNetworks() { 2330 try { 2331 Bundle extras = new Bundle(); 2332 if (SdkLevel.isAtLeastS()) { 2333 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 2334 mContext.getAttributionSource()); 2335 } 2336 ParceledListSlice<WifiConfiguration> parceledList = 2337 mService.getPrivilegedConfiguredNetworks(mContext.getOpPackageName(), 2338 mContext.getAttributionTag(), extras); 2339 if (parceledList == null) { 2340 return Collections.emptyList(); 2341 } 2342 return parceledList.getList(); 2343 } catch (RemoteException e) { 2344 throw e.rethrowFromSystemServer(); 2345 } 2346 } 2347 2348 /** 2349 * Gets the {@link WifiConfiguration} with credentials of the connected wifi network 2350 * that's providing internet by default. 2351 * <p> 2352 * On {@link android.os.Build.VERSION_CODES#TIRAMISU} or later SDKs, the caller need to have 2353 * the following permissions: {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with 2354 * android:usesPermissionFlags="neverForLocation", 2355 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and 2356 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. If the app does not have 2357 * android:usesPermissionFlags="neverForLocation", then it must also have 2358 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}. 2359 * <p> 2360 * On {@link Build.VERSION_CODES#S} or prior SDKs, the caller need to have the 2361 * following permissions: {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, 2362 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 2363 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. 2364 * 2365 * @return The WifiConfiguration representation of the connected wifi network providing 2366 * internet, or null if wifi is not connected. 2367 * 2368 * @throws SecurityException if caller does not have the required permissions 2369 * @hide 2370 **/ 2371 @SystemApi 2372 @RequiresPermission(allOf = {NEARBY_WIFI_DEVICES, ACCESS_WIFI_STATE, READ_WIFI_CREDENTIAL}, 2373 conditional = true) 2374 @Nullable getPrivilegedConnectedNetwork()2375 public WifiConfiguration getPrivilegedConnectedNetwork() { 2376 try { 2377 Bundle extras = new Bundle(); 2378 if (SdkLevel.isAtLeastS()) { 2379 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 2380 mContext.getAttributionSource()); 2381 } 2382 return mService.getPrivilegedConnectedNetwork(mContext.getOpPackageName(), 2383 mContext.getAttributionTag(), extras); 2384 } catch (RemoteException e) { 2385 throw e.rethrowFromSystemServer(); 2386 } 2387 } 2388 2389 /** 2390 * Returns a list of all matching WifiConfigurations of PasspointConfiguration for a given list 2391 * of ScanResult. 2392 * 2393 * An empty list will be returned when no PasspointConfiguration are installed or if no 2394 * PasspointConfiguration match the ScanResult. 2395 * 2396 * @param scanResults a list of scanResult that represents the BSSID 2397 * @return List that consists of {@link WifiConfiguration} and corresponding scanResults per 2398 * network type({@link #PASSPOINT_HOME_NETWORK} and {@link #PASSPOINT_ROAMING_NETWORK}). 2399 * @hide 2400 */ 2401 @SystemApi 2402 @RequiresPermission(anyOf = { 2403 android.Manifest.permission.NETWORK_SETTINGS, 2404 android.Manifest.permission.NETWORK_SETUP_WIZARD 2405 }) 2406 @NonNull getAllMatchingWifiConfigs( @onNull List<ScanResult> scanResults)2407 public List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> getAllMatchingWifiConfigs( 2408 @NonNull List<ScanResult> scanResults) { 2409 List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>(); 2410 try { 2411 Map<String, Map<Integer, List<ScanResult>>> results = 2412 mService.getAllMatchingPasspointProfilesForScanResults( 2413 new ParceledListSlice<>(scanResults)); 2414 if (results.isEmpty()) { 2415 return configs; 2416 } 2417 List<WifiConfiguration> wifiConfigurations = 2418 mService.getWifiConfigsForPasspointProfiles( 2419 new StringParceledListSlice(new ArrayList<>(results.keySet()))) 2420 .getList(); 2421 for (WifiConfiguration configuration : wifiConfigurations) { 2422 Map<Integer, List<ScanResult>> scanResultsPerNetworkType = 2423 results.get(configuration.getProfileKey()); 2424 if (scanResultsPerNetworkType != null) { 2425 configs.add(Pair.create(configuration, scanResultsPerNetworkType)); 2426 } 2427 } 2428 } catch (RemoteException e) { 2429 throw e.rethrowFromSystemServer(); 2430 } 2431 2432 return configs; 2433 } 2434 2435 /** 2436 * To be used with setScreenOnScanSchedule. 2437 * @hide 2438 */ 2439 @SystemApi 2440 public static class ScreenOnScanSchedule { 2441 private final Duration mScanInterval; 2442 private final int mScanType; 2443 2444 /** 2445 * Creates a ScreenOnScanSchedule. 2446 * @param scanInterval Interval between framework-initiated connectivity scans. 2447 * @param scanType One of the {@code WifiScanner.SCAN_TYPE_} values. 2448 */ ScreenOnScanSchedule(@onNull Duration scanInterval, @WifiAnnotations.ScanType int scanType)2449 public ScreenOnScanSchedule(@NonNull Duration scanInterval, 2450 @WifiAnnotations.ScanType int scanType) { 2451 if (scanInterval == null) { 2452 throw new IllegalArgumentException("scanInterval can't be null"); 2453 } 2454 mScanInterval = scanInterval; 2455 mScanType = scanType; 2456 } 2457 2458 /** 2459 * Gets the interval between framework-initiated connectivity scans. 2460 */ getScanInterval()2461 public @NonNull Duration getScanInterval() { 2462 return mScanInterval; 2463 } 2464 2465 /** 2466 * Gets the type of scan to be used. One of the {@code WifiScanner.SCAN_TYPE_} values. 2467 */ getScanType()2468 public @WifiAnnotations.ScanType int getScanType() { 2469 return mScanType; 2470 } 2471 } 2472 2473 /** 2474 * This API allows a privileged app to customize the wifi framework's network selection logic. 2475 * To revert to default behavior, call this API with a {@link WifiNetworkSelectionConfig} 2476 * created from a default {@link WifiNetworkSelectionConfig.Builder}. 2477 * 2478 * Use {@link WifiManager#getNetworkSelectionConfig(Executor, Consumer)} to get the current 2479 * network selection configuration. 2480 * <P> 2481 * @param nsConfig an Object representing the network selection configuration being programmed. 2482 * This should be created with a {@link WifiNetworkSelectionConfig.Builder}. 2483 * 2484 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2485 * @throws IllegalArgumentException if input is invalid. 2486 * @throws SecurityException if the caller does not have permission. 2487 * @hide 2488 */ 2489 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2490 @RequiresPermission(anyOf = { 2491 android.Manifest.permission.NETWORK_SETTINGS, 2492 MANAGE_WIFI_NETWORK_SELECTION 2493 }) 2494 @SystemApi setNetworkSelectionConfig(@onNull WifiNetworkSelectionConfig nsConfig)2495 public void setNetworkSelectionConfig(@NonNull WifiNetworkSelectionConfig nsConfig) { 2496 try { 2497 if (nsConfig == null) { 2498 throw new IllegalArgumentException("nsConfig can not be null"); 2499 } 2500 mService.setNetworkSelectionConfig(nsConfig); 2501 } catch (RemoteException e) { 2502 throw e.rethrowFromSystemServer(); 2503 } 2504 } 2505 2506 /** 2507 * This API allows a privileged app to retrieve the {@link WifiNetworkSelectionConfig} 2508 * currently being used by the network selector. 2509 * 2510 * Use {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)} to set a 2511 * new network selection configuration. 2512 * <P> 2513 * @param executor The executor on which callback will be invoked. 2514 * @param resultsCallback An asynchronous callback that will return 2515 * {@link WifiNetworkSelectionConfig} 2516 * 2517 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2518 * @throws SecurityException if the caller does not have permission. 2519 * @throws NullPointerException if the caller provided invalid inputs. 2520 * @hide 2521 */ 2522 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2523 @RequiresPermission(anyOf = { 2524 android.Manifest.permission.NETWORK_SETTINGS, 2525 MANAGE_WIFI_NETWORK_SELECTION 2526 }) 2527 @SystemApi getNetworkSelectionConfig(@onNull @allbackExecutor Executor executor, @NonNull Consumer<WifiNetworkSelectionConfig> resultsCallback)2528 public void getNetworkSelectionConfig(@NonNull @CallbackExecutor Executor executor, 2529 @NonNull Consumer<WifiNetworkSelectionConfig> resultsCallback) { 2530 Objects.requireNonNull(executor, "executor cannot be null"); 2531 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 2532 try { 2533 mService.getNetworkSelectionConfig( 2534 new IWifiNetworkSelectionConfigListener.Stub() { 2535 @Override 2536 public void onResult(WifiNetworkSelectionConfig value) { 2537 Binder.clearCallingIdentity(); 2538 executor.execute(() -> { 2539 resultsCallback.accept(value); 2540 }); 2541 } 2542 }); 2543 } catch (RemoteException e) { 2544 throw e.rethrowFromSystemServer(); 2545 } 2546 } 2547 2548 /** 2549 * Allows a privileged app to enable/disable whether a confirmation dialog should be displayed 2550 * when third-party apps attempt to turn on WiFi. 2551 * 2552 * Use {@link #isThirdPartyAppEnablingWifiConfirmationDialogEnabled()} to get the 2553 * currently configured value. 2554 * 2555 * Note: Only affects behavior for apps with targetSDK < Q, since third party apps are not 2556 * allowed to enable wifi on targetSDK >= Q. 2557 * 2558 * This overrides the overlay value |config_showConfirmationDialogForThirdPartyAppsEnablingWifi| 2559 * <P> 2560 * @param enable true to enable the confirmation dialog, false otherwise 2561 * 2562 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2563 * @throws SecurityException if the caller does not have permission. 2564 * @hide 2565 */ 2566 @RequiresPermission(anyOf = { 2567 android.Manifest.permission.NETWORK_SETTINGS, 2568 android.Manifest.permission.NETWORK_SETUP_WIZARD 2569 }) 2570 @SystemApi setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable)2571 public void setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable) { 2572 try { 2573 mService.setThirdPartyAppEnablingWifiConfirmationDialogEnabled(enable); 2574 } catch (RemoteException e) { 2575 throw e.rethrowFromSystemServer(); 2576 } 2577 } 2578 2579 /** 2580 * Check whether the wifi configuration indicates that a confirmation dialog should be displayed 2581 * when third-party apps attempt to turn on WiFi. 2582 * 2583 * Use {@link #setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} to set this 2584 * value. 2585 * 2586 * Note: This setting only affects behavior for apps with targetSDK < Q, since third party apps 2587 * are not allowed to enable wifi on targetSDK >= Q. 2588 * 2589 * <P> 2590 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2591 * @throws SecurityException if the caller does not have permission. 2592 * @return true if dialog should be displayed, false otherwise. 2593 * @hide 2594 */ 2595 @RequiresPermission(anyOf = { 2596 android.Manifest.permission.NETWORK_SETTINGS, 2597 android.Manifest.permission.NETWORK_SETUP_WIZARD 2598 }) 2599 @SystemApi isThirdPartyAppEnablingWifiConfirmationDialogEnabled()2600 public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled() { 2601 try { 2602 return mService.isThirdPartyAppEnablingWifiConfirmationDialogEnabled(); 2603 } catch (RemoteException e) { 2604 throw e.rethrowFromSystemServer(); 2605 } 2606 } 2607 2608 /** 2609 * Allows a privileged app to customize the screen-on scan behavior. When a non-null schedule 2610 * is set via this API, it will always get used instead of the scan schedules defined in the 2611 * overlay. When a null schedule is set via this API, the wifi subsystem will go back to using 2612 * the scan schedules defined in the overlay. Also note, the scan schedule will be truncated 2613 * (rounded down) to the nearest whole second. 2614 * <p> 2615 * Example usage: 2616 * The following call specifies that first scheduled scan should be in 20 seconds using 2617 * {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}, and all 2618 * scheduled scans later should happen every 40 seconds using 2619 * {@link WifiScanner#SCAN_TYPE_LOW_POWER}. 2620 * <pre> 2621 * List<ScreenOnScanSchedule> schedule = new ArrayList<>(); 2622 * schedule.add(new ScreenOnScanSchedule(Duration.ofSeconds(20), 2623 * WifiScanner.SCAN_TYPE_HIGH_ACCURACY)); 2624 * schedule.add(new ScreenOnScanSchedule(Duration.ofSeconds(40), 2625 * WifiScanner.SCAN_TYPE_LOW_POWER)); 2626 * wifiManager.setScreenOnScanSchedule(schedule); 2627 * </pre> 2628 * @param screenOnScanSchedule defines the screen-on scan schedule and the corresponding 2629 * scan type. Set to null to clear any previously set value. 2630 * 2631 * @throws IllegalStateException if input is invalid 2632 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2633 * @throws SecurityException if the caller does not have permission. 2634 * @hide 2635 */ 2636 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2637 @RequiresPermission(anyOf = { 2638 android.Manifest.permission.NETWORK_SETTINGS, 2639 MANAGE_WIFI_NETWORK_SELECTION 2640 }) 2641 @SystemApi setScreenOnScanSchedule(@ullable List<ScreenOnScanSchedule> screenOnScanSchedule)2642 public void setScreenOnScanSchedule(@Nullable List<ScreenOnScanSchedule> screenOnScanSchedule) { 2643 try { 2644 if (screenOnScanSchedule == null) { 2645 mService.setScreenOnScanSchedule(null, null); 2646 return; 2647 } 2648 if (screenOnScanSchedule.isEmpty()) { 2649 throw new IllegalArgumentException("The input should either be null or a non-empty" 2650 + " list"); 2651 } 2652 int[] scanSchedule = new int[screenOnScanSchedule.size()]; 2653 int[] scanType = new int[screenOnScanSchedule.size()]; 2654 for (int i = 0; i < screenOnScanSchedule.size(); i++) { 2655 scanSchedule[i] = (int) screenOnScanSchedule.get(i).getScanInterval().toSeconds(); 2656 scanType[i] = screenOnScanSchedule.get(i).getScanType(); 2657 } 2658 mService.setScreenOnScanSchedule(scanSchedule, scanType); 2659 } catch (RemoteException e) { 2660 throw e.rethrowFromSystemServer(); 2661 } 2662 } 2663 2664 /** 2665 * The Wi-Fi framework may trigger connectivity scans in response to the screen turning on for 2666 * network selection purposes. This API allows a privileged app to set a delay to the next 2667 * connectivity scan triggered by the Wi-Fi framework in response to the next screen-on event. 2668 * This gives a window for the privileged app to issue their own custom scans to influence Wi-Fi 2669 * network selection. The expected usage is the privileged app monitor for the screen turning 2670 * off, and then call this API if it believes delaying the next screen-on connectivity scan is 2671 * needed. 2672 * <p> 2673 * Note that this API will only delay screen-on connectivity scans once. This API will need to 2674 * be called again if further screen-on scan delays are needed after it resolves. 2675 * @param delayMs defines the time in milliseconds to delay the next screen-on connectivity 2676 * scan. Setting this to 0 will remove the delay. 2677 * 2678 * @throws IllegalStateException if input is invalid 2679 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2680 * @throws SecurityException if the caller does not have permission. 2681 * @hide 2682 */ 2683 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2684 @RequiresPermission(anyOf = { 2685 android.Manifest.permission.NETWORK_SETTINGS, 2686 MANAGE_WIFI_NETWORK_SELECTION 2687 }) 2688 @SystemApi setOneShotScreenOnConnectivityScanDelayMillis(@ntRangefrom = 0) int delayMs)2689 public void setOneShotScreenOnConnectivityScanDelayMillis(@IntRange(from = 0) int delayMs) { 2690 try { 2691 mService.setOneShotScreenOnConnectivityScanDelayMillis(delayMs); 2692 } catch (RemoteException e) { 2693 throw e.rethrowFromSystemServer(); 2694 } 2695 } 2696 2697 /** 2698 * Retrieve a list of {@link WifiConfiguration} for available {@link WifiNetworkSuggestion} 2699 * matching the given list of {@link ScanResult}. 2700 * 2701 * An available {@link WifiNetworkSuggestion} must satisfy: 2702 * <ul> 2703 * <li> Matching one of the {@link ScanResult} from the given list. 2704 * <li> and {@link WifiNetworkSuggestion.Builder#setIsUserAllowedToManuallyConnect(boolean)} set 2705 * to true. 2706 * </ul> 2707 * 2708 * @param scanResults a list of scanResult. 2709 * @return a list of @link WifiConfiguration} for available {@link WifiNetworkSuggestion} 2710 * @hide 2711 */ 2712 @SystemApi 2713 @RequiresPermission(anyOf = { 2714 android.Manifest.permission.NETWORK_SETTINGS, 2715 android.Manifest.permission.NETWORK_SETUP_WIZARD 2716 }) 2717 @NonNull getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( @onNull List<ScanResult> scanResults)2718 public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( 2719 @NonNull List<ScanResult> scanResults) { 2720 try { 2721 return mService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( 2722 new ParceledListSlice<>(scanResults)).getList(); 2723 } catch (RemoteException e) { 2724 throw e.rethrowAsRuntimeException(); 2725 } 2726 } 2727 2728 /** 2729 * Specify a set of SSIDs that will not get disabled internally by the Wi-Fi subsystem when 2730 * connection issues occur. To clear the list, call this API with an empty Set. 2731 * <p> 2732 * {@link #getSsidsAllowlist()} can be used to check the SSIDs that have been set. 2733 * @param ssids - list of WifiSsid that will not get disabled internally 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 * @throws IllegalArgumentException if the input is null. 2738 * @hide 2739 */ 2740 @SystemApi 2741 @RequiresPermission(anyOf = { 2742 android.Manifest.permission.NETWORK_SETTINGS, 2743 android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional = true) setSsidsAllowlist(@onNull Set<WifiSsid> ssids)2744 public void setSsidsAllowlist(@NonNull Set<WifiSsid> ssids) { 2745 if (ssids == null) { 2746 throw new IllegalArgumentException(TAG + ": ssids can not be null"); 2747 } 2748 try { 2749 mService.setSsidsAllowlist(mContext.getOpPackageName(), 2750 new ParceledListSlice<>(new ArrayList<>(ssids))); 2751 } catch (RemoteException e) { 2752 throw e.rethrowFromSystemServer(); 2753 } 2754 } 2755 2756 /** 2757 * Get the Set of SSIDs that will not get disabled internally by the Wi-Fi subsystem when 2758 * connection issues occur. 2759 * @throws SecurityException if the calling app is not a Device Owner (DO), Profile Owner (PO), 2760 * or a privileged app that has one of the permissions required by 2761 * this API. 2762 * @hide 2763 */ 2764 @SystemApi 2765 @RequiresPermission(anyOf = { 2766 android.Manifest.permission.NETWORK_SETTINGS, 2767 android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional = true) getSsidsAllowlist()2768 public @NonNull Set<WifiSsid> getSsidsAllowlist() { 2769 try { 2770 return new ArraySet<WifiSsid>( 2771 mService.getSsidsAllowlist(mContext.getOpPackageName()).getList()); 2772 } catch (RemoteException e) { 2773 throw e.rethrowFromSystemServer(); 2774 } 2775 } 2776 2777 /** 2778 * Returns a list of unique Hotspot 2.0 OSU (Online Sign-Up) providers associated with a given 2779 * list of ScanResult. 2780 * 2781 * An empty list will be returned if no match is found. 2782 * 2783 * @param scanResults a list of ScanResult 2784 * @return Map that consists {@link OsuProvider} and a list of matching {@link ScanResult} 2785 * @hide 2786 */ 2787 @SystemApi 2788 @RequiresPermission(anyOf = { 2789 android.Manifest.permission.NETWORK_SETTINGS, 2790 android.Manifest.permission.NETWORK_SETUP_WIZARD 2791 }) 2792 @NonNull getMatchingOsuProviders( @ullable List<ScanResult> scanResults)2793 public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( 2794 @Nullable List<ScanResult> scanResults) { 2795 if (scanResults == null) { 2796 return new HashMap<>(); 2797 } 2798 try { 2799 return mService.getMatchingOsuProviders(new ParceledListSlice<>(scanResults)); 2800 } catch (RemoteException e) { 2801 throw e.rethrowFromSystemServer(); 2802 } 2803 } 2804 2805 /** 2806 * Returns the matching Passpoint R2 configurations for given OSU (Online Sign-Up) providers. 2807 * 2808 * Given a list of OSU providers, this only returns OSU providers that already have Passpoint R2 2809 * configurations in the device. 2810 * An empty map will be returned when there is no matching Passpoint R2 configuration for the 2811 * given OsuProviders. 2812 * 2813 * @param osuProviders a set of {@link OsuProvider} 2814 * @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}. 2815 * @hide 2816 */ 2817 @SystemApi 2818 @RequiresPermission(anyOf = { 2819 android.Manifest.permission.NETWORK_SETTINGS, 2820 android.Manifest.permission.NETWORK_SETUP_WIZARD 2821 }) 2822 @NonNull getMatchingPasspointConfigsForOsuProviders( @onNull Set<OsuProvider> osuProviders)2823 public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( 2824 @NonNull Set<OsuProvider> osuProviders) { 2825 try { 2826 return mService.getMatchingPasspointConfigsForOsuProviders( 2827 new ParceledListSlice<>(new ArrayList<>(osuProviders))); 2828 } catch (RemoteException e) { 2829 throw e.rethrowFromSystemServer(); 2830 } 2831 } 2832 2833 /** 2834 * Add a new network description to the set of configured networks. 2835 * The {@code networkId} field of the supplied configuration object 2836 * is ignored. 2837 * <p/> 2838 * The new network will be marked DISABLED by default. To enable it, 2839 * called {@link #enableNetwork}. 2840 * 2841 * @param config the set of variables that describe the configuration, 2842 * contained in a {@link WifiConfiguration} object. 2843 * If the {@link WifiConfiguration} has an Http Proxy set 2844 * the calling app must be System, or be provisioned as the Profile or Device Owner. 2845 * @return the ID of the newly created network description. This is used in 2846 * other operations to specified the network to be acted upon. 2847 * Returns {@code -1} on failure. 2848 * 2849 * @deprecated 2850 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2851 * mechanism to trigger connection to a Wi-Fi network. 2852 * b) See {@link #addNetworkSuggestions(List)}, 2853 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2854 * when auto-connecting to wifi. 2855 * <b>Compatibility Note:</b> For applications targeting 2856 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 2857 * {@code -1}. 2858 * <p> 2859 * Deprecation Exemptions: 2860 * <ul> 2861 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2862 * </ul> 2863 */ 2864 @Deprecated addNetwork(WifiConfiguration config)2865 public int addNetwork(WifiConfiguration config) { 2866 if (config == null) { 2867 return -1; 2868 } 2869 config.networkId = -1; 2870 return addOrUpdateNetwork(config); 2871 } 2872 2873 /** 2874 * This is a new version of {@link #addNetwork(WifiConfiguration)} which returns more detailed 2875 * failure codes. The usage of this API is limited to Device Owner (DO), Profile Owner (PO), 2876 * system app, and privileged apps. 2877 * <p> 2878 * Add a new network description to the set of configured networks. The {@code networkId} 2879 * field of the supplied configuration object is ignored. The new network will be marked 2880 * DISABLED by default. To enable it, call {@link #enableNetwork}. 2881 * <p> 2882 * @param config the set of variables that describe the configuration, 2883 * contained in a {@link WifiConfiguration} object. 2884 * If the {@link WifiConfiguration} has an Http Proxy set 2885 * the calling app must be System, or be provisioned as the Profile or Device Owner. 2886 * @return A {@link AddNetworkResult} Object. 2887 * @throws SecurityException if the calling app is not a Device Owner (DO), 2888 * Profile Owner (PO), system app, or a privileged app that has one of 2889 * the permissions required by this API. 2890 * @throws IllegalArgumentException if the input configuration is null or if the 2891 * security type in input configuration is not supported. 2892 */ 2893 @RequiresPermission(anyOf = { 2894 android.Manifest.permission.NETWORK_SETTINGS, 2895 android.Manifest.permission.NETWORK_STACK, 2896 android.Manifest.permission.NETWORK_SETUP_WIZARD, 2897 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING 2898 }, conditional = true) 2899 @NonNull addNetworkPrivileged(@onNull WifiConfiguration config)2900 public AddNetworkResult addNetworkPrivileged(@NonNull WifiConfiguration config) { 2901 if (config == null) throw new IllegalArgumentException("config cannot be null"); 2902 if (config.isSecurityType(WifiInfo.SECURITY_TYPE_DPP) 2903 && !isFeatureSupported(WIFI_FEATURE_DPP_AKM)) { 2904 throw new IllegalArgumentException("dpp akm is not supported"); 2905 } 2906 config.networkId = -1; 2907 try { 2908 return mService.addOrUpdateNetworkPrivileged(config, mContext.getOpPackageName()); 2909 } catch (RemoteException e) { 2910 throw e.rethrowFromSystemServer(); 2911 } 2912 } 2913 2914 /** 2915 * Provides the results of a call to {@link #addNetworkPrivileged(WifiConfiguration)} 2916 */ 2917 public static final class AddNetworkResult implements Parcelable { 2918 /** 2919 * The operation has completed successfully. 2920 */ 2921 public static final int STATUS_SUCCESS = 0; 2922 /** 2923 * The operation has failed due to an unknown reason. 2924 */ 2925 public static final int STATUS_FAILURE_UNKNOWN = 1; 2926 /** 2927 * The calling app does not have permission to call this API. 2928 */ 2929 public static final int STATUS_NO_PERMISSION = 2; 2930 /** 2931 * Generic failure code for adding a passpoint network. 2932 */ 2933 public static final int STATUS_ADD_PASSPOINT_FAILURE = 3; 2934 /** 2935 * Generic failure code for adding a non-passpoint network. 2936 */ 2937 public static final int STATUS_ADD_WIFI_CONFIG_FAILURE = 4; 2938 /** 2939 * The network configuration is invalid. 2940 */ 2941 public static final int STATUS_INVALID_CONFIGURATION = 5; 2942 /** 2943 * The calling app has no permission to modify the configuration. 2944 */ 2945 public static final int STATUS_NO_PERMISSION_MODIFY_CONFIG = 6; 2946 /** 2947 * The calling app has no permission to modify the proxy setting. 2948 */ 2949 public static final int STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING = 7; 2950 /** 2951 * The calling app has no permission to modify the MAC randomization setting. 2952 */ 2953 public static final int STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION = 8; 2954 /** 2955 * Internal failure in updating network keys.. 2956 */ 2957 public static final int STATUS_FAILURE_UPDATE_NETWORK_KEYS = 9; 2958 /** 2959 * The enterprise network is missing either the root CA or domain name. 2960 */ 2961 public static final int STATUS_INVALID_CONFIGURATION_ENTERPRISE = 10; 2962 2963 /** @hide */ 2964 @IntDef(prefix = { "STATUS_" }, value = { 2965 STATUS_SUCCESS, 2966 STATUS_FAILURE_UNKNOWN, 2967 STATUS_NO_PERMISSION, 2968 STATUS_ADD_PASSPOINT_FAILURE, 2969 STATUS_ADD_WIFI_CONFIG_FAILURE, 2970 STATUS_INVALID_CONFIGURATION, 2971 STATUS_NO_PERMISSION_MODIFY_CONFIG, 2972 STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING, 2973 STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION, 2974 STATUS_FAILURE_UPDATE_NETWORK_KEYS, 2975 STATUS_INVALID_CONFIGURATION_ENTERPRISE, 2976 }) 2977 @Retention(RetentionPolicy.SOURCE) 2978 public @interface AddNetworkStatusCode {} 2979 2980 @Override describeContents()2981 public int describeContents() { 2982 return 0; 2983 } 2984 2985 @Override writeToParcel(@onNull Parcel dest, int flags)2986 public void writeToParcel(@NonNull Parcel dest, int flags) { 2987 dest.writeInt(statusCode); 2988 dest.writeInt(networkId); 2989 } 2990 2991 /** Implement the Parcelable interface */ 2992 public static final @android.annotation.NonNull Creator<AddNetworkResult> CREATOR = 2993 new Creator<AddNetworkResult>() { 2994 public AddNetworkResult createFromParcel(Parcel in) { 2995 return new AddNetworkResult(in.readInt(), in.readInt()); 2996 } 2997 2998 public AddNetworkResult[] newArray(int size) { 2999 return new AddNetworkResult[size]; 3000 } 3001 }; 3002 3003 /** 3004 * One of the {@code STATUS_} values. If the operation is successful this field 3005 * will be set to {@code STATUS_SUCCESS}. 3006 */ 3007 public final @AddNetworkStatusCode int statusCode; 3008 /** 3009 * The identifier of the added network, which could be used in other operations. This field 3010 * will be set to {@code -1} if the operation failed. 3011 */ 3012 public final int networkId; 3013 AddNetworkResult(@ddNetworkStatusCode int statusCode, int networkId)3014 public AddNetworkResult(@AddNetworkStatusCode int statusCode, int networkId) { 3015 this.statusCode = statusCode; 3016 this.networkId = networkId; 3017 } 3018 } 3019 3020 /** 3021 * Update the network description of an existing configured network. 3022 * 3023 * @param config the set of variables that describe the configuration, 3024 * contained in a {@link WifiConfiguration} object. It may 3025 * be sparse, so that only the items that are being changed 3026 * are non-<code>null</code>. The {@code networkId} field 3027 * must be set to the ID of the existing network being updated. 3028 * If the {@link WifiConfiguration} has an Http Proxy set 3029 * the calling app must be System, or be provisioned as the Profile or Device Owner. 3030 * @return Returns the {@code networkId} of the supplied 3031 * {@code WifiConfiguration} on success. 3032 * <br/> 3033 * Returns {@code -1} on failure, including when the {@code networkId} 3034 * field of the {@code WifiConfiguration} does not refer to an 3035 * existing network. 3036 * 3037 * @deprecated 3038 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3039 * mechanism to trigger connection to a Wi-Fi network. 3040 * b) See {@link #addNetworkSuggestions(List)}, 3041 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3042 * when auto-connecting to wifi. 3043 * <b>Compatibility Note:</b> For applications targeting 3044 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3045 * {@code -1}. 3046 * <p> 3047 * Deprecation Exemptions: 3048 * <ul> 3049 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3050 * </ul> 3051 */ 3052 @Deprecated updateNetwork(WifiConfiguration config)3053 public int updateNetwork(WifiConfiguration config) { 3054 if (config == null || config.networkId < 0) { 3055 return -1; 3056 } 3057 return addOrUpdateNetwork(config); 3058 } 3059 3060 /** 3061 * Internal method for doing the RPC that creates a new network description 3062 * or updates an existing one. 3063 * 3064 * @param config The possibly sparse object containing the variables that 3065 * are to set or updated in the network description. 3066 * @return the ID of the network on success, {@code -1} on failure. 3067 */ addOrUpdateNetwork(WifiConfiguration config)3068 private int addOrUpdateNetwork(WifiConfiguration config) { 3069 Bundle extras = new Bundle(); 3070 if (SdkLevel.isAtLeastS()) { 3071 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 3072 mContext.getAttributionSource()); 3073 } 3074 3075 try { 3076 return mService.addOrUpdateNetwork(config, mContext.getOpPackageName(), extras); 3077 } catch (RemoteException e) { 3078 throw e.rethrowFromSystemServer(); 3079 } 3080 } 3081 3082 /** 3083 * Interface for indicating user selection from the list of networks presented in the 3084 * {@link NetworkRequestMatchCallback#onMatch(List)}. 3085 * 3086 * The platform will implement this callback and pass it along with the 3087 * {@link NetworkRequestMatchCallback#onUserSelectionCallbackRegistration( 3088 * NetworkRequestUserSelectionCallback)}. The UI component handling 3089 * {@link NetworkRequestMatchCallback} will invoke {@link #select(WifiConfiguration)} or 3090 * {@link #reject()} to return the user's selection back to the platform via this callback. 3091 * @hide 3092 */ 3093 @SystemApi 3094 public interface NetworkRequestUserSelectionCallback { 3095 /** 3096 * User selected this network to connect to. 3097 * @param wifiConfiguration WifiConfiguration object corresponding to the network 3098 * user selected. 3099 */ 3100 @SuppressLint("CallbackMethodName") select(@onNull WifiConfiguration wifiConfiguration)3101 default void select(@NonNull WifiConfiguration wifiConfiguration) {} 3102 3103 /** 3104 * User rejected the app's request. 3105 */ 3106 @SuppressLint("CallbackMethodName") reject()3107 default void reject() {} 3108 } 3109 3110 /** 3111 * Interface for network request callback. Should be implemented by applications and passed when 3112 * calling {@link #registerNetworkRequestMatchCallback(Executor, 3113 * WifiManager.NetworkRequestMatchCallback)}. 3114 * 3115 * This is meant to be implemented by a UI component to present the user with a list of networks 3116 * matching the app's request. The user is allowed to pick one of these networks to connect to 3117 * or reject the request by the app. 3118 * @hide 3119 */ 3120 @SystemApi 3121 public interface NetworkRequestMatchCallback { 3122 /** 3123 * Invoked to register a callback to be invoked to convey user selection. The callback 3124 * object passed in this method is to be invoked by the UI component after the service sends 3125 * a list of matching scan networks using {@link #onMatch(List)} and user picks a network 3126 * from that list. 3127 * 3128 * @param userSelectionCallback Callback object to send back the user selection. 3129 */ onUserSelectionCallbackRegistration( @onNull NetworkRequestUserSelectionCallback userSelectionCallback)3130 default void onUserSelectionCallbackRegistration( 3131 @NonNull NetworkRequestUserSelectionCallback userSelectionCallback) {} 3132 3133 /** 3134 * Invoked when the active network request is aborted, either because 3135 * <li> The app released the request, OR</li> 3136 * <li> Request was overridden by a new request</li> 3137 * This signals the end of processing for the current request and should stop the UI 3138 * component. No subsequent calls from the UI component will be handled by the platform. 3139 */ onAbort()3140 default void onAbort() {} 3141 3142 /** 3143 * Invoked when a network request initiated by an app matches some networks in scan results. 3144 * This may be invoked multiple times for a single network request as the platform finds new 3145 * matching networks in scan results. 3146 * 3147 * @param scanResults List of {@link ScanResult} objects corresponding to the networks 3148 * matching the request. 3149 */ onMatch(@onNull List<ScanResult> scanResults)3150 default void onMatch(@NonNull List<ScanResult> scanResults) {} 3151 3152 /** 3153 * Invoked on a successful connection with the network that the user selected 3154 * via {@link NetworkRequestUserSelectionCallback}. 3155 * 3156 * @param wifiConfiguration WifiConfiguration object corresponding to the network that the 3157 * user selected. 3158 */ onUserSelectionConnectSuccess(@onNull WifiConfiguration wifiConfiguration)3159 default void onUserSelectionConnectSuccess(@NonNull WifiConfiguration wifiConfiguration) {} 3160 3161 /** 3162 * Invoked on failure to establish connection with the network that the user selected 3163 * via {@link NetworkRequestUserSelectionCallback}. 3164 * 3165 * @param wifiConfiguration WifiConfiguration object corresponding to the network 3166 * user selected. 3167 */ onUserSelectionConnectFailure(@onNull WifiConfiguration wifiConfiguration)3168 default void onUserSelectionConnectFailure(@NonNull WifiConfiguration wifiConfiguration) {} 3169 } 3170 3171 /** 3172 * Callback proxy for NetworkRequestUserSelectionCallback objects. 3173 * @hide 3174 */ 3175 private class NetworkRequestUserSelectionCallbackProxy implements 3176 NetworkRequestUserSelectionCallback { 3177 private final INetworkRequestUserSelectionCallback mCallback; 3178 NetworkRequestUserSelectionCallbackProxy( INetworkRequestUserSelectionCallback callback)3179 NetworkRequestUserSelectionCallbackProxy( 3180 INetworkRequestUserSelectionCallback callback) { 3181 mCallback = callback; 3182 } 3183 3184 @Override select(@onNull WifiConfiguration wifiConfiguration)3185 public void select(@NonNull WifiConfiguration wifiConfiguration) { 3186 if (mVerboseLoggingEnabled) { 3187 Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: select " 3188 + "wificonfiguration: " + wifiConfiguration); 3189 } 3190 try { 3191 mCallback.select(wifiConfiguration); 3192 } catch (RemoteException e) { 3193 Log.e(TAG, "Failed to invoke onSelected", e); 3194 throw e.rethrowFromSystemServer(); 3195 } 3196 } 3197 3198 @Override reject()3199 public void reject() { 3200 if (mVerboseLoggingEnabled) { 3201 Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: reject"); 3202 } 3203 try { 3204 mCallback.reject(); 3205 } catch (RemoteException e) { 3206 Log.e(TAG, "Failed to invoke onRejected", e); 3207 throw e.rethrowFromSystemServer(); 3208 } 3209 } 3210 } 3211 3212 /** 3213 * Callback proxy for NetworkRequestMatchCallback objects. 3214 * @hide 3215 */ 3216 private class NetworkRequestMatchCallbackProxy extends INetworkRequestMatchCallback.Stub { 3217 private final Executor mExecutor; 3218 private final NetworkRequestMatchCallback mCallback; 3219 NetworkRequestMatchCallbackProxy(Executor executor, NetworkRequestMatchCallback callback)3220 NetworkRequestMatchCallbackProxy(Executor executor, NetworkRequestMatchCallback callback) { 3221 mExecutor = executor; 3222 mCallback = callback; 3223 } 3224 3225 @Override onUserSelectionCallbackRegistration( INetworkRequestUserSelectionCallback userSelectionCallback)3226 public void onUserSelectionCallbackRegistration( 3227 INetworkRequestUserSelectionCallback userSelectionCallback) { 3228 if (mVerboseLoggingEnabled) { 3229 Log.v(TAG, "NetworkRequestMatchCallbackProxy: " 3230 + "onUserSelectionCallbackRegistration callback: " + userSelectionCallback); 3231 } 3232 Binder.clearCallingIdentity(); 3233 mExecutor.execute(() -> { 3234 mCallback.onUserSelectionCallbackRegistration( 3235 new NetworkRequestUserSelectionCallbackProxy(userSelectionCallback)); 3236 }); 3237 } 3238 3239 @Override onAbort()3240 public void onAbort() { 3241 if (mVerboseLoggingEnabled) { 3242 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onAbort"); 3243 } 3244 Binder.clearCallingIdentity(); 3245 mExecutor.execute(() -> { 3246 mCallback.onAbort(); 3247 }); 3248 } 3249 3250 @Override onMatch(List<ScanResult> scanResults)3251 public void onMatch(List<ScanResult> scanResults) { 3252 if (mVerboseLoggingEnabled) { 3253 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onMatch scanResults: " 3254 + scanResults); 3255 } 3256 Binder.clearCallingIdentity(); 3257 mExecutor.execute(() -> { 3258 mCallback.onMatch(scanResults); 3259 }); 3260 } 3261 3262 @Override onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration)3263 public void onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration) { 3264 if (mVerboseLoggingEnabled) { 3265 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectSuccess " 3266 + " wificonfiguration: " + wifiConfiguration); 3267 } 3268 Binder.clearCallingIdentity(); 3269 mExecutor.execute(() -> { 3270 mCallback.onUserSelectionConnectSuccess(wifiConfiguration); 3271 }); 3272 } 3273 3274 @Override onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration)3275 public void onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration) { 3276 if (mVerboseLoggingEnabled) { 3277 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectFailure" 3278 + " wificonfiguration: " + wifiConfiguration); 3279 } 3280 Binder.clearCallingIdentity(); 3281 mExecutor.execute(() -> { 3282 mCallback.onUserSelectionConnectFailure(wifiConfiguration); 3283 }); 3284 } 3285 } 3286 3287 /** 3288 * Registers a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. 3289 * Caller can unregister a previously registered callback using 3290 * {@link #unregisterNetworkRequestMatchCallback(NetworkRequestMatchCallback)} 3291 * <p> 3292 * Applications should have the 3293 * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers 3294 * without the permission will trigger a {@link java.lang.SecurityException}. 3295 * <p> 3296 * 3297 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 3298 * object. 3299 * @param callback Callback for network match events to register. 3300 * @hide 3301 */ 3302 @SystemApi 3303 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) registerNetworkRequestMatchCallback(@onNull @allbackExecutor Executor executor, @NonNull NetworkRequestMatchCallback callback)3304 public void registerNetworkRequestMatchCallback(@NonNull @CallbackExecutor Executor executor, 3305 @NonNull NetworkRequestMatchCallback callback) { 3306 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 3307 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 3308 Log.v(TAG, "registerNetworkRequestMatchCallback: callback=" + callback 3309 + ", executor=" + executor); 3310 3311 try { 3312 synchronized (sNetworkRequestMatchCallbackMap) { 3313 INetworkRequestMatchCallback.Stub binderCallback = 3314 new NetworkRequestMatchCallbackProxy(executor, callback); 3315 sNetworkRequestMatchCallbackMap.put(System.identityHashCode(callback), 3316 binderCallback); 3317 mService.registerNetworkRequestMatchCallback(binderCallback); 3318 } 3319 } catch (RemoteException e) { 3320 throw e.rethrowFromSystemServer(); 3321 } 3322 } 3323 3324 /** 3325 * Unregisters a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. 3326 * <p> 3327 * Applications should have the 3328 * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers 3329 * without the permission will trigger a {@link java.lang.SecurityException}. 3330 * <p> 3331 * 3332 * @param callback Callback for network match events to unregister. 3333 * @hide 3334 */ 3335 @SystemApi 3336 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) unregisterNetworkRequestMatchCallback( @onNull NetworkRequestMatchCallback callback)3337 public void unregisterNetworkRequestMatchCallback( 3338 @NonNull NetworkRequestMatchCallback callback) { 3339 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 3340 Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback); 3341 3342 try { 3343 synchronized (sNetworkRequestMatchCallbackMap) { 3344 int callbackIdentifier = System.identityHashCode(callback); 3345 if (!sNetworkRequestMatchCallbackMap.contains(callbackIdentifier)) { 3346 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 3347 return; 3348 } 3349 mService.unregisterNetworkRequestMatchCallback( 3350 sNetworkRequestMatchCallbackMap.get(callbackIdentifier)); 3351 sNetworkRequestMatchCallbackMap.remove(callbackIdentifier); 3352 } 3353 } catch (RemoteException e) { 3354 throw e.rethrowFromSystemServer(); 3355 } 3356 } 3357 3358 /** 3359 * Privileged API to revoke all app state from wifi stack (equivalent to operations that the 3360 * wifi stack performs to clear state for an app that was uninstalled. 3361 * This removes: 3362 * <li> All saved networks or passpoint profiles added by the app </li> 3363 * <li> All previously approved peer to peer connection to access points initiated by the app 3364 * using {@link WifiNetworkSpecifier}</li> 3365 * <li> All network suggestions and approvals provided using {@link WifiNetworkSuggestion}</li> 3366 * <p> 3367 * @param targetAppUid UID of the app. 3368 * @param targetAppPackageName Package name of the app. 3369 * @hide 3370 */ 3371 @SystemApi 3372 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) removeAppState(int targetAppUid, @NonNull String targetAppPackageName)3373 public void removeAppState(int targetAppUid, @NonNull String targetAppPackageName) { 3374 try { 3375 mService.removeAppState(targetAppUid, targetAppPackageName); 3376 } catch (RemoteException e) { 3377 throw e.rethrowAsRuntimeException(); 3378 } 3379 } 3380 3381 /** 3382 * Provide a list of network suggestions to the device. See {@link WifiNetworkSuggestion} 3383 * for a detailed explanation of the parameters. 3384 * When the device decides to connect to one of the provided network suggestions, platform sends 3385 * a directed broadcast {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} to the app if 3386 * the network was created with 3387 * {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired(boolean)} flag set and the 3388 * app holds {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} 3389 * permission. 3390 *<p> 3391 * NOTE: 3392 * <ul> 3393 * <li> These networks are just a suggestion to the platform. The platform will ultimately 3394 * decide on which network the device connects to. </li> 3395 * <li> When an app is uninstalled or disabled, all its suggested networks are discarded. 3396 * If the device is currently connected to a suggested network which is being removed then the 3397 * device will disconnect from that network.</li> 3398 * <li> If user reset network settings, all added suggestions will be discarded. Apps can use 3399 * {@link #getNetworkSuggestions()} to check if their suggestions are in the device.</li> 3400 * <li> In-place modification of existing suggestions are allowed.</li> 3401 * <ul> 3402 * <li> If the provided suggestions include any previously provided suggestions by the app, 3403 * previous suggestions will be updated.</li> 3404 * <li>If one of the provided suggestions marks a previously unmetered suggestion as metered and 3405 * the device is currently connected to that suggested network, then the device will disconnect 3406 * from that network. The system will immediately re-evaluate all the network candidates 3407 * and possibly reconnect back to the same suggestion. This disconnect is to make sure that any 3408 * traffic flowing over unmetered networks isn't accidentally continued over a metered network. 3409 * </li> 3410 * <li> 3411 * On {@link android.os.Build.VERSION_CODES#TIRAMISU} or above If one of the provided 3412 * suggestions marks a previously trusted suggestion as untrusted and the device is currently 3413 * connected to that suggested network, then the device will disconnect from that network. The 3414 * system will immediately re-evaluate all the network candidates. This disconnect is to make 3415 * sure device will not remain connected to an untrusted network without a related 3416 * {@link android.net.NetworkRequest}. 3417 * </li> 3418 * </ul> 3419 * </ul> 3420 * 3421 * @param networkSuggestions List of network suggestions provided by the app. 3422 * @return Status code for the operation. One of the STATUS_NETWORK_SUGGESTIONS_ values. 3423 * @throws SecurityException if the caller is missing required permissions. 3424 * @see WifiNetworkSuggestion#equals(Object) 3425 */ 3426 @RequiresPermission(CHANGE_WIFI_STATE) addNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions)3427 public @NetworkSuggestionsStatusCode int addNetworkSuggestions( 3428 @NonNull List<WifiNetworkSuggestion> networkSuggestions) { 3429 try { 3430 return mService.addNetworkSuggestions(new ParceledListSlice<>(networkSuggestions), 3431 mContext.getOpPackageName(), mContext.getAttributionTag()); 3432 } catch (RemoteException e) { 3433 throw e.rethrowFromSystemServer(); 3434 } 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 device will immediately disconnect from that network. This method is same 3441 * as {@link #removeNetworkSuggestions(List, int)} with 3442 * {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT} 3443 * 3444 * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters. 3445 * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used. 3446 * <p></ 3447 * Note: Use {@link #removeNetworkSuggestions(List, int)}. An {@code action} of 3448 * {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT} is equivalent to the current behavior. 3449 * 3450 * @param networkSuggestions List of network suggestions to be removed. Pass an empty list 3451 * to remove all the previous suggestions provided by the app. 3452 * @return Status code for the operation. One of the {@code STATUS_NETWORK_SUGGESTIONS_*} 3453 * values. Any matching suggestions are removed from the device and will not be considered for 3454 * any further connection attempts. 3455 */ 3456 @RequiresPermission(CHANGE_WIFI_STATE) removeNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions)3457 public @NetworkSuggestionsStatusCode int removeNetworkSuggestions( 3458 @NonNull List<WifiNetworkSuggestion> networkSuggestions) { 3459 return removeNetworkSuggestions(networkSuggestions, ACTION_REMOVE_SUGGESTION_DISCONNECT); 3460 } 3461 3462 /** 3463 * Remove some or all of the network suggestions that were previously provided by the app. 3464 * If one of the suggestions being removed was used to establish connection to the current 3465 * network, then the specified action will be executed. 3466 * 3467 * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters. 3468 * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used. 3469 * 3470 * @param networkSuggestions List of network suggestions to be removed. Pass an empty list 3471 * to remove all the previous suggestions provided by the app. 3472 * @param action Desired action to execute after removing the suggestion. One of 3473 * {@code ACTION_REMOVE_SUGGESTION_*} 3474 * @return Status code for the operation. One of the {@code STATUS_NETWORK_SUGGESTIONS_*} 3475 * values. Any matching suggestions are removed from the device and will not be considered for 3476 * further connection attempts. 3477 */ 3478 @RequiresPermission(CHANGE_WIFI_STATE) removeNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions, @ActionAfterRemovingSuggestion int action)3479 public @NetworkSuggestionsStatusCode int removeNetworkSuggestions( 3480 @NonNull List<WifiNetworkSuggestion> networkSuggestions, 3481 @ActionAfterRemovingSuggestion int action) { 3482 try { 3483 return mService.removeNetworkSuggestions(new ParceledListSlice<>(networkSuggestions), 3484 mContext.getOpPackageName(), action); 3485 } catch (RemoteException e) { 3486 throw e.rethrowFromSystemServer(); 3487 } 3488 } 3489 3490 /** 3491 * Get all network suggestions provided by the calling app. 3492 * See {@link #addNetworkSuggestions(List)} 3493 * See {@link #removeNetworkSuggestions(List)} 3494 * @return a list of {@link WifiNetworkSuggestion} 3495 */ 3496 @RequiresPermission(ACCESS_WIFI_STATE) getNetworkSuggestions()3497 public @NonNull List<WifiNetworkSuggestion> getNetworkSuggestions() { 3498 try { 3499 return mService.getNetworkSuggestions(mContext.getOpPackageName()).getList(); 3500 } catch (RemoteException e) { 3501 throw e.rethrowAsRuntimeException(); 3502 } 3503 } 3504 3505 /** 3506 * Returns the max number of network suggestions that are allowed per app on the device. 3507 * @see #addNetworkSuggestions(List) 3508 * @see #removeNetworkSuggestions(List) 3509 */ getMaxNumberOfNetworkSuggestionsPerApp()3510 public int getMaxNumberOfNetworkSuggestionsPerApp() { 3511 return getMaxNumberOfNetworkSuggestionsPerApp( 3512 mContext.getSystemService(ActivityManager.class).isLowRamDevice()); 3513 } 3514 3515 /** @hide */ getMaxNumberOfNetworkSuggestionsPerApp(boolean isLowRamDevice)3516 public static int getMaxNumberOfNetworkSuggestionsPerApp(boolean isLowRamDevice) { 3517 return isLowRamDevice 3518 ? NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM 3519 : NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM; 3520 } 3521 3522 /** 3523 * Add or update a Passpoint configuration. The configuration provides a credential 3524 * for connecting to Passpoint networks that are operated by the Passpoint 3525 * service provider specified in the configuration. 3526 * 3527 * Each configuration is uniquely identified by a unique key which depends on the contents of 3528 * the configuration. This allows the caller to install multiple profiles with the same FQDN 3529 * (Fully qualified domain name). Therefore, in order to update an existing profile, it is 3530 * first required to remove it using {@link WifiManager#removePasspointConfiguration(String)}. 3531 * Otherwise, a new profile will be added with both configuration. 3532 * 3533 * Deprecated for general app usage - except DO/PO apps. 3534 * See {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} to 3535 * create a passpoint suggestion. 3536 * See {@link #addNetworkSuggestions(List)}, {@link #removeNetworkSuggestions(List)} for new 3537 * API to add Wi-Fi networks for consideration when auto-connecting to wifi. 3538 * <b>Compatibility Note:</b> For applications targeting 3539 * {@link android.os.Build.VERSION_CODES#R} or above, this API will always fail and throw 3540 * {@link IllegalArgumentException}. 3541 * <p> 3542 * Deprecation Exemptions: 3543 * <ul> 3544 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3545 * </ul> 3546 * 3547 * @param config The Passpoint configuration to be added 3548 * @throws IllegalArgumentException if configuration is invalid or Passpoint is not enabled on 3549 * the device. 3550 */ addOrUpdatePasspointConfiguration(PasspointConfiguration config)3551 public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) { 3552 try { 3553 if (!mService.addOrUpdatePasspointConfiguration(config, mContext.getOpPackageName())) { 3554 throw new IllegalArgumentException(); 3555 } 3556 } catch (RemoteException e) { 3557 throw e.rethrowFromSystemServer(); 3558 } 3559 } 3560 3561 /** 3562 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name) added 3563 * by the caller. 3564 * 3565 * @param fqdn The FQDN of the Passpoint configuration added by the caller to be removed 3566 * @throws IllegalArgumentException if no configuration is associated with the given FQDN or 3567 * Passpoint is not enabled on the device. 3568 * @deprecated This will be non-functional in a future release. 3569 * <br> 3570 * Requires {@code android.Manifest.permission.NETWORK_SETTINGS} or 3571 * {@code android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}. 3572 */ 3573 @Deprecated removePasspointConfiguration(String fqdn)3574 public void removePasspointConfiguration(String fqdn) { 3575 try { 3576 if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) { 3577 throw new IllegalArgumentException(); 3578 } 3579 } catch (RemoteException e) { 3580 throw e.rethrowFromSystemServer(); 3581 } 3582 } 3583 3584 /** 3585 * Return the list of installed Passpoint configurations added by the caller. 3586 * 3587 * An empty list will be returned when no configurations are installed. 3588 * 3589 * @return A list of {@link PasspointConfiguration} added by the caller 3590 * @deprecated This will be non-functional in a future release. 3591 * <br> 3592 * Requires {@code android.Manifest.permission.NETWORK_SETTINGS} or 3593 * {@code android.Manifest.permission.NETWORK_SETUP_WIZARD}. 3594 */ 3595 @Deprecated getPasspointConfigurations()3596 public List<PasspointConfiguration> getPasspointConfigurations() { 3597 try { 3598 return mService.getPasspointConfigurations(mContext.getOpPackageName()).getList(); 3599 } catch (RemoteException e) { 3600 throw e.rethrowFromSystemServer(); 3601 } 3602 } 3603 3604 /** 3605 * Query for a Hotspot 2.0 release 2 OSU icon file. An {@link #ACTION_PASSPOINT_ICON} intent 3606 * will be broadcasted once the request is completed. The presence of the intent extra 3607 * {@link #EXTRA_ICON} will indicate the result of the request. 3608 * A missing intent extra {@link #EXTRA_ICON} will indicate a failure. 3609 * 3610 * @param bssid The BSSID of the AP 3611 * @param fileName Name of the icon file (remote file) to query from the AP 3612 * 3613 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 3614 * @hide 3615 */ queryPasspointIcon(long bssid, String fileName)3616 public void queryPasspointIcon(long bssid, String fileName) { 3617 try { 3618 mService.queryPasspointIcon(bssid, fileName); 3619 } catch (RemoteException e) { 3620 throw e.rethrowFromSystemServer(); 3621 } 3622 } 3623 3624 /** 3625 * Match the currently associated network against the SP matching the given FQDN 3626 * @param fqdn FQDN of the SP 3627 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 3628 * @hide 3629 */ matchProviderWithCurrentNetwork(String fqdn)3630 public int matchProviderWithCurrentNetwork(String fqdn) { 3631 try { 3632 return mService.matchProviderWithCurrentNetwork(fqdn); 3633 } catch (RemoteException e) { 3634 throw e.rethrowFromSystemServer(); 3635 } 3636 } 3637 3638 /** 3639 * Remove the specified network from the list of configured networks. 3640 * This may result in the asynchronous delivery of state change 3641 * events. 3642 * 3643 * Applications are not allowed to remove networks created by other 3644 * applications. 3645 * 3646 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 3647 * #getConfiguredNetworks}. 3648 * @return {@code true} if the operation succeeded 3649 * 3650 * @deprecated 3651 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3652 * mechanism to trigger connection to a Wi-Fi network. 3653 * b) See {@link #addNetworkSuggestions(List)}, 3654 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3655 * when auto-connecting to wifi. 3656 * <b>Compatibility Note:</b> For applications targeting 3657 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3658 * {@code false}. 3659 * <p> 3660 * Deprecation Exemptions: 3661 * <ul> 3662 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3663 * </ul> 3664 */ 3665 @Deprecated removeNetwork(int netId)3666 public boolean removeNetwork(int netId) { 3667 try { 3668 return mService.removeNetwork(netId, mContext.getOpPackageName()); 3669 } catch (RemoteException e) { 3670 throw e.rethrowFromSystemServer(); 3671 } 3672 } 3673 3674 /** 3675 * Remove all configured networks that were not created by the calling app. Can only 3676 * be called by a Device Owner (DO) app. 3677 * 3678 * @return {@code true} if at least one network is removed, {@code false} otherwise 3679 * @throws SecurityException if the caller is not a Device Owner app 3680 */ 3681 @RequiresPermission(CHANGE_WIFI_STATE) removeNonCallerConfiguredNetworks()3682 public boolean removeNonCallerConfiguredNetworks() { 3683 try { 3684 return mService.removeNonCallerConfiguredNetworks(mContext.getOpPackageName()); 3685 } catch (RemoteException e) { 3686 throw e.rethrowFromSystemServer(); 3687 } 3688 } 3689 /** 3690 * Allow a previously configured network to be associated with. If 3691 * <code>attemptConnect</code> is true, an attempt to connect to the selected 3692 * network is initiated. This may result in the asynchronous delivery 3693 * of state change events. 3694 * <p> 3695 * <b>Note:</b> Network communication may not use Wi-Fi even if Wi-Fi is connected; 3696 * traffic may instead be sent through another network, such as cellular data, 3697 * Bluetooth tethering, or Ethernet. For example, traffic will never use a 3698 * Wi-Fi network that does not provide Internet access (e.g. a wireless 3699 * printer), if another network that does offer Internet access (e.g. 3700 * cellular data) is available. Applications that need to ensure that their 3701 * network traffic uses Wi-Fi should use APIs such as 3702 * {@link Network#bindSocket(java.net.Socket)}, 3703 * {@link Network#openConnection(java.net.URL)}, or 3704 * {@link ConnectivityManager#bindProcessToNetwork} to do so. 3705 * 3706 * Applications are not allowed to enable networks created by other 3707 * applications. 3708 * 3709 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 3710 * #getConfiguredNetworks}. 3711 * @param attemptConnect The way to select a particular network to connect to is specify 3712 * {@code true} for this parameter. 3713 * @return {@code true} if the operation succeeded 3714 * 3715 * @deprecated 3716 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3717 * mechanism to trigger connection to a Wi-Fi network. 3718 * b) See {@link #addNetworkSuggestions(List)}, 3719 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3720 * when auto-connecting to wifi. 3721 * <b>Compatibility Note:</b> For applications targeting 3722 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3723 * {@code false}. 3724 * Deprecation Exemptions: 3725 * <ul> 3726 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3727 * </ul> 3728 */ 3729 @Deprecated enableNetwork(int netId, boolean attemptConnect)3730 public boolean enableNetwork(int netId, boolean attemptConnect) { 3731 try { 3732 return mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName()); 3733 } catch (RemoteException e) { 3734 throw e.rethrowFromSystemServer(); 3735 } 3736 } 3737 3738 /** 3739 * Disable a configured network. The specified network will not be 3740 * a candidate for associating. This may result in the asynchronous 3741 * delivery of state change events. 3742 * 3743 * Applications are not allowed to disable networks created by other 3744 * applications. 3745 * 3746 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 3747 * #getConfiguredNetworks}. 3748 * @return {@code true} if the operation succeeded 3749 * 3750 * @deprecated 3751 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3752 * mechanism to trigger connection to a Wi-Fi network. 3753 * b) See {@link #addNetworkSuggestions(List)}, 3754 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3755 * when auto-connecting to wifi. 3756 * <b>Compatibility Note:</b> For applications targeting 3757 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3758 * {@code false}. 3759 * <p> 3760 * Deprecation Exemptions: 3761 * <ul> 3762 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3763 * </ul> 3764 */ 3765 @Deprecated disableNetwork(int netId)3766 public boolean disableNetwork(int netId) { 3767 try { 3768 return mService.disableNetwork(netId, mContext.getOpPackageName()); 3769 } catch (RemoteException e) { 3770 throw e.rethrowFromSystemServer(); 3771 } 3772 } 3773 3774 /** 3775 * Disassociate from the currently active access point. This may result 3776 * in the asynchronous delivery of state change events. 3777 * @return {@code true} if the operation succeeded 3778 * 3779 * @deprecated 3780 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3781 * mechanism to trigger connection to a Wi-Fi network. 3782 * b) See {@link #addNetworkSuggestions(List)}, 3783 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3784 * when auto-connecting to wifi. 3785 * <b>Compatibility Note:</b> For applications targeting 3786 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3787 * {@code false}. 3788 * <p> 3789 * Deprecation Exemptions: 3790 * <ul> 3791 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3792 * </ul> 3793 */ 3794 @Deprecated disconnect()3795 public boolean disconnect() { 3796 try { 3797 return mService.disconnect(mContext.getOpPackageName()); 3798 } catch (RemoteException e) { 3799 throw e.rethrowFromSystemServer(); 3800 } 3801 } 3802 3803 /** 3804 * Reconnect to the currently active access point, if we are currently 3805 * disconnected. This may result in the asynchronous delivery of state 3806 * change events. 3807 * @return {@code true} if the operation succeeded 3808 * 3809 * @deprecated 3810 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3811 * mechanism to trigger connection to a Wi-Fi network. 3812 * b) See {@link #addNetworkSuggestions(List)}, 3813 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3814 * when auto-connecting to wifi. 3815 * <b>Compatibility Note:</b> For applications targeting 3816 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3817 * {@code false}. 3818 * <p> 3819 * Deprecation Exemptions: 3820 * <ul> 3821 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3822 * </ul> 3823 */ 3824 @Deprecated reconnect()3825 public boolean reconnect() { 3826 try { 3827 return mService.reconnect(mContext.getOpPackageName()); 3828 } catch (RemoteException e) { 3829 throw e.rethrowFromSystemServer(); 3830 } 3831 } 3832 3833 /** 3834 * Reconnect to the currently active access point, even if we are already 3835 * connected. This may result in the asynchronous delivery of state 3836 * change events. 3837 * @return {@code true} if the operation succeeded 3838 * 3839 * @deprecated 3840 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3841 * mechanism to trigger connection to a Wi-Fi network. 3842 * b) See {@link #addNetworkSuggestions(List)}, 3843 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3844 * when auto-connecting to wifi. 3845 * <b>Compatibility Note:</b> For applications targeting 3846 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. 3847 */ 3848 @Deprecated reassociate()3849 public boolean reassociate() { 3850 try { 3851 return mService.reassociate(mContext.getOpPackageName()); 3852 } catch (RemoteException e) { 3853 throw e.rethrowFromSystemServer(); 3854 } 3855 } 3856 3857 /** 3858 * Check that the supplicant daemon is responding to requests. 3859 * @return {@code true} if we were able to communicate with the supplicant and 3860 * it returned the expected response to the PING message. 3861 * @deprecated Will return the output of {@link #isWifiEnabled()} instead. 3862 */ 3863 @Deprecated pingSupplicant()3864 public boolean pingSupplicant() { 3865 return isWifiEnabled(); 3866 } 3867 3868 /** @hide */ 3869 public static final int WIFI_FEATURE_INFRA = 0; // Basic infrastructure mode 3870 /** @hide */ 3871 public static final int WIFI_FEATURE_PASSPOINT = 2; // Support for GAS/ANQP 3872 /** @hide */ 3873 public static final int WIFI_FEATURE_P2P = 3; // Wifi-Direct 3874 /** @hide */ 3875 public static final int WIFI_FEATURE_MOBILE_HOTSPOT = 4; // Soft AP 3876 /** @hide */ 3877 public static final int WIFI_FEATURE_SCANNER = 5; // WifiScanner APIs 3878 /** @hide */ 3879 public static final int WIFI_FEATURE_AWARE = 6; // Wi-Fi Aware networking 3880 /** @hide */ 3881 public static final int WIFI_FEATURE_D2D_RTT = 7; // Device-to-device RTT 3882 /** @hide */ 3883 public static final int WIFI_FEATURE_D2AP_RTT = 8; // Device-to-AP RTT 3884 /** @hide */ 3885 public static final int WIFI_FEATURE_PNO = 10; // Preferred network offload 3886 /** @hide */ 3887 public static final int WIFI_FEATURE_TDLS = 12; // Tunnel directed link setup 3888 /** @hide */ 3889 public static final int WIFI_FEATURE_TDLS_OFFCHANNEL = 13; // TDLS off channel 3890 /** @hide */ 3891 public static final int WIFI_FEATURE_AP_STA = 15; // AP STA Concurrency 3892 /** @hide */ 3893 public static final int WIFI_FEATURE_LINK_LAYER_STATS = 16; // Link layer stats 3894 /** @hide */ 3895 public static final int WIFI_FEATURE_LOGGER = 17; // WiFi Logger 3896 /** @hide */ 3897 public static final int WIFI_FEATURE_RSSI_MONITOR = 19; // RSSI Monitor 3898 /** @hide */ 3899 public static final int WIFI_FEATURE_MKEEP_ALIVE = 20; // mkeep_alive 3900 /** @hide */ 3901 public static final int WIFI_FEATURE_CONFIG_NDO = 21; // ND offload 3902 /** @hide */ 3903 public static final int WIFI_FEATURE_CONTROL_ROAMING = 23; // Control firmware roaming 3904 /** @hide */ 3905 public static final int WIFI_FEATURE_IE_WHITELIST = 24; // Probe IE white listing 3906 /** @hide */ 3907 public static final int WIFI_FEATURE_SCAN_RAND = 25; // Random MAC & Probe seq 3908 /** @hide */ 3909 public static final int WIFI_FEATURE_TX_POWER_LIMIT = 26; // Set Tx power limit 3910 /** @hide */ 3911 public static final int WIFI_FEATURE_WPA3_SAE = 27; // WPA3-Personal SAE 3912 /** @hide */ 3913 public static final int WIFI_FEATURE_WPA3_SUITE_B = 28; // WPA3-Enterprise Suite-B 3914 /** @hide */ 3915 public static final int WIFI_FEATURE_OWE = 29; // Enhanced Open 3916 /** @hide */ 3917 public static final int WIFI_FEATURE_LOW_LATENCY = 30; // Low Latency modes 3918 /** @hide */ 3919 public static final int WIFI_FEATURE_DPP = 31; // DPP (Easy-Connect) 3920 /** @hide */ 3921 public static final int WIFI_FEATURE_P2P_RAND_MAC = 32; // Random P2P MAC 3922 /** @hide */ 3923 public static final int WIFI_FEATURE_CONNECTED_RAND_MAC = 33; // Random STA MAC 3924 /** @hide */ 3925 public static final int WIFI_FEATURE_AP_RAND_MAC = 34; // Random AP MAC 3926 /** @hide */ 3927 public static final int WIFI_FEATURE_MBO = 35; // MBO Support 3928 /** @hide */ 3929 public static final int WIFI_FEATURE_OCE = 36; // OCE Support 3930 /** @hide */ 3931 public static final int WIFI_FEATURE_WAPI = 37; // WAPI 3932 3933 /** @hide */ 3934 public static final int WIFI_FEATURE_FILS_SHA256 = 38; // FILS-SHA256 3935 3936 /** @hide */ 3937 public static final int WIFI_FEATURE_FILS_SHA384 = 39; // FILS-SHA384 3938 3939 /** @hide */ 3940 public static final int WIFI_FEATURE_SAE_PK = 40; // SAE-PK 3941 3942 /** @hide */ 3943 public static final int WIFI_FEATURE_STA_BRIDGED_AP = 41; // STA + Bridged AP 3944 3945 /** @hide */ 3946 public static final int WIFI_FEATURE_BRIDGED_AP = 42; // Bridged AP 3947 3948 /** @hide */ 3949 public static final int WIFI_FEATURE_INFRA_60G = 43; // 60 GHz Band Support 3950 3951 /** 3952 * Support for 2 STA's for the local-only (peer to peer) connection + internet connection 3953 * concurrency. 3954 * @hide 3955 */ 3956 public static final int WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 44; 3957 3958 /** 3959 * Support for 2 STA's for the make before break concurrency. 3960 * @hide 3961 */ 3962 public static final int WIFI_FEATURE_ADDITIONAL_STA_MBB = 45; 3963 3964 /** 3965 * Support for 2 STA's for the restricted connection + internet connection concurrency. 3966 * @hide 3967 */ 3968 public static final int WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 46; 3969 3970 /** 3971 * DPP (Easy-Connect) Enrollee Responder mode support 3972 * @hide 3973 */ 3974 public static final int WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 47; 3975 3976 /** 3977 * Passpoint Terms and Conditions feature support 3978 * @hide 3979 */ 3980 public static final int WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 48; 3981 3982 /** @hide */ 3983 public static final int WIFI_FEATURE_SAE_H2E = 49; // Hash-to-Element 3984 3985 /** @hide */ 3986 public static final int WIFI_FEATURE_WFD_R2 = 50; // Wi-Fi Display R2 3987 3988 /** 3989 * RFC 7542 decorated identity support 3990 * @hide */ 3991 public static final int WIFI_FEATURE_DECORATED_IDENTITY = 51; 3992 3993 /** 3994 * Trust On First Use support for WPA Enterprise network 3995 * @hide 3996 */ 3997 public static final int WIFI_FEATURE_TRUST_ON_FIRST_USE = 52; 3998 3999 /** 4000 * Support for 2 STA's multi internet concurrency. 4001 * @hide 4002 */ 4003 public static final int WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 53; 4004 4005 /** 4006 * Support for DPP (Easy-Connect) AKM. 4007 * @hide 4008 */ 4009 public static final int WIFI_FEATURE_DPP_AKM = 54; 4010 4011 /** 4012 * Support for setting TLS minimum version. 4013 * @hide 4014 */ 4015 public static final int WIFI_FEATURE_SET_TLS_MINIMUM_VERSION = 55; 4016 4017 /** 4018 * Support for TLS v.13. 4019 * @hide 4020 */ 4021 public static final int WIFI_FEATURE_TLS_V1_3 = 56; 4022 4023 /** 4024 * Support for Dual Band Simultaneous (DBS) operation. 4025 * @hide 4026 */ 4027 public static final int WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS = 57; 4028 4029 /** 4030 * Support for TID-To-Link Mapping negotiation. 4031 * @hide 4032 */ 4033 public static final int WIFI_FEATURE_T2LM_NEGOTIATION = 58; 4034 4035 /** 4036 * Support for WEP Wi-Fi Network 4037 * @hide 4038 */ 4039 public static final int WIFI_FEATURE_WEP = 59; 4040 4041 /** 4042 * Support for WPA PERSONAL Wi-Fi Network 4043 * @hide 4044 */ 4045 public static final int WIFI_FEATURE_WPA_PERSONAL = 60; 4046 4047 /** 4048 * Support for Roaming Mode 4049 * @hide 4050 */ 4051 public static final int WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT = 61; 4052 4053 /** 4054 * Supports device-to-device connections when infra STA is disabled. 4055 * @hide 4056 */ 4057 public static final int WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED = 62; 4058 4059 /** 4060 * Support for Soft AP multi-links operation. 4061 * @hide 4062 */ 4063 public static final int WIFI_FEATURE_SOFTAP_MLO = 63; 4064 4065 /** 4066 * Supports multiple Wi-Fi 7 multi-link devices (MLD) on SoftAp. 4067 * @hide 4068 */ 4069 public static final int WIFI_FEATURE_MULTIPLE_MLD_ON_SAP = 64; 4070 4071 /** 4072 * NOTE: When adding a new WIFI_FEATURE_ value, also be sure to update 4073 * {@link com.android.server.wifi.util.FeatureBitsetUtils} 4074 */ 4075 isFeatureSupported(int feature)4076 private boolean isFeatureSupported(int feature) { 4077 try { 4078 return mService.isFeatureSupported(feature); 4079 } catch (RemoteException e) { 4080 throw e.rethrowFromSystemServer(); 4081 } 4082 } 4083 4084 /** 4085 * @return true if this adapter supports Passpoint 4086 * @hide 4087 */ isPasspointSupported()4088 public boolean isPasspointSupported() { 4089 // Both OEM and chip support are required 4090 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT) 4091 && isFeatureSupported(WIFI_FEATURE_PASSPOINT); 4092 } 4093 4094 /** 4095 * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct) 4096 */ isP2pSupported()4097 public boolean isP2pSupported() { 4098 // Both OEM and chip support are required 4099 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT) 4100 && isFeatureSupported(WIFI_FEATURE_P2P); 4101 } 4102 4103 /** 4104 * @return true if this adapter supports portable Wi-Fi hotspot 4105 * @hide 4106 */ 4107 @SystemApi isPortableHotspotSupported()4108 public boolean isPortableHotspotSupported() { 4109 return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT); 4110 } 4111 4112 /** 4113 * @return true if this adapter supports WifiScanner APIs 4114 * @hide 4115 */ 4116 @SystemApi isWifiScannerSupported()4117 public boolean isWifiScannerSupported() { 4118 return isFeatureSupported(WIFI_FEATURE_SCANNER); 4119 } 4120 4121 /** 4122 * @return true if this adapter supports Neighbour Awareness Network APIs 4123 * @hide 4124 */ isWifiAwareSupported()4125 public boolean isWifiAwareSupported() { 4126 // Both OEM and chip support are required 4127 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE) 4128 && isFeatureSupported(WIFI_FEATURE_AWARE); 4129 } 4130 4131 /** 4132 * Query whether or not the device supports Station (STA) + Access point (AP) concurrency. 4133 * 4134 * @return true if this device supports STA + AP concurrency, false otherwise. 4135 */ isStaApConcurrencySupported()4136 public boolean isStaApConcurrencySupported() { 4137 return isFeatureSupported(WIFI_FEATURE_AP_STA); 4138 } 4139 4140 /** 4141 * Query whether or not the device supports concurrent station (STA) connections for local-only 4142 * connections using {@link WifiNetworkSpecifier}. 4143 * 4144 * @return true if this device supports multiple STA concurrency for this use-case, false 4145 * otherwise. 4146 */ isStaConcurrencyForLocalOnlyConnectionsSupported()4147 public boolean isStaConcurrencyForLocalOnlyConnectionsSupported() { 4148 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY); 4149 } 4150 4151 /** 4152 * Query whether or not the device supports concurrent station (STA) connections for 4153 * make-before-break wifi to wifi switching. 4154 * 4155 * Note: This is an internal feature which is not available to apps. 4156 * 4157 * @return true if this device supports multiple STA concurrency for this use-case, false 4158 * otherwise. 4159 */ isMakeBeforeBreakWifiSwitchingSupported()4160 public boolean isMakeBeforeBreakWifiSwitchingSupported() { 4161 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_MBB); 4162 } 4163 4164 /** 4165 * Query whether or not the device supports concurrent station (STA) connections for multi 4166 * internet connections. 4167 * 4168 * @return true if this device supports multiple STA concurrency for this use-case, false 4169 * otherwise. 4170 */ 4171 @RequiresApi(Build.VERSION_CODES.TIRAMISU) isStaConcurrencyForMultiInternetSupported()4172 public boolean isStaConcurrencyForMultiInternetSupported() { 4173 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET); 4174 } 4175 4176 /** 4177 * Query whether or not the device supports concurrent station (STA) connections for restricted 4178 * connections using {@link WifiNetworkSuggestion.Builder#setOemPaid(boolean)} / 4179 * {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)}. 4180 * 4181 * @return true if this device supports multiple STA concurrency for this use-case, false 4182 * otherwise. 4183 * @hide 4184 */ 4185 @SystemApi isStaConcurrencyForRestrictedConnectionsSupported()4186 public boolean isStaConcurrencyForRestrictedConnectionsSupported() { 4187 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED); 4188 } 4189 4190 /** 4191 * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)} 4192 * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT} and 4193 * {@link android.content.pm.PackageManager#FEATURE_WIFI_AWARE}. 4194 * 4195 * @return true if this adapter supports Device-to-device RTT 4196 * @hide 4197 */ 4198 @Deprecated 4199 @SystemApi isDeviceToDeviceRttSupported()4200 public boolean isDeviceToDeviceRttSupported() { 4201 return isFeatureSupported(WIFI_FEATURE_D2D_RTT); 4202 } 4203 4204 /** 4205 * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)} 4206 * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT}. 4207 * 4208 * @return true if this adapter supports Device-to-AP RTT 4209 */ 4210 @Deprecated isDeviceToApRttSupported()4211 public boolean isDeviceToApRttSupported() { 4212 return isFeatureSupported(WIFI_FEATURE_D2AP_RTT); 4213 } 4214 4215 /** 4216 * @return true if this adapter supports offloaded connectivity scan 4217 */ isPreferredNetworkOffloadSupported()4218 public boolean isPreferredNetworkOffloadSupported() { 4219 try { 4220 return mService.isPnoSupported(); 4221 } catch (RemoteException e) { 4222 throw e.rethrowFromSystemServer(); 4223 } 4224 } 4225 4226 /** 4227 * @return true if this adapter supports Tunnel Directed Link Setup 4228 */ isTdlsSupported()4229 public boolean isTdlsSupported() { 4230 return isFeatureSupported(WIFI_FEATURE_TDLS); 4231 } 4232 4233 /** 4234 * @return true if this adapter supports Off Channel Tunnel Directed Link Setup 4235 * @hide 4236 */ isOffChannelTdlsSupported()4237 public boolean isOffChannelTdlsSupported() { 4238 return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL); 4239 } 4240 4241 /** 4242 * @return true if this adapter supports advanced power/performance counters 4243 */ isEnhancedPowerReportingSupported()4244 public boolean isEnhancedPowerReportingSupported() { 4245 return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS); 4246 } 4247 4248 /** 4249 * @return true if this device supports connected MAC randomization. 4250 * @hide 4251 */ 4252 @SystemApi isConnectedMacRandomizationSupported()4253 public boolean isConnectedMacRandomizationSupported() { 4254 return isFeatureSupported(WIFI_FEATURE_CONNECTED_RAND_MAC); 4255 } 4256 4257 /** 4258 * @return true if this device supports AP MAC randomization. 4259 * @hide 4260 */ 4261 @SystemApi isApMacRandomizationSupported()4262 public boolean isApMacRandomizationSupported() { 4263 return isFeatureSupported(WIFI_FEATURE_AP_RAND_MAC); 4264 } 4265 4266 /** 4267 * @return true if this device supports Low latency mode. 4268 * @hide 4269 */ 4270 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 4271 @SystemApi isLowLatencyModeSupported()4272 public boolean isLowLatencyModeSupported() { 4273 return isFeatureSupported(WIFI_FEATURE_LOW_LATENCY); 4274 } 4275 4276 /** 4277 * Check if the chipset supports 2.4GHz band. 4278 * @return {@code true} if supported, {@code false} otherwise. 4279 */ is24GHzBandSupported()4280 public boolean is24GHzBandSupported() { 4281 try { 4282 return mService.is24GHzBandSupported(); 4283 } catch (RemoteException e) { 4284 throw e.rethrowFromSystemServer(); 4285 } 4286 } 4287 4288 /** 4289 * Check if the chipset supports 5GHz band. 4290 * @return {@code true} if supported, {@code false} otherwise. 4291 */ is5GHzBandSupported()4292 public boolean is5GHzBandSupported() { 4293 try { 4294 return mService.is5GHzBandSupported(); 4295 } catch (RemoteException e) { 4296 throw e.rethrowFromSystemServer(); 4297 } 4298 } 4299 4300 /** 4301 * Check if the chipset supports the 60GHz frequency band. 4302 * 4303 * @return {@code true} if supported, {@code false} otherwise. 4304 */ 4305 @RequiresApi(Build.VERSION_CODES.S) is60GHzBandSupported()4306 public boolean is60GHzBandSupported() { 4307 try { 4308 return mService.is60GHzBandSupported(); 4309 } catch (RemoteException e) { 4310 throw e.rethrowFromSystemServer(); 4311 } 4312 } 4313 4314 /** 4315 * Check if the chipset supports 6GHz band. 4316 * @return {@code true} if supported, {@code false} otherwise. 4317 */ is6GHzBandSupported()4318 public boolean is6GHzBandSupported() { 4319 try { 4320 return mService.is6GHzBandSupported(); 4321 } catch (RemoteException e) { 4322 throw e.rethrowFromSystemServer(); 4323 } 4324 } 4325 4326 /** 4327 * Check if the chipset supports a certain Wi-Fi standard. 4328 * @param standard the IEEE 802.11 standard to check on. 4329 * valid values from {@link ScanResult}'s {@code WIFI_STANDARD_} 4330 * @return {@code true} if supported, {@code false} otherwise. 4331 */ isWifiStandardSupported(@ifiAnnotations.WifiStandard int standard)4332 public boolean isWifiStandardSupported(@WifiAnnotations.WifiStandard int standard) { 4333 try { 4334 return mService.isWifiStandardSupported(standard); 4335 } catch (RemoteException e) { 4336 throw e.rethrowFromSystemServer(); 4337 } 4338 } 4339 4340 /** 4341 * Query whether or not the device supports concurrency of Station (STA) + multiple access 4342 * points (AP) (where the APs bridged together). 4343 * 4344 * @return true if this device supports concurrency of STA + multiple APs which are bridged 4345 * together, false otherwise. 4346 */ isStaBridgedApConcurrencySupported()4347 public boolean isStaBridgedApConcurrencySupported() { 4348 return isFeatureSupported(WIFI_FEATURE_STA_BRIDGED_AP); 4349 } 4350 4351 /** 4352 * Query whether or not the device supports multiple Access point (AP) which are bridged 4353 * together. 4354 * 4355 * @return true if this device supports concurrency of multiple AP which bridged together, 4356 * false otherwise. 4357 */ isBridgedApConcurrencySupported()4358 public boolean isBridgedApConcurrencySupported() { 4359 return isFeatureSupported(WIFI_FEATURE_BRIDGED_AP); 4360 } 4361 4362 /** 4363 * @return true if this devices supports device-to-device (D2d) Wi-Fi use-cases 4364 * such as Wi-Fi Direct when infra station (STA) is disabled. 4365 */ 4366 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) isD2dSupportedWhenInfraStaDisabled()4367 public boolean isD2dSupportedWhenInfraStaDisabled() { 4368 return isFeatureSupported(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED); 4369 } 4370 4371 /** 4372 * Interface for Wi-Fi activity energy info listener. Should be implemented by applications and 4373 * set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}. 4374 * 4375 * @hide 4376 */ 4377 @SystemApi 4378 public interface OnWifiActivityEnergyInfoListener { 4379 /** 4380 * Called when Wi-Fi activity energy info is available. 4381 * Note: this listener is triggered at most once for each call to 4382 * {@link #getWifiActivityEnergyInfoAsync}. 4383 * 4384 * @param info the latest {@link WifiActivityEnergyInfo}, or null if unavailable. 4385 */ onWifiActivityEnergyInfo(@ullable WifiActivityEnergyInfo info)4386 void onWifiActivityEnergyInfo(@Nullable WifiActivityEnergyInfo info); 4387 } 4388 4389 private static class OnWifiActivityEnergyInfoProxy 4390 extends IOnWifiActivityEnergyInfoListener.Stub { 4391 private final Object mLock = new Object(); 4392 @Nullable @GuardedBy("mLock") private Executor mExecutor; 4393 @Nullable @GuardedBy("mLock") private OnWifiActivityEnergyInfoListener mListener; 4394 OnWifiActivityEnergyInfoProxy(Executor executor, OnWifiActivityEnergyInfoListener listener)4395 OnWifiActivityEnergyInfoProxy(Executor executor, 4396 OnWifiActivityEnergyInfoListener listener) { 4397 mExecutor = executor; 4398 mListener = listener; 4399 } 4400 4401 @Override onWifiActivityEnergyInfo(WifiActivityEnergyInfo info)4402 public void onWifiActivityEnergyInfo(WifiActivityEnergyInfo info) { 4403 Executor executor; 4404 OnWifiActivityEnergyInfoListener listener; 4405 synchronized (mLock) { 4406 if (mExecutor == null || mListener == null) { 4407 return; 4408 } 4409 executor = mExecutor; 4410 listener = mListener; 4411 // null out to allow garbage collection, prevent triggering listener more than once 4412 mExecutor = null; 4413 mListener = null; 4414 } 4415 Binder.clearCallingIdentity(); 4416 executor.execute(() -> listener.onWifiActivityEnergyInfo(info)); 4417 } 4418 } 4419 4420 /** 4421 * Request to get the current {@link WifiActivityEnergyInfo} asynchronously. 4422 * Note: This method will return null if {@link #isEnhancedPowerReportingSupported()} returns 4423 * false. 4424 * 4425 * @param executor the executor that the listener will be invoked on 4426 * @param listener the listener that will receive the {@link WifiActivityEnergyInfo} object 4427 * when it becomes available. The listener will be triggered at most once for 4428 * each call to this method. 4429 * 4430 * @hide 4431 */ 4432 @SystemApi 4433 @RequiresPermission(ACCESS_WIFI_STATE) getWifiActivityEnergyInfoAsync( @onNull @allbackExecutor Executor executor, @NonNull OnWifiActivityEnergyInfoListener listener)4434 public void getWifiActivityEnergyInfoAsync( 4435 @NonNull @CallbackExecutor Executor executor, 4436 @NonNull OnWifiActivityEnergyInfoListener listener) { 4437 Objects.requireNonNull(executor, "executor cannot be null"); 4438 Objects.requireNonNull(listener, "listener cannot be null"); 4439 try { 4440 mService.getWifiActivityEnergyInfoAsync( 4441 new OnWifiActivityEnergyInfoProxy(executor, listener)); 4442 } catch (RemoteException e) { 4443 throw e.rethrowFromSystemServer(); 4444 } 4445 } 4446 4447 /** 4448 * Request a scan for access points. Returns immediately. The availability 4449 * of the results is made known later by means of an asynchronous event sent 4450 * on completion of the scan. 4451 * <p> 4452 * To initiate a Wi-Fi scan, declare the 4453 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} 4454 * permission in the manifest, and perform these steps: 4455 * </p> 4456 * <ol style="1"> 4457 * <li>Invoke the following method: 4458 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).startScan()}</li> 4459 * <li> 4460 * Register a BroadcastReceiver to listen to 4461 * {@code SCAN_RESULTS_AVAILABLE_ACTION}.</li> 4462 * <li>When a broadcast is received, call: 4463 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).getScanResults()}</li> 4464 * </ol> 4465 * @return {@code true} if the operation succeeded, i.e., the scan was initiated. 4466 * @deprecated The ability for apps to trigger scan requests will be removed in a future 4467 * release. 4468 */ 4469 @Deprecated startScan()4470 public boolean startScan() { 4471 return startScan(null); 4472 } 4473 4474 /** @hide */ 4475 @SystemApi 4476 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) startScan(WorkSource workSource)4477 public boolean startScan(WorkSource workSource) { 4478 try { 4479 String packageName = mContext.getOpPackageName(); 4480 String attributionTag = mContext.getAttributionTag(); 4481 return mService.startScan(packageName, attributionTag); 4482 } catch (RemoteException e) { 4483 throw e.rethrowFromSystemServer(); 4484 } 4485 } 4486 4487 /** 4488 * WPS has been deprecated from Client mode operation. 4489 * 4490 * @return null 4491 * @hide 4492 * @deprecated This API is deprecated 4493 */ getCurrentNetworkWpsNfcConfigurationToken()4494 public String getCurrentNetworkWpsNfcConfigurationToken() { 4495 return null; 4496 } 4497 4498 /** 4499 * Return dynamic information about the current Wi-Fi connection, if any is active. 4500 * <p> 4501 * 4502 * @return the Wi-Fi information, contained in {@link WifiInfo}. 4503 * 4504 * @deprecated Starting with {@link Build.VERSION_CODES#S}, WifiInfo retrieval is moved to 4505 * {@link ConnectivityManager} API surface. WifiInfo is attached in 4506 * {@link NetworkCapabilities#getTransportInfo()} which is available via callback in 4507 * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} or on-demand from 4508 * {@link ConnectivityManager#getNetworkCapabilities(Network)}. 4509 * 4510 *</p> 4511 * Usage example: 4512 * <pre> 4513 * final NetworkRequest request = 4514 * new NetworkRequest.Builder() 4515 * .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 4516 * .build(); 4517 * final ConnectivityManager connectivityManager = 4518 * context.getSystemService(ConnectivityManager.class); 4519 * final NetworkCallback networkCallback = new NetworkCallback() { 4520 * ... 4521 * @Override 4522 * void onAvailable(Network network) {} 4523 * 4524 * @Override 4525 * void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { 4526 * WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo(); 4527 * } 4528 * // etc. 4529 * }; 4530 * connectivityManager.requestNetwork(request, networkCallback); // For request 4531 * connectivityManager.registerNetworkCallback(request, networkCallback); // For listen 4532 * </pre> 4533 * <p> 4534 * <b>Compatibility Notes:</b> 4535 * <li>Apps can continue using this API, however newer features 4536 * such as ability to mask out location sensitive data in WifiInfo will not be supported 4537 * via this API. </li> 4538 * <li>On devices supporting concurrent connections (indicated via 4539 * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc) this API will return 4540 * the details of the internet providing connection (if any) to all apps, except for the apps 4541 * that triggered the creation of the concurrent connection. For such apps, this API will return 4542 * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will 4543 * trigger a concurrent connection on supported devices and hence this API will provide 4544 * details of their peer to peer connection (not the internet providing connection). This 4545 * is to maintain backwards compatibility with behavior on single STA devices.</li> 4546 * </p> 4547 */ 4548 @Deprecated 4549 @RequiresPermission(allOf = {ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION}, conditional = true) getConnectionInfo()4550 public WifiInfo getConnectionInfo() { 4551 try { 4552 return mService.getConnectionInfo(mContext.getOpPackageName(), 4553 mContext.getAttributionTag()); 4554 } catch (RemoteException e) { 4555 throw e.rethrowFromSystemServer(); 4556 } 4557 } 4558 4559 /** 4560 * Return the results of the latest access point scan. 4561 * @return the list of access points found in the most recent scan. An app must hold 4562 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission 4563 * and {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission 4564 * in order to get valid results. 4565 * 4566 * <p> 4567 * When an Access Point’s beacon or probe response includes a Multi-BSSID Element, the 4568 * returned scan results should include separate scan result for each BSSID within the 4569 * Multi-BSSID Information Element. This includes both transmitted and non-transmitted BSSIDs. 4570 * Original Multi-BSSID Element will be included in the Information Elements attached to 4571 * each of the scan results. 4572 * Note: This is the expected behavior for devices supporting 11ax (WiFi-6) and above, and an 4573 * optional requirement for devices running with older WiFi generations. 4574 * </p> 4575 */ 4576 @RequiresPermission(allOf = {ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION}) getScanResults()4577 public List<ScanResult> getScanResults() { 4578 try { 4579 ParceledListSlice<ScanResult> parceledList = mService 4580 .getScanResults(mContext.getOpPackageName(), mContext.getAttributionTag()); 4581 if (parceledList == null) { 4582 return Collections.emptyList(); 4583 } 4584 return parceledList.getList(); 4585 } catch (RemoteException e) { 4586 throw e.rethrowFromSystemServer(); 4587 } 4588 } 4589 4590 /** 4591 * Get the filtered ScanResults which match the network configurations specified by the 4592 * {@code networkSuggestionsToMatch}. Suggestions which use {@link WifiConfiguration} use 4593 * SSID and the security type to match. Suggestions which use {@link PasspointConfigration} 4594 * use the matching rules of Hotspot 2.0. 4595 * @param networkSuggestionsToMatch The list of {@link WifiNetworkSuggestion} to match against. 4596 * These may or may not be suggestions which are installed on the device. 4597 * @param scanResults The scan results to be filtered. Optional - if not provided(empty list), 4598 * the Wi-Fi service will use the most recent scan results which the system has. 4599 * @return The map of {@link WifiNetworkSuggestion} to the list of {@link ScanResult} 4600 * corresponding to networks which match them. 4601 * @hide 4602 */ 4603 @SystemApi 4604 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) 4605 @NonNull getMatchingScanResults( @onNull List<WifiNetworkSuggestion> networkSuggestionsToMatch, @Nullable List<ScanResult> scanResults)4606 public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( 4607 @NonNull List<WifiNetworkSuggestion> networkSuggestionsToMatch, 4608 @Nullable List<ScanResult> scanResults) { 4609 if (networkSuggestionsToMatch == null) { 4610 throw new IllegalArgumentException("networkSuggestions must not be null."); 4611 } 4612 try { 4613 return mService.getMatchingScanResults( 4614 new ParceledListSlice<>(networkSuggestionsToMatch), 4615 new ParceledListSlice<>(scanResults), 4616 mContext.getOpPackageName(), mContext.getAttributionTag()); 4617 } catch (RemoteException e) { 4618 throw e.rethrowFromSystemServer(); 4619 } 4620 } 4621 4622 /** 4623 * Set if scanning is always available. 4624 * 4625 * If set to {@code true}, apps can issue {@link #startScan} and fetch scan results 4626 * even when Wi-Fi is turned off. 4627 * 4628 * @param isAvailable true to enable, false to disable. 4629 * @hide 4630 * @see #isScanAlwaysAvailable() 4631 */ 4632 @SystemApi 4633 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setScanAlwaysAvailable(boolean isAvailable)4634 public void setScanAlwaysAvailable(boolean isAvailable) { 4635 try { 4636 mService.setScanAlwaysAvailable(isAvailable, mContext.getOpPackageName()); 4637 } catch (RemoteException e) { 4638 throw e.rethrowFromSystemServer(); 4639 } 4640 } 4641 4642 /** 4643 * Check if scanning is always available. 4644 * 4645 * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results 4646 * even when Wi-Fi is turned off. 4647 * 4648 * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}. 4649 * @deprecated The ability for apps to trigger scan requests will be removed in a future 4650 * release. 4651 */ 4652 @Deprecated isScanAlwaysAvailable()4653 public boolean isScanAlwaysAvailable() { 4654 try { 4655 return mService.isScanAlwaysAvailable(); 4656 } catch (RemoteException e) { 4657 throw e.rethrowFromSystemServer(); 4658 } 4659 } 4660 4661 /** 4662 * Get channel data such as the number of APs found on each channel from the most recent scan. 4663 * App requires {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} 4664 * 4665 * @param executor The executor on which callback will be invoked. 4666 * @param resultsCallback A callback that will return {@code List<Bundle>} containing channel 4667 * data such as the number of APs found on each channel. 4668 * {@link WifiManager#CHANNEL_DATA_KEY_FREQUENCY_MHZ} and 4669 * {@link WifiManager#CHANNEL_DATA_KEY_NUM_AP} are used to get 4670 * the frequency (Mhz) and number of APs. 4671 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 4672 * @throws SecurityException if the caller does not have permission. 4673 * @throws NullPointerException if the caller provided invalid inputs. 4674 */ 4675 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 4676 @RequiresPermission(NEARBY_WIFI_DEVICES) getChannelData(@onNull @allbackExecutor Executor executor, @NonNull Consumer<List<Bundle>> resultsCallback)4677 public void getChannelData(@NonNull @CallbackExecutor Executor executor, 4678 @NonNull Consumer<List<Bundle>> resultsCallback) { 4679 Objects.requireNonNull(executor, "executor cannot be null"); 4680 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 4681 try { 4682 Bundle extras = new Bundle(); 4683 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 4684 mContext.getAttributionSource()); 4685 mService.getChannelData(new IListListener.Stub() { 4686 @Override 4687 public void onResult(List value) { 4688 Binder.clearCallingIdentity(); 4689 executor.execute(() -> { 4690 resultsCallback.accept(value); 4691 }); 4692 } 4693 }, mContext.getOpPackageName(), extras); 4694 } catch (RemoteException e) { 4695 throw e.rethrowFromSystemServer(); 4696 } 4697 } 4698 4699 /** 4700 * Tell the device to persist the current list of configured networks. 4701 * <p> 4702 * Note: It is possible for this method to change the network IDs of 4703 * existing networks. You should assume the network IDs can be different 4704 * after calling this method. 4705 * 4706 * @return {@code false}. 4707 * @deprecated There is no need to call this method - 4708 * {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)} 4709 * and {@link #removeNetwork(int)} already persist the configurations automatically. 4710 */ 4711 @Deprecated saveConfiguration()4712 public boolean saveConfiguration() { 4713 return false; 4714 } 4715 4716 /** 4717 * Helper class to support driver country code changed listener. 4718 */ 4719 private static class OnDriverCountryCodeChangedProxy 4720 extends IOnWifiDriverCountryCodeChangedListener.Stub { 4721 4722 @NonNull private Executor mExecutor; 4723 @NonNull private ActiveCountryCodeChangedCallback mCallback; 4724 OnDriverCountryCodeChangedProxy(@onNull Executor executor, @NonNull ActiveCountryCodeChangedCallback callback)4725 OnDriverCountryCodeChangedProxy(@NonNull Executor executor, 4726 @NonNull ActiveCountryCodeChangedCallback callback) { 4727 Objects.requireNonNull(executor); 4728 Objects.requireNonNull(callback); 4729 mExecutor = executor; 4730 mCallback = callback; 4731 } 4732 4733 @Override onDriverCountryCodeChanged(String countryCode)4734 public void onDriverCountryCodeChanged(String countryCode) { 4735 Log.i(TAG, "OnDriverCountryCodeChangedProxy: receive onDriverCountryCodeChanged: " 4736 + countryCode); 4737 Binder.clearCallingIdentity(); 4738 if (countryCode != null) { 4739 mExecutor.execute(() -> mCallback.onActiveCountryCodeChanged(countryCode)); 4740 } else { 4741 mExecutor.execute(() -> mCallback.onCountryCodeInactive()); 4742 } 4743 } 4744 } 4745 4746 /** 4747 * Interface used to listen the active country code changed event. 4748 * @hide 4749 */ 4750 @SystemApi 4751 public interface ActiveCountryCodeChangedCallback { 4752 /** 4753 * Called when the country code used by the Wi-Fi subsystem has changed. 4754 * 4755 * @param countryCode An ISO-3166-alpha2 country code which is 2-Character alphanumeric. 4756 */ onActiveCountryCodeChanged(@onNull String countryCode)4757 void onActiveCountryCodeChanged(@NonNull String countryCode); 4758 4759 /** 4760 * Called when the Wi-Fi subsystem does not have an active country code. 4761 * This can happen when Wi-Fi is disabled. 4762 */ onCountryCodeInactive()4763 void onCountryCodeInactive(); 4764 } 4765 4766 /** 4767 * Add the provided callback for the active country code changed event. 4768 * Caller will receive either 4769 * {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)} 4770 * or {@link WifiManager.ActiveCountryCodeChangedCallback#onCountryCodeInactive()} 4771 * on registration. 4772 * 4773 * Note: When the global location setting is off or the caller does not have runtime location 4774 * permission, caller will not receive the callback even if caller register callback succeeded. 4775 * 4776 * 4777 * Caller can remove a previously registered callback using 4778 * {@link WifiManager#unregisterActiveCountryCodeChangedCallback( 4779 * ActiveCountryCodeChangedCallback)}. 4780 * 4781 * <p> 4782 * Note: 4783 * The value provided by 4784 * {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)} 4785 * may be different from the returned value from {@link WifiManager#getCountryCode()} even if 4786 * the Wi-Fi subsystem is active. See: {@link WifiManager#getCountryCode()} for details. 4787 * </p> 4788 * 4789 * @param executor The Executor on which to execute the callbacks. 4790 * @param callback callback for the driver country code changed events. 4791 * @hide 4792 */ 4793 @SystemApi 4794 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 4795 @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) registerActiveCountryCodeChangedCallback( @onNull @allbackExecutor Executor executor, @NonNull ActiveCountryCodeChangedCallback callback)4796 public void registerActiveCountryCodeChangedCallback( 4797 @NonNull @CallbackExecutor Executor executor, 4798 @NonNull ActiveCountryCodeChangedCallback callback) { 4799 if (!SdkLevel.isAtLeastT()) { 4800 throw new UnsupportedOperationException(); 4801 } 4802 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 4803 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 4804 if (mVerboseLoggingEnabled) { 4805 Log.d(TAG, "registerActiveCountryCodeChangedCallback: callback=" + callback 4806 + ", executor=" + executor); 4807 } 4808 final int callbackIdentifier = System.identityHashCode(callback); 4809 synchronized (sActiveCountryCodeChangedCallbackMap) { 4810 try { 4811 IOnWifiDriverCountryCodeChangedListener.Stub binderListener = 4812 new OnDriverCountryCodeChangedProxy(executor, callback); 4813 sActiveCountryCodeChangedCallbackMap.put(callbackIdentifier, 4814 binderListener); 4815 mService.registerDriverCountryCodeChangedListener(binderListener, 4816 mContext.getOpPackageName(), mContext.getAttributionTag()); 4817 } catch (RemoteException e) { 4818 sActiveCountryCodeChangedCallbackMap.remove(callbackIdentifier); 4819 throw e.rethrowFromSystemServer(); 4820 } 4821 } 4822 } 4823 4824 /** 4825 * Allow callers to remove a previously registered listener. After calling this method, 4826 * applications will no longer receive the active country code changed events through that 4827 * callback. 4828 * 4829 * @param callback Callback to remove the active country code changed events. 4830 * 4831 * @hide 4832 */ 4833 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 4834 @SystemApi unregisterActiveCountryCodeChangedCallback( @onNull ActiveCountryCodeChangedCallback callback)4835 public void unregisterActiveCountryCodeChangedCallback( 4836 @NonNull ActiveCountryCodeChangedCallback callback) { 4837 if (!SdkLevel.isAtLeastT()) { 4838 throw new UnsupportedOperationException(); 4839 } 4840 if (callback == null) throw new IllegalArgumentException("Callback cannot be null"); 4841 if (mVerboseLoggingEnabled) { 4842 Log.d(TAG, "unregisterActiveCountryCodeChangedCallback: callback=" + callback); 4843 } 4844 final int callbackIdentifier = System.identityHashCode(callback); 4845 synchronized (sActiveCountryCodeChangedCallbackMap) { 4846 try { 4847 if (!sActiveCountryCodeChangedCallbackMap.contains(callbackIdentifier)) { 4848 Log.w(TAG, "Unknown external listener " + callbackIdentifier); 4849 return; 4850 } 4851 mService.unregisterDriverCountryCodeChangedListener( 4852 sActiveCountryCodeChangedCallbackMap.get(callbackIdentifier)); 4853 } catch (RemoteException e) { 4854 throw e.rethrowFromSystemServer(); 4855 } finally { 4856 sActiveCountryCodeChangedCallbackMap.remove(callbackIdentifier); 4857 } 4858 } 4859 } 4860 4861 /** 4862 * Interface used to listen to changes in current network state. 4863 * @hide 4864 */ 4865 @SystemApi 4866 public interface WifiNetworkStateChangedListener { 4867 /** @hide */ 4868 @Retention(RetentionPolicy.SOURCE) 4869 @IntDef(prefix = {"WIFI_ROLE_CLIENT_"}, value = { 4870 WIFI_ROLE_CLIENT_PRIMARY, 4871 WIFI_ROLE_CLIENT_SECONDARY_INTERNET, 4872 WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY 4873 }) 4874 @interface WifiClientModeRole {} 4875 4876 /** 4877 * A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}. 4878 * Represents the primary Client Mode Manager which is mostly used for internet, but could 4879 * also be used for other use-cases such as local only connections. 4880 **/ 4881 int WIFI_ROLE_CLIENT_PRIMARY = 1; 4882 /** 4883 * A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}. 4884 * Represents a Client Mode Manager dedicated for the secondary internet use-case. 4885 **/ 4886 int WIFI_ROLE_CLIENT_SECONDARY_INTERNET = 2; 4887 /** 4888 * A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}. 4889 * Represents a Client Mode Manager dedicated for the local only connection use-case. 4890 **/ 4891 int WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY = 3; 4892 4893 /** @hide */ 4894 @Retention(RetentionPolicy.SOURCE) 4895 @IntDef(prefix = {"WIFI_NETWORK_STATUS_"}, value = { 4896 WIFI_NETWORK_STATUS_IDLE, 4897 WIFI_NETWORK_STATUS_SCANNING, 4898 WIFI_NETWORK_STATUS_CONNECTING, 4899 WIFI_NETWORK_STATUS_AUTHENTICATING, 4900 WIFI_NETWORK_STATUS_OBTAINING_IPADDR, 4901 WIFI_NETWORK_STATUS_CONNECTED, 4902 WIFI_NETWORK_STATUS_DISCONNECTED, 4903 WIFI_NETWORK_STATUS_FAILED 4904 }) 4905 @interface WifiNetworkState {} 4906 4907 /** 4908 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4909 * Supplicant is in uninitialized state. 4910 **/ 4911 int WIFI_NETWORK_STATUS_IDLE = 1; 4912 /** 4913 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4914 * Supplicant is scanning. 4915 **/ 4916 int WIFI_NETWORK_STATUS_SCANNING = 2; 4917 /** 4918 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4919 * L2 connection is in progress. 4920 **/ 4921 int WIFI_NETWORK_STATUS_CONNECTING = 3; 4922 /** 4923 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4924 * L2 connection 4 way handshake. 4925 **/ 4926 int WIFI_NETWORK_STATUS_AUTHENTICATING = 4; 4927 /** 4928 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4929 * L2 connection complete. Obtaining IP address. 4930 **/ 4931 int WIFI_NETWORK_STATUS_OBTAINING_IPADDR = 5; 4932 /** 4933 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4934 * L3 connection is complete. 4935 **/ 4936 int WIFI_NETWORK_STATUS_CONNECTED = 6; 4937 /** 4938 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4939 * Network disconnected. 4940 **/ 4941 int WIFI_NETWORK_STATUS_DISCONNECTED = 7; 4942 /** 4943 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4944 * A pseudo-state that should normally never be seen. 4945 **/ 4946 int WIFI_NETWORK_STATUS_FAILED = 8; 4947 4948 4949 /** 4950 * Provides network state changes per client mode role. 4951 * @param cmmRole the role of the wifi client mode manager having the state change. 4952 * One of {@link WifiClientModeRole}. 4953 * @param state the wifi network state specified by one of {@link WifiNetworkState}. 4954 */ onWifiNetworkStateChanged(@ifiClientModeRole int cmmRole, @WifiNetworkState int state)4955 void onWifiNetworkStateChanged(@WifiClientModeRole int cmmRole, 4956 @WifiNetworkState int state); 4957 } 4958 4959 /** 4960 * Helper class to support wifi network state changed listener. 4961 */ 4962 private static class OnWifiNetworkStateChangedProxy 4963 extends IWifiNetworkStateChangedListener.Stub { 4964 4965 @NonNull private Executor mExecutor; 4966 @NonNull private WifiNetworkStateChangedListener mListener; 4967 OnWifiNetworkStateChangedProxy(@onNull Executor executor, @NonNull WifiNetworkStateChangedListener listener)4968 OnWifiNetworkStateChangedProxy(@NonNull Executor executor, 4969 @NonNull WifiNetworkStateChangedListener listener) { 4970 Objects.requireNonNull(executor); 4971 Objects.requireNonNull(listener); 4972 mExecutor = executor; 4973 mListener = listener; 4974 } 4975 4976 @Override onWifiNetworkStateChanged(int cmmRole, int state)4977 public void onWifiNetworkStateChanged(int cmmRole, int state) { 4978 Log.i(TAG, "OnWifiNetworkStateChangedProxy: onWifiNetworkStateChanged: " 4979 + cmmRole + ", " + state); 4980 Binder.clearCallingIdentity(); 4981 mExecutor.execute(() -> mListener.onWifiNetworkStateChanged(cmmRole, state)); 4982 } 4983 } 4984 4985 /** 4986 * Add a listener to listen to Wi-Fi network state changes on available client mode roles 4987 * specified in {@link WifiNetworkStateChangedListener.WifiClientModeRole}. 4988 * When wifi state changes such as connected/disconnect happens, results will be delivered via 4989 * {@link WifiNetworkStateChangedListener#onWifiNetworkStateChanged(int, int)}. 4990 * 4991 * @param executor The Executor on which to execute the callbacks. 4992 * @param listener listener for the network status updates. 4993 * @throws SecurityException if the caller is missing required permissions. 4994 * @throws IllegalArgumentException if incorrect input arguments are provided. 4995 * @hide 4996 */ 4997 @SystemApi 4998 @RequiresPermission(Manifest.permission.NETWORK_SETTINGS) addWifiNetworkStateChangedListener(@onNull @allbackExecutor Executor executor, @NonNull WifiNetworkStateChangedListener listener)4999 public void addWifiNetworkStateChangedListener(@NonNull @CallbackExecutor Executor executor, 5000 @NonNull WifiNetworkStateChangedListener listener) { 5001 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 5002 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 5003 if (mVerboseLoggingEnabled) { 5004 Log.d(TAG, "addWifiNetworkStateChangedListener: listener=" + listener 5005 + ", executor=" + executor); 5006 } 5007 final int listenerIdentifier = System.identityHashCode(listener); 5008 synchronized (sOnWifiNetworkStateChangedListenerMap) { 5009 try { 5010 IWifiNetworkStateChangedListener.Stub listenerProxy = 5011 new OnWifiNetworkStateChangedProxy(executor, listener); 5012 sOnWifiNetworkStateChangedListenerMap.put(listenerIdentifier, 5013 listenerProxy); 5014 mService.addWifiNetworkStateChangedListener(listenerProxy); 5015 } catch (RemoteException e) { 5016 sOnWifiNetworkStateChangedListenerMap.remove(listenerIdentifier); 5017 throw e.rethrowFromSystemServer(); 5018 } 5019 } 5020 } 5021 5022 /** 5023 * Remove a listener added using 5024 * {@link #addWifiNetworkStateChangedListener(Executor, WifiNetworkStateChangedListener)}. 5025 * @param listener the listener to be removed. 5026 * @throws IllegalArgumentException if incorrect input arguments are provided. 5027 * @hide 5028 */ 5029 @SystemApi 5030 @RequiresApi(Build.VERSION_CODES.TIRAMISU) removeWifiNetworkStateChangedListener( @onNull WifiNetworkStateChangedListener listener)5031 public void removeWifiNetworkStateChangedListener( 5032 @NonNull WifiNetworkStateChangedListener listener) { 5033 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 5034 if (mVerboseLoggingEnabled) { 5035 Log.d(TAG, "removeWifiNetworkStateChangedListener: listener=" + listener); 5036 } 5037 final int listenerIdentifier = System.identityHashCode(listener); 5038 synchronized (sOnWifiNetworkStateChangedListenerMap) { 5039 try { 5040 if (!sOnWifiNetworkStateChangedListenerMap.contains(listenerIdentifier)) { 5041 Log.w(TAG, "Unknown external listener " + listenerIdentifier); 5042 return; 5043 } 5044 mService.removeWifiNetworkStateChangedListener( 5045 sOnWifiNetworkStateChangedListenerMap.get(listenerIdentifier)); 5046 } catch (RemoteException e) { 5047 throw e.rethrowFromSystemServer(); 5048 } finally { 5049 sOnWifiNetworkStateChangedListenerMap.remove(listenerIdentifier); 5050 } 5051 } 5052 } 5053 5054 /** 5055 * Get the country code as resolved by the Wi-Fi framework. 5056 * The Wi-Fi framework uses multiple sources to resolve a country code 5057 * - in order of priority (high to low): 5058 * 1. Override country code set by {@link WifiManager#setOverrideCountryCode(String)} 5059 * and cleared by {@link WifiManager#clearOverrideCountryCode()}. Typically only used 5060 * for testing. 5061 * 2. Country code supplied by the telephony module. Typically provided from the 5062 * current network or from emergency cell information. 5063 * 3. Country code supplied by the wifi driver module. (802.11d) 5064 * 4. Default country code set either via {@code ro.boot.wificountrycode} 5065 * or the {@link WifiManager#setDefaultCountryCode(String)}. 5066 * 5067 * <p> 5068 * Note: 5069 * This method returns the Country Code value used by the framework - even if not currently 5070 * used by the Wi-Fi subsystem. I.e. the returned value from this API may be different from the 5071 * value provided by 5072 * {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)}. 5073 * Such a difference may happen when there is an ongoing network connection (STA, AP, Direct, 5074 * or Aware) and the Wi-Fi subsystem does not support dynamic updates - at that point the 5075 * framework may defer setting the Country Code to the Wi-Fi subsystem. 5076 * </p> 5077 * @return the country code in ISO 3166 alpha-2 (2-letter) upper format, 5078 * or null if there is no country code configured. 5079 * 5080 * @hide 5081 */ 5082 @Nullable 5083 @SystemApi 5084 @RequiresPermission(anyOf = { 5085 android.Manifest.permission.NETWORK_SETTINGS, 5086 android.Manifest.permission.ACCESS_COARSE_LOCATION 5087 }) getCountryCode()5088 public String getCountryCode() { 5089 try { 5090 return mService.getCountryCode(mContext.getOpPackageName(), 5091 mContext.getAttributionTag()); 5092 } catch (RemoteException e) { 5093 throw e.rethrowFromSystemServer(); 5094 } 5095 } 5096 5097 /** 5098 * Set the override country code - may be used for testing. See the country code resolution 5099 * order and format in {@link #getCountryCode()}. 5100 * @param country A 2-Character alphanumeric country code. 5101 * @see #getCountryCode(). 5102 * 5103 * @hide 5104 */ 5105 @RequiresApi(Build.VERSION_CODES.S) 5106 @SystemApi 5107 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) setOverrideCountryCode(@onNull String country)5108 public void setOverrideCountryCode(@NonNull String country) { 5109 try { 5110 mService.setOverrideCountryCode(country); 5111 } catch (RemoteException e) { 5112 throw e.rethrowFromSystemServer(); 5113 } 5114 } 5115 5116 /** 5117 * This clears the override country code which was previously set by 5118 * {@link WifiManager#setOverrideCountryCode(String)} method. 5119 * @see #getCountryCode(). 5120 * 5121 * @hide 5122 */ 5123 @RequiresApi(Build.VERSION_CODES.S) 5124 @SystemApi 5125 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) clearOverrideCountryCode()5126 public void clearOverrideCountryCode() { 5127 try { 5128 mService.clearOverrideCountryCode(); 5129 } catch (RemoteException e) { 5130 throw e.rethrowFromSystemServer(); 5131 } 5132 } 5133 /** 5134 * Used to configure the default country code. See {@link #getCountryCode()} for resolution 5135 * method of the country code. 5136 * @param country A 2-character alphanumeric country code. 5137 * @see #getCountryCode(). 5138 * 5139 * @hide 5140 */ 5141 @RequiresApi(Build.VERSION_CODES.S) 5142 @SystemApi 5143 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) setDefaultCountryCode(@onNull String country)5144 public void setDefaultCountryCode(@NonNull String country) { 5145 try { 5146 mService.setDefaultCountryCode(country); 5147 } catch (RemoteException e) { 5148 throw e.rethrowFromSystemServer(); 5149 } 5150 } 5151 5152 /** 5153 * Return the DHCP-assigned addresses from the last successful DHCP request, 5154 * if any. 5155 * 5156 * @return the DHCP information 5157 * 5158 * @deprecated Use the methods on {@link android.net.LinkProperties} which can be obtained 5159 * either via {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)} or 5160 * {@link ConnectivityManager#getLinkProperties(Network)}. 5161 * 5162 * <p> 5163 * <b>Compatibility Notes:</b> 5164 * <li>On devices supporting concurrent connections (indicated via 5165 * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc), this API will return 5166 * the details of the internet providing connection (if any) to all apps, except for the apps 5167 * that triggered the creation of the concurrent connection. For such apps, this API will return 5168 * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will 5169 * trigger a concurrent connection on supported devices and hence this API will provide 5170 * details of their peer to peer connection (not the internet providing connection). This 5171 * is to maintain backwards compatibility with behavior on single STA devices.</li> 5172 * </p> 5173 */ 5174 @Deprecated getDhcpInfo()5175 public DhcpInfo getDhcpInfo() { 5176 try { 5177 return mService.getDhcpInfo(mContext.getOpPackageName()); 5178 } catch (RemoteException e) { 5179 throw e.rethrowFromSystemServer(); 5180 } 5181 } 5182 5183 /** 5184 * Enable or disable Wi-Fi. 5185 * <p> 5186 * Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE} 5187 * permission to toggle wifi. 5188 * 5189 * @param enabled {@code true} to enable, {@code false} to disable. 5190 * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is 5191 * either already in the requested state, or in progress toward the requested state. 5192 * @throws SecurityException if the caller is missing required permissions. 5193 * 5194 * @deprecated Starting with Build.VERSION_CODES#Q, applications are not allowed to 5195 * enable/disable Wi-Fi. 5196 * <b>Compatibility Note:</b> For applications targeting 5197 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 5198 * {@code false}. If apps are targeting an older SDK ({@link android.os.Build.VERSION_CODES#P} 5199 * or below), they can continue to use this API. 5200 * <p> 5201 * Deprecation Exemptions: 5202 * <ul> 5203 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 5204 * </ul> 5205 * 5206 * Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, DO and a profile owner of 5207 * an organization owned device may set a user restriction (DISALLOW_CHANGE_WIFI_STATE) 5208 * to only allow DO/PO to use this API. 5209 */ 5210 @Deprecated setWifiEnabled(boolean enabled)5211 public boolean setWifiEnabled(boolean enabled) { 5212 try { 5213 return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); 5214 } catch (RemoteException e) { 5215 throw e.rethrowFromSystemServer(); 5216 } 5217 } 5218 5219 /** 5220 * Abstract callback class for applications to receive updates about the Wi-Fi subsystem 5221 * restarting. The Wi-Fi subsystem can restart due to internal recovery mechanisms or via user 5222 * action. 5223 */ 5224 @RequiresApi(Build.VERSION_CODES.S) 5225 public abstract static class SubsystemRestartTrackingCallback { 5226 private final SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy mProxy; 5227 SubsystemRestartTrackingCallback()5228 public SubsystemRestartTrackingCallback() { 5229 mProxy = new SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy(); 5230 } 5231 5232 /*package*/ @NonNull getProxy()5233 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy getProxy() { 5234 return mProxy; 5235 } 5236 5237 /** 5238 * Indicates that the Wi-Fi subsystem is about to restart. 5239 */ onSubsystemRestarting()5240 public abstract void onSubsystemRestarting(); 5241 5242 /** 5243 * Indicates that the Wi-Fi subsystem has restarted. 5244 */ onSubsystemRestarted()5245 public abstract void onSubsystemRestarted(); 5246 5247 private static class SubsystemRestartCallbackProxy extends ISubsystemRestartCallback.Stub { 5248 private final Object mLock = new Object(); 5249 @Nullable 5250 @GuardedBy("mLock") 5251 private Executor mExecutor; 5252 @Nullable 5253 @GuardedBy("mLock") 5254 private SubsystemRestartTrackingCallback mCallback; 5255 SubsystemRestartCallbackProxy()5256 SubsystemRestartCallbackProxy() { 5257 mExecutor = null; 5258 mCallback = null; 5259 } 5260 initProxy(@onNull Executor executor, @NonNull SubsystemRestartTrackingCallback callback)5261 /*package*/ void initProxy(@NonNull Executor executor, 5262 @NonNull SubsystemRestartTrackingCallback callback) { 5263 synchronized (mLock) { 5264 mExecutor = executor; 5265 mCallback = callback; 5266 } 5267 } 5268 cleanUpProxy()5269 /*package*/ void cleanUpProxy() { 5270 synchronized (mLock) { 5271 mExecutor = null; 5272 mCallback = null; 5273 } 5274 } 5275 5276 @Override onSubsystemRestarting()5277 public void onSubsystemRestarting() { 5278 Executor executor; 5279 SubsystemRestartTrackingCallback callback; 5280 synchronized (mLock) { 5281 executor = mExecutor; 5282 callback = mCallback; 5283 } 5284 if (executor == null || callback == null) { 5285 return; 5286 } 5287 Binder.clearCallingIdentity(); 5288 executor.execute(callback::onSubsystemRestarting); 5289 } 5290 5291 @Override onSubsystemRestarted()5292 public void onSubsystemRestarted() { 5293 Executor executor; 5294 SubsystemRestartTrackingCallback callback; 5295 synchronized (mLock) { 5296 executor = mExecutor; 5297 callback = mCallback; 5298 } 5299 if (executor == null || callback == null) { 5300 return; 5301 } 5302 Binder.clearCallingIdentity(); 5303 executor.execute(callback::onSubsystemRestarted); 5304 } 5305 } 5306 } 5307 5308 /** 5309 * Registers a {@link SubsystemRestartTrackingCallback} to listen to Wi-Fi subsystem restarts. 5310 * The subsystem may restart due to internal recovery mechanisms or via user action. 5311 * 5312 * @see #unregisterSubsystemRestartTrackingCallback(SubsystemRestartTrackingCallback) 5313 * 5314 * @param executor Executor to execute callback on 5315 * @param callback {@link SubsystemRestartTrackingCallback} to register 5316 */ 5317 @RequiresApi(Build.VERSION_CODES.S) 5318 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) registerSubsystemRestartTrackingCallback( @onNull @allbackExecutor Executor executor, @NonNull SubsystemRestartTrackingCallback callback)5319 public void registerSubsystemRestartTrackingCallback( 5320 @NonNull @CallbackExecutor Executor executor, 5321 @NonNull SubsystemRestartTrackingCallback callback) { 5322 if (executor == null) throw new IllegalArgumentException("executor must not be null"); 5323 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5324 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy(); 5325 proxy.initProxy(executor, callback); 5326 try { 5327 mService.registerSubsystemRestartCallback(proxy); 5328 } catch (RemoteException e) { 5329 proxy.cleanUpProxy(); 5330 throw e.rethrowFromSystemServer(); 5331 } 5332 } 5333 5334 /** 5335 * Unregisters a {@link SubsystemRestartTrackingCallback} registered with 5336 * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)} 5337 * 5338 * @param callback {@link SubsystemRestartTrackingCallback} to unregister 5339 */ 5340 @RequiresApi(Build.VERSION_CODES.S) 5341 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) unregisterSubsystemRestartTrackingCallback( @onNull SubsystemRestartTrackingCallback callback)5342 public void unregisterSubsystemRestartTrackingCallback( 5343 @NonNull SubsystemRestartTrackingCallback callback) { 5344 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5345 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy(); 5346 try { 5347 mService.unregisterSubsystemRestartCallback(proxy); 5348 } catch (RemoteException e) { 5349 throw e.rethrowFromSystemServer(); 5350 } finally { 5351 proxy.cleanUpProxy(); 5352 } 5353 } 5354 5355 /** 5356 * Restart the Wi-Fi subsystem. 5357 * 5358 * Restarts the Wi-Fi subsystem - effectively disabling it and re-enabling it. All existing 5359 * Access Point (AP) associations are torn down, all Soft APs are disabled, Wi-Fi Direct and 5360 * Wi-Fi Aware are disabled. 5361 * 5362 * The state of the system after restart is not guaranteed to match its state before the API is 5363 * called - for instance the device may associate to a different Access Point (AP), and tethered 5364 * hotspots may or may not be restored. 5365 * 5366 * Use the 5367 * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)} 5368 * to track the operation. 5369 * 5370 * @hide 5371 */ 5372 @RequiresApi(Build.VERSION_CODES.S) 5373 @SystemApi 5374 @RequiresPermission(android.Manifest.permission.RESTART_WIFI_SUBSYSTEM) restartWifiSubsystem()5375 public void restartWifiSubsystem() { 5376 try { 5377 mService.restartWifiSubsystem(); 5378 } catch (RemoteException e) { 5379 throw e.rethrowFromSystemServer(); 5380 } 5381 } 5382 5383 /** 5384 * Gets the Wi-Fi enabled state. 5385 * @return One of {@link #WIFI_STATE_DISABLED}, 5386 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 5387 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 5388 * @see #isWifiEnabled() 5389 */ getWifiState()5390 public int getWifiState() { 5391 try { 5392 return mService.getWifiEnabledState(); 5393 } catch (RemoteException e) { 5394 throw e.rethrowFromSystemServer(); 5395 } 5396 } 5397 5398 /** 5399 * Return whether Wi-Fi is enabled or disabled. 5400 * @return {@code true} if Wi-Fi is enabled 5401 * @see #getWifiState() 5402 */ isWifiEnabled()5403 public boolean isWifiEnabled() { 5404 return getWifiState() == WIFI_STATE_ENABLED; 5405 } 5406 5407 /** 5408 * Register a callback for Wi-Fi state. See {@link WifiStateChangedListener}. 5409 * Caller will receive the event when the Wi-Fi state changes. 5410 * Caller can remove a previously registered callback using 5411 * {@link WifiManager#removeWifiStateChangedListener(WifiStateChangedListener)} 5412 * 5413 * @param executor Executor to execute listener callback on 5414 * @param listener Listener to register 5415 */ 5416 @FlaggedApi(Flags.FLAG_WIFI_STATE_CHANGED_LISTENER) 5417 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) addWifiStateChangedListener(@onNull @allbackExecutor Executor executor, @NonNull WifiStateChangedListener listener)5418 public void addWifiStateChangedListener(@NonNull @CallbackExecutor Executor executor, 5419 @NonNull WifiStateChangedListener listener) { 5420 Objects.requireNonNull(executor); 5421 Objects.requireNonNull(listener); 5422 if (mVerboseLoggingEnabled) { 5423 Log.d(TAG, "addWifiStateChangedListener: listener=" + listener 5424 + ", executor=" + executor); 5425 } 5426 final int listenerIdentifier = System.identityHashCode(listener); 5427 synchronized (sWifiStateChangedListenerMap) { 5428 try { 5429 if (sWifiStateChangedListenerMap.contains(listenerIdentifier)) { 5430 Log.w(TAG, "Same listener already registered"); 5431 return; 5432 } 5433 IWifiStateChangedListener.Stub listenerProxy = 5434 new WifiStateChangedListenerProxy(executor, listener); 5435 sWifiStateChangedListenerMap.put(listenerIdentifier, listenerProxy); 5436 mService.addWifiStateChangedListener(listenerProxy); 5437 } catch (RemoteException e) { 5438 sWifiStateChangedListenerMap.remove(listenerIdentifier); 5439 throw e.rethrowFromSystemServer(); 5440 } 5441 } 5442 } 5443 5444 /** 5445 * Unregisters a WifiStateChangedListener from listening on the current Wi-Fi state. 5446 * 5447 * @param listener WifiStateChangedListener to unregister 5448 */ 5449 @FlaggedApi(Flags.FLAG_WIFI_STATE_CHANGED_LISTENER) 5450 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) removeWifiStateChangedListener(@onNull WifiStateChangedListener listener)5451 public void removeWifiStateChangedListener(@NonNull WifiStateChangedListener listener) { 5452 Objects.requireNonNull(listener); 5453 if (mVerboseLoggingEnabled) { 5454 Log.d(TAG, "removeWifiStateChangedListener: listener=" + listener); 5455 } 5456 final int listenerIdentifier = System.identityHashCode(listener); 5457 synchronized (sWifiStateChangedListenerMap) { 5458 try { 5459 if (!sWifiStateChangedListenerMap.contains(listenerIdentifier)) { 5460 Log.w(TAG, "Unknown external listener " + listenerIdentifier); 5461 return; 5462 } 5463 mService.removeWifiStateChangedListener( 5464 sWifiStateChangedListenerMap.get(listenerIdentifier)); 5465 } catch (RemoteException e) { 5466 throw e.rethrowFromSystemServer(); 5467 } finally { 5468 sWifiStateChangedListenerMap.remove(listenerIdentifier); 5469 } 5470 } 5471 } 5472 5473 /** 5474 * Listener interface for applications to be notified when the Wi-Fi enabled state changes. 5475 */ 5476 @FlaggedApi(Flags.FLAG_WIFI_STATE_CHANGED_LISTENER) 5477 public interface WifiStateChangedListener { 5478 /** 5479 * Called when the Wi-Fi enabled state changes. 5480 * The new value can be queried via {@link WifiManager#getWifiState()}. 5481 */ onWifiStateChanged()5482 void onWifiStateChanged(); 5483 } 5484 5485 /** 5486 * Listener proxy for WifiStateChangedListener objects. 5487 */ 5488 private static class WifiStateChangedListenerProxy extends IWifiStateChangedListener.Stub { 5489 private Executor mExecutor; 5490 private WifiStateChangedListener mListener; 5491 WifiStateChangedListenerProxy(@onNull Executor executor, @NonNull WifiStateChangedListener listener)5492 WifiStateChangedListenerProxy(@NonNull Executor executor, 5493 @NonNull WifiStateChangedListener listener) { 5494 Objects.requireNonNull(executor); 5495 Objects.requireNonNull(listener); 5496 mExecutor = executor; 5497 mListener = listener; 5498 } 5499 5500 @Override onWifiStateChanged()5501 public void onWifiStateChanged() { 5502 Log.i(TAG, "WifiStateChangedListenerProxy: onWifiStateChanged"); 5503 Binder.clearCallingIdentity(); 5504 mExecutor.execute(() -> mListener.onWifiStateChanged()); 5505 } 5506 } 5507 5508 /** 5509 * Calculates the level of the signal. This should be used any time a signal 5510 * is being shown. 5511 * 5512 * @param rssi The power of the signal measured in RSSI. 5513 * @param numLevels The number of levels to consider in the calculated level. 5514 * @return A level of the signal, given in the range of 0 to numLevels-1 (both inclusive). 5515 * @deprecated Callers should use {@link #calculateSignalLevel(int)} instead to get the 5516 * signal level using the system default RSSI thresholds, or otherwise compute the RSSI level 5517 * themselves using their own formula. 5518 */ 5519 @Deprecated calculateSignalLevel(int rssi, int numLevels)5520 public static int calculateSignalLevel(int rssi, int numLevels) { 5521 if (rssi <= MIN_RSSI) { 5522 return 0; 5523 } else if (rssi >= MAX_RSSI) { 5524 return numLevels - 1; 5525 } else { 5526 float inputRange = (MAX_RSSI - MIN_RSSI); 5527 float outputRange = (numLevels - 1); 5528 return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange); 5529 } 5530 } 5531 5532 /** 5533 * Given a raw RSSI, return the RSSI signal quality rating using the system default RSSI 5534 * quality rating thresholds. 5535 * @param rssi a raw RSSI value, in dBm, usually between -55 and -90 5536 * @return the RSSI signal quality rating, in the range 5537 * [0, {@link #getMaxSignalLevel()}], where 0 is the lowest (worst signal) RSSI 5538 * rating and {@link #getMaxSignalLevel()} is the highest (best signal) RSSI rating. 5539 */ 5540 @IntRange(from = 0) calculateSignalLevel(int rssi)5541 public int calculateSignalLevel(int rssi) { 5542 try { 5543 return mService.calculateSignalLevel(rssi); 5544 } catch (RemoteException e) { 5545 throw e.rethrowFromSystemServer(); 5546 } 5547 } 5548 5549 /** 5550 * Get the system default maximum signal level. 5551 * This is the maximum RSSI level returned by {@link #calculateSignalLevel(int)}. 5552 */ 5553 @IntRange(from = 0) getMaxSignalLevel()5554 public int getMaxSignalLevel() { 5555 return calculateSignalLevel(Integer.MAX_VALUE); 5556 } 5557 5558 /** 5559 * Compares two signal strengths. 5560 * 5561 * @param rssiA The power of the first signal measured in RSSI. 5562 * @param rssiB The power of the second signal measured in RSSI. 5563 * @return Returns <0 if the first signal is weaker than the second signal, 5564 * 0 if the two signals have the same strength, and >0 if the first 5565 * signal is stronger than the second signal. 5566 */ compareSignalLevel(int rssiA, int rssiB)5567 public static int compareSignalLevel(int rssiA, int rssiB) { 5568 return rssiA - rssiB; 5569 } 5570 5571 /** 5572 * Call allowing ConnectivityService to update WifiService with interface mode changes. 5573 * 5574 * @param ifaceName String name of the updated interface, or null to represent all interfaces 5575 * @param mode int representing the new mode, one of: 5576 * {@link #IFACE_IP_MODE_TETHERED}, 5577 * {@link #IFACE_IP_MODE_LOCAL_ONLY}, 5578 * {@link #IFACE_IP_MODE_CONFIGURATION_ERROR}, 5579 * {@link #IFACE_IP_MODE_UNSPECIFIED} 5580 * 5581 * @hide 5582 */ 5583 @SystemApi 5584 @RequiresPermission(anyOf = { 5585 android.Manifest.permission.NETWORK_STACK, 5586 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5587 }) updateInterfaceIpState(@ullable String ifaceName, @IfaceIpMode int mode)5588 public void updateInterfaceIpState(@Nullable String ifaceName, @IfaceIpMode int mode) { 5589 try { 5590 mService.updateInterfaceIpState(ifaceName, mode); 5591 } catch (RemoteException e) { 5592 throw e.rethrowFromSystemServer(); 5593 } 5594 } 5595 5596 /* Wi-Fi/Cellular Coex */ 5597 5598 /** 5599 * Mandatory coex restriction flag for Wi-Fi Direct. 5600 * 5601 * @see #setCoexUnsafeChannels(List, int) 5602 * 5603 * @hide 5604 */ 5605 @SystemApi 5606 @RequiresApi(Build.VERSION_CODES.S) 5607 public static final int COEX_RESTRICTION_WIFI_DIRECT = 0x1 << 0; 5608 5609 /** 5610 * Mandatory coex restriction flag for SoftAP 5611 * 5612 * @see #setCoexUnsafeChannels(List, int) 5613 * 5614 * @hide 5615 */ 5616 @SystemApi 5617 @RequiresApi(Build.VERSION_CODES.S) 5618 public static final int COEX_RESTRICTION_SOFTAP = 0x1 << 1; 5619 5620 /** 5621 * Mandatory coex restriction flag for Wi-Fi Aware. 5622 * 5623 * @see #setCoexUnsafeChannels(List, int) 5624 * 5625 * @hide 5626 */ 5627 @SystemApi 5628 @RequiresApi(Build.VERSION_CODES.S) 5629 public static final int COEX_RESTRICTION_WIFI_AWARE = 0x1 << 2; 5630 5631 /** @hide */ 5632 @RequiresApi(Build.VERSION_CODES.S) 5633 @Retention(RetentionPolicy.SOURCE) 5634 @IntDef(flag = true, prefix = {"COEX_RESTRICTION_"}, value = { 5635 COEX_RESTRICTION_WIFI_DIRECT, 5636 COEX_RESTRICTION_SOFTAP, 5637 COEX_RESTRICTION_WIFI_AWARE 5638 }) 5639 public @interface CoexRestriction {} 5640 5641 /** 5642 * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise. 5643 * 5644 * @hide 5645 */ isDefaultCoexAlgorithmEnabled()5646 public boolean isDefaultCoexAlgorithmEnabled() { 5647 try { 5648 return mService.isDefaultCoexAlgorithmEnabled(); 5649 } catch (RemoteException e) { 5650 throw e.rethrowFromSystemServer(); 5651 } 5652 } 5653 5654 /** 5655 * Specify the list of {@link CoexUnsafeChannel} to propagate through the framework for 5656 * Wi-Fi/Cellular coex channel avoidance if the default algorithm is disabled via overlay 5657 * (i.e. config_wifiCoexDefaultAlgorithmEnabled = false). Otherwise do nothing. 5658 * 5659 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 5660 * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode 5661 * restrictions on the specified channels. If any restrictions are set, 5662 * then the supplied CoexUnsafeChannels should be completely avoided for 5663 * the specified modes, rather than be avoided with best effort. 5664 * 5665 * @hide 5666 */ 5667 @SystemApi 5668 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS) 5669 @RequiresApi(Build.VERSION_CODES.S) setCoexUnsafeChannels( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)5670 public void setCoexUnsafeChannels( 5671 @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions) { 5672 if (unsafeChannels == null) { 5673 throw new IllegalArgumentException("unsafeChannels must not be null"); 5674 } 5675 try { 5676 mService.setCoexUnsafeChannels(unsafeChannels, restrictions); 5677 } catch (RemoteException e) { 5678 throw e.rethrowFromSystemServer(); 5679 } 5680 } 5681 5682 /** 5683 * Registers a CoexCallback to listen on the current CoexUnsafeChannels and restrictions being 5684 * used for Wi-Fi/cellular coex channel avoidance. The callback method 5685 * {@link CoexCallback#onCoexUnsafeChannelsChanged(List, int)} will be called immediately after 5686 * registration to return the current values. 5687 * 5688 * @param executor Executor to execute listener callback on 5689 * @param callback CoexCallback to register 5690 * 5691 * @hide 5692 */ 5693 @SystemApi 5694 @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) 5695 @RequiresApi(Build.VERSION_CODES.S) registerCoexCallback( @onNull @allbackExecutor Executor executor, @NonNull CoexCallback callback)5696 public void registerCoexCallback( 5697 @NonNull @CallbackExecutor Executor executor, @NonNull CoexCallback callback) { 5698 if (executor == null) throw new IllegalArgumentException("executor must not be null"); 5699 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5700 CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); 5701 proxy.initProxy(executor, callback); 5702 try { 5703 mService.registerCoexCallback(proxy); 5704 } catch (RemoteException e) { 5705 throw e.rethrowFromSystemServer(); 5706 } 5707 } 5708 5709 /** 5710 * Unregisters a CoexCallback from listening on the current CoexUnsafeChannels and restrictions 5711 * being used for Wi-Fi/cellular coex channel avoidance. 5712 * @param callback CoexCallback to unregister 5713 * 5714 * @hide 5715 */ 5716 @SystemApi 5717 @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) 5718 @RequiresApi(Build.VERSION_CODES.S) unregisterCoexCallback(@onNull CoexCallback callback)5719 public void unregisterCoexCallback(@NonNull CoexCallback callback) { 5720 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5721 CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); 5722 try { 5723 mService.unregisterCoexCallback(proxy); 5724 } catch (RemoteException e) { 5725 throw e.rethrowFromSystemServer(); 5726 } finally { 5727 proxy.cleanUpProxy(); 5728 } 5729 } 5730 5731 /** 5732 * Abstract callback class for applications to receive updates about current CoexUnsafeChannels 5733 * for Wi-Fi/Cellular coex channel avoidance. 5734 * 5735 * @hide 5736 */ 5737 @SystemApi 5738 @RequiresApi(Build.VERSION_CODES.S) 5739 public abstract static class CoexCallback { 5740 private final CoexCallbackProxy mCoexCallbackProxy; 5741 CoexCallback()5742 public CoexCallback() { 5743 if (!SdkLevel.isAtLeastS()) { 5744 throw new UnsupportedOperationException(); 5745 } 5746 mCoexCallbackProxy = new CoexCallbackProxy(); 5747 } 5748 5749 /*package*/ @NonNull getProxy()5750 CoexCallbackProxy getProxy() { 5751 return mCoexCallbackProxy; 5752 } 5753 5754 /** 5755 * This indicates the current CoexUnsafeChannels and restrictions calculated by the default 5756 * coex algorithm if config_wifiCoexDefaultAlgorithmEnabled is {@code true}. Otherwise, the 5757 * values will match the ones supplied to {@link #setCoexUnsafeChannels(List, int)}. 5758 * 5759 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 5760 * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode 5761 * restrictions on the specified channels. If any restrictions are set, 5762 * then the supplied CoexUnsafeChannels should be completely avoided for 5763 * the specified modes, rather than be avoided with best effort. 5764 */ onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)5765 public abstract void onCoexUnsafeChannelsChanged( 5766 @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions); 5767 5768 /** 5769 * Callback proxy for CoexCallback objects. 5770 */ 5771 private static class CoexCallbackProxy extends ICoexCallback.Stub { 5772 private final Object mLock = new Object(); 5773 @Nullable @GuardedBy("mLock") private Executor mExecutor; 5774 @Nullable @GuardedBy("mLock") private CoexCallback mCallback; 5775 CoexCallbackProxy()5776 CoexCallbackProxy() { 5777 mExecutor = null; 5778 mCallback = null; 5779 } 5780 initProxy(@onNull Executor executor, @NonNull CoexCallback callback)5781 /*package*/ void initProxy(@NonNull Executor executor, 5782 @NonNull CoexCallback callback) { 5783 synchronized (mLock) { 5784 mExecutor = executor; 5785 mCallback = callback; 5786 } 5787 } 5788 cleanUpProxy()5789 /*package*/ void cleanUpProxy() { 5790 synchronized (mLock) { 5791 mExecutor = null; 5792 mCallback = null; 5793 } 5794 } 5795 5796 @Override onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)5797 public void onCoexUnsafeChannelsChanged( 5798 @NonNull List<CoexUnsafeChannel> unsafeChannels, 5799 @CoexRestriction int restrictions) { 5800 Executor executor; 5801 CoexCallback callback; 5802 synchronized (mLock) { 5803 executor = mExecutor; 5804 callback = mCallback; 5805 } 5806 if (executor == null || callback == null) { 5807 return; 5808 } 5809 Binder.clearCallingIdentity(); 5810 executor.execute(() -> 5811 callback.onCoexUnsafeChannelsChanged(unsafeChannels, restrictions)); 5812 } 5813 } 5814 } 5815 5816 /** 5817 * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. 5818 * Note that starting Soft AP mode may disable station mode operation if the device does not 5819 * support concurrency. 5820 * @param wifiConfig SSID, security and channel details as part of WifiConfiguration, or null to 5821 * use the persisted Soft AP configuration that was previously set using 5822 * {@link #setWifiApConfiguration(WifiConfiguration)}. 5823 * @return {@code true} if the operation succeeded, {@code false} otherwise 5824 * 5825 * @hide 5826 */ 5827 @RequiresPermission(anyOf = { 5828 android.Manifest.permission.NETWORK_STACK, 5829 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5830 }) startSoftAp(@ullable WifiConfiguration wifiConfig)5831 public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) { 5832 try { 5833 return mService.startSoftAp(wifiConfig, mContext.getOpPackageName()); 5834 } catch (RemoteException e) { 5835 throw e.rethrowFromSystemServer(); 5836 } 5837 } 5838 5839 /** 5840 * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. 5841 * Note that starting Soft AP mode may disable station mode operation if the device does not 5842 * support concurrency. 5843 * 5844 * Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid 5845 * unexpected error due to invalid configuration. 5846 * 5847 * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP, or 5848 * null to use the persisted Soft AP configuration that was previously set 5849 * using {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)}. 5850 * @return {@code true} if the operation succeeded, {@code false} otherwise 5851 * 5852 * @deprecated Use {@link #startTetheredHotspot(TetheringManager.TetheringRequest)} 5853 * instead. 5854 * @hide 5855 */ 5856 @SystemApi 5857 @RequiresPermission(anyOf = { 5858 android.Manifest.permission.NETWORK_STACK, 5859 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5860 }) 5861 @Deprecated startTetheredHotspot(@ullable SoftApConfiguration softApConfig)5862 public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) { 5863 try { 5864 return mService.startTetheredHotspot(softApConfig, mContext.getOpPackageName()); 5865 } catch (RemoteException e) { 5866 throw e.rethrowFromSystemServer(); 5867 } 5868 } 5869 5870 /** 5871 * Start Soft AP (hotspot) mode for tethering purposes with the specified TetheringRequest. 5872 * Note that starting Soft AP mode may disable station mode operation if the device does not 5873 * support concurrency. 5874 * 5875 * @param request A valid TetheringRequest specifying the configuration of the SAP. 5876 * @param executor Executor to run the callback on. 5877 * @param callback Callback to listen on state changes for this specific request. 5878 * @hide 5879 */ 5880 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 5881 @SystemApi 5882 @RequiresPermission(anyOf = { 5883 android.Manifest.permission.NETWORK_STACK, 5884 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5885 }) startTetheredHotspot(@onNull TetheringManager.TetheringRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull SoftApCallback callback)5886 public void startTetheredHotspot(@NonNull TetheringManager.TetheringRequest request, 5887 @NonNull @CallbackExecutor Executor executor, @NonNull SoftApCallback callback) { 5888 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 5889 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 5890 ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback, 5891 IFACE_IP_MODE_TETHERED); 5892 try { 5893 mService.startTetheredHotspotRequest(request, binderCallback, 5894 mContext.getOpPackageName()); 5895 } catch (RemoteException e) { 5896 throw e.rethrowFromSystemServer(); 5897 } 5898 } 5899 5900 /** 5901 * Stop SoftAp mode. 5902 * Note that stopping softap mode will restore the previous wifi mode. 5903 * @return {@code true} if the operation succeeds, {@code false} otherwise 5904 * 5905 * @hide 5906 */ 5907 @SystemApi 5908 @RequiresPermission(anyOf = { 5909 android.Manifest.permission.NETWORK_STACK, 5910 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5911 }) stopSoftAp()5912 public boolean stopSoftAp() { 5913 try { 5914 return mService.stopSoftAp(); 5915 } catch (RemoteException e) { 5916 throw e.rethrowFromSystemServer(); 5917 } 5918 } 5919 5920 /** 5921 * Check if input configuration is valid. 5922 * 5923 * @param config a configuration would like to be checked. 5924 * @return true if config is valid, otherwise false. 5925 */ validateSoftApConfiguration(@onNull SoftApConfiguration config)5926 public boolean validateSoftApConfiguration(@NonNull SoftApConfiguration config) { 5927 if (config == null) { 5928 throw new IllegalArgumentException(TAG + ": config can not be null"); 5929 } 5930 try { 5931 return mService.validateSoftApConfiguration(config); 5932 } catch (RemoteException e) { 5933 throw e.rethrowFromSystemServer(); 5934 } 5935 } 5936 5937 /** 5938 * Request a local only hotspot that an application can use to communicate between co-located 5939 * devices connected to the created WiFi hotspot. The network created by this method will not 5940 * have Internet access. Each application can make a single request for the hotspot, but 5941 * multiple applications could be requesting the hotspot at the same time. When multiple 5942 * applications have successfully registered concurrently, they will be sharing the underlying 5943 * hotspot. {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} is called 5944 * when the hotspot is ready for use by the application. 5945 * <p> 5946 * Each application can make a single active call to this method. The {@link 5947 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} callback supplies the 5948 * requestor with a {@link LocalOnlyHotspotReservation} that contains a 5949 * {@link SoftApConfiguration} with the SSID, security type and credentials needed to connect 5950 * to the hotspot. Communicating this information is up to the application. 5951 * <p> 5952 * If the LocalOnlyHotspot cannot be created, the {@link LocalOnlyHotspotCallback#onFailed(int)} 5953 * method will be called. Example failures include errors bringing up the network or if 5954 * there is an incompatible operating mode. For example, if the user is currently using Wifi 5955 * Tethering to provide an upstream to another device, LocalOnlyHotspot may not start due to 5956 * an incompatible mode. The possible error codes include: 5957 * {@link LocalOnlyHotspotCallback#ERROR_NO_CHANNEL}, 5958 * {@link LocalOnlyHotspotCallback#ERROR_GENERIC}, 5959 * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE} and 5960 * {@link LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED}. 5961 * <p> 5962 * Internally, requests will be tracked to prevent the hotspot from being torn down while apps 5963 * are still using it. The {@link LocalOnlyHotspotReservation} object passed in the {@link 5964 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call should be closed when 5965 * the LocalOnlyHotspot is no longer needed using {@link LocalOnlyHotspotReservation#close()}. 5966 * Since the hotspot may be shared among multiple applications, removing the final registered 5967 * application request will trigger the hotspot teardown. This means that applications should 5968 * not listen to broadcasts containing wifi state to determine if the hotspot was stopped after 5969 * they are done using it. Additionally, once {@link LocalOnlyHotspotReservation#close()} is 5970 * called, applications will not receive callbacks of any kind. 5971 * <p> 5972 * Applications should be aware that the user may also stop the LocalOnlyHotspot through the 5973 * Settings UI; it is not guaranteed to stay up as long as there is a requesting application. 5974 * The requestors will be notified of this case via 5975 * {@link LocalOnlyHotspotCallback#onStopped()}. Other cases may arise where the hotspot is 5976 * torn down (Emergency mode, etc). Application developers should be aware that it can stop 5977 * unexpectedly, but they will receive a notification if they have properly registered. 5978 * <p> 5979 * Applications should also be aware that this network will be shared with other applications. 5980 * Applications are responsible for protecting their data on this network (e.g. TLS). 5981 * <p> 5982 * Applications targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later need to have 5983 * the following permissions: {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 5984 * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}. 5985 * Applications targeting {@link Build.VERSION_CODES#S} or prior SDK levels need to have the 5986 * following permissions: {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 5987 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} 5988 * Callers without 5989 * the permissions will trigger a {@link java.lang.SecurityException}. 5990 * <p> 5991 * @param callback LocalOnlyHotspotCallback for the application to receive updates about 5992 * operating status. 5993 * @param handler Handler to be used for callbacks. If the caller passes a null Handler, the 5994 * main thread will be used. 5995 */ 5996 @RequiresPermission(allOf = {CHANGE_WIFI_STATE, ACCESS_FINE_LOCATION, NEARBY_WIFI_DEVICES}, 5997 conditional = true) startLocalOnlyHotspot(LocalOnlyHotspotCallback callback, @Nullable Handler handler)5998 public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback, 5999 @Nullable Handler handler) { 6000 Executor executor = handler == null ? null : new HandlerExecutor(handler); 6001 startLocalOnlyHotspotInternal(null, executor, callback, false); 6002 } 6003 6004 /** 6005 * Starts a local-only hotspot with a specific configuration applied. See 6006 * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}. 6007 * 6008 * Since custom configuration settings may be incompatible with each other, the hotspot started 6009 * through this method cannot coexist with another hotspot created through 6010 * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}. If this is attempted, 6011 * the first hotspot request wins and others receive 6012 * {@link LocalOnlyHotspotCallback#ERROR_GENERIC} through 6013 * {@link LocalOnlyHotspotCallback#onFailed}. 6014 * 6015 * @param config Custom configuration for the hotspot. See {@link SoftApConfiguration}. 6016 * @param executor Executor to run callback methods on. 6017 * @param callback LocalOnlyHotspotCallback for the application to receive updates about 6018 * operating status. 6019 */ 6020 @RequiresPermission(allOf = {CHANGE_WIFI_STATE, NEARBY_WIFI_DEVICES}) 6021 @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS) startLocalOnlyHotspotWithConfiguration(@onNull SoftApConfiguration config, @NonNull @CallbackExecutor Executor executor, @NonNull LocalOnlyHotspotCallback callback)6022 public void startLocalOnlyHotspotWithConfiguration(@NonNull SoftApConfiguration config, 6023 @NonNull @CallbackExecutor Executor executor, 6024 @NonNull LocalOnlyHotspotCallback callback) { 6025 Objects.requireNonNull(config); 6026 Objects.requireNonNull(executor); 6027 Objects.requireNonNull(callback); 6028 startLocalOnlyHotspotInternal(config, executor, callback, false); 6029 } 6030 6031 6032 /** 6033 * Starts a local-only hotspot with a specific configuration applied. See 6034 * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}. 6035 * 6036 * Applications need either {@link android.Manifest.permission#NETWORK_SETUP_WIZARD}, 6037 * {@link android.Manifest.permission#NETWORK_SETTINGS} or 6038 * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} to call this method. 6039 * 6040 * Since custom configuration settings may be incompatible with each other, the hotspot started 6041 * through this method cannot coexist with another hotspot created through 6042 * startLocalOnlyHotspot. If this is attempted, the first hotspot request wins and others 6043 * receive {@link LocalOnlyHotspotCallback#ERROR_GENERIC} through 6044 * {@link LocalOnlyHotspotCallback#onFailed}. 6045 * 6046 * @param config Custom configuration for the hotspot. See {@link SoftApConfiguration}. 6047 * @param executor Executor to run callback methods on, or null to use the main thread. 6048 * @param callback Callback object for updates about hotspot status, or null for no updates. 6049 * @hide 6050 */ 6051 @SystemApi 6052 @RequiresPermission(anyOf = { 6053 android.Manifest.permission.NETWORK_SETTINGS, 6054 android.Manifest.permission.NETWORK_SETUP_WIZARD, 6055 NEARBY_WIFI_DEVICES}) startLocalOnlyHotspot(@onNull SoftApConfiguration config, @Nullable @CallbackExecutor Executor executor, @Nullable LocalOnlyHotspotCallback callback)6056 public void startLocalOnlyHotspot(@NonNull SoftApConfiguration config, 6057 @Nullable @CallbackExecutor Executor executor, 6058 @Nullable LocalOnlyHotspotCallback callback) { 6059 Objects.requireNonNull(config); 6060 startLocalOnlyHotspotInternal(config, executor, callback, true); 6061 } 6062 6063 /** 6064 * Common implementation of both configurable and non-configurable LOHS. 6065 * 6066 * @param config App-specified configuration, or null. When present, additional privileges are 6067 * required, and the hotspot cannot be shared with other clients. 6068 * @param executor Executor to run callback methods on, or null to use the main thread. 6069 * @param callback Callback object for updates about hotspot status, or null for no updates. 6070 */ startLocalOnlyHotspotInternal( @ullable SoftApConfiguration config, @Nullable @CallbackExecutor Executor executor, @Nullable LocalOnlyHotspotCallback callback, boolean isCalledFromSystemApi)6071 private void startLocalOnlyHotspotInternal( 6072 @Nullable SoftApConfiguration config, 6073 @Nullable @CallbackExecutor Executor executor, 6074 @Nullable LocalOnlyHotspotCallback callback, 6075 boolean isCalledFromSystemApi) { 6076 if (executor == null) { 6077 executor = mContext.getMainExecutor(); 6078 } 6079 synchronized (mLock) { 6080 LocalOnlyHotspotCallbackProxy proxy = 6081 new LocalOnlyHotspotCallbackProxy(this, executor, callback); 6082 try { 6083 String packageName = mContext.getOpPackageName(); 6084 String featureId = mContext.getAttributionTag(); 6085 Bundle extras = new Bundle(); 6086 if (SdkLevel.isAtLeastS()) { 6087 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 6088 mContext.getAttributionSource()); 6089 } 6090 int returnCode = mService.startLocalOnlyHotspot(proxy, packageName, featureId, 6091 config, extras, isCalledFromSystemApi); 6092 if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) { 6093 // Send message to the proxy to make sure we call back on the correct thread 6094 proxy.onHotspotFailed(returnCode); 6095 return; 6096 } 6097 mLOHSCallbackProxy = proxy; 6098 } catch (RemoteException e) { 6099 throw e.rethrowFromSystemServer(); 6100 } 6101 } 6102 } 6103 6104 /** 6105 * Cancels a pending local only hotspot request. This can be used by the calling application to 6106 * cancel the existing request if the provided callback has not been triggered. Calling this 6107 * method will be equivalent to closing the returned LocalOnlyHotspotReservation, but it is not 6108 * explicitly required. 6109 * <p> 6110 * When cancelling this request, application developers should be aware that there may still be 6111 * outstanding local only hotspot requests and the hotspot may still start, or continue running. 6112 * Additionally, if a callback was registered, it will no longer be triggered after calling 6113 * cancel. 6114 * 6115 * @hide 6116 */ 6117 @UnsupportedAppUsage cancelLocalOnlyHotspotRequest()6118 public void cancelLocalOnlyHotspotRequest() { 6119 synchronized (mLock) { 6120 stopLocalOnlyHotspot(); 6121 } 6122 } 6123 6124 /** 6125 * Method used to inform WifiService that the LocalOnlyHotspot is no longer needed. This 6126 * method is used by WifiManager to release LocalOnlyHotspotReservations held by calling 6127 * applications and removes the internal tracking for the hotspot request. When all requesting 6128 * applications are finished using the hotspot, it will be stopped and WiFi will return to the 6129 * previous operational mode. 6130 * 6131 * This method should not be called by applications. Instead, they should call the close() 6132 * method on their LocalOnlyHotspotReservation. 6133 */ stopLocalOnlyHotspot()6134 private void stopLocalOnlyHotspot() { 6135 synchronized (mLock) { 6136 if (mLOHSCallbackProxy == null) { 6137 // nothing to do, the callback was already cleaned up. 6138 return; 6139 } 6140 mLOHSCallbackProxy = null; 6141 try { 6142 mService.stopLocalOnlyHotspot(); 6143 } catch (RemoteException e) { 6144 throw e.rethrowFromSystemServer(); 6145 } 6146 } 6147 } 6148 6149 /** 6150 * Registers a callback for local only hotspot. See {@link SoftApCallback}. Caller will receive 6151 * the following callbacks on registration: 6152 * <ul> 6153 * <li> {@link SoftApCallback#onStateChanged(int, int)}</li> 6154 * <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li> 6155 * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li> 6156 * <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li> 6157 * </ul> 6158 * 6159 * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know 6160 * if there are any clients connected to a specific bridged instance of this AP 6161 * (if bridged AP is enabled). 6162 * 6163 * Note: Caller will receive the callback 6164 * {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} 6165 * on registration when there are clients connected to AP. 6166 * 6167 * These will be dispatched on registration to provide the caller with the current state 6168 * (and are not an indication of any current change). Note that receiving an immediate 6169 * WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start 6170 * soft AP has failed. Caller can unregister a previously registered callback using 6171 * {@link #unregisterLocalOnlyHotspotSoftApCallback} 6172 * <p> 6173 * 6174 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 6175 * object. 6176 * @param callback Callback for local only hotspot events 6177 * @hide 6178 */ 6179 @SystemApi 6180 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 6181 @RequiresPermission(NEARBY_WIFI_DEVICES) registerLocalOnlyHotspotSoftApCallback(@onNull @allbackExecutor Executor executor, @NonNull SoftApCallback callback)6182 public void registerLocalOnlyHotspotSoftApCallback(@NonNull @CallbackExecutor Executor executor, 6183 @NonNull SoftApCallback callback) { 6184 if (!SdkLevel.isAtLeastT()) { 6185 throw new UnsupportedOperationException(); 6186 } 6187 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 6188 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 6189 Log.v(TAG, "registerLocalOnlyHotspotSoftApCallback: callback=" + callback + ", executor=" 6190 + executor); 6191 try { 6192 synchronized (sLocalOnlyHotspotSoftApCallbackMap) { 6193 ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback, 6194 IFACE_IP_MODE_LOCAL_ONLY); 6195 sLocalOnlyHotspotSoftApCallbackMap.put(System.identityHashCode(callback), 6196 binderCallback); 6197 Bundle extras = new Bundle(); 6198 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 6199 mContext.getAttributionSource()); 6200 mService.registerLocalOnlyHotspotSoftApCallback(binderCallback, extras); 6201 } 6202 } catch (RemoteException e) { 6203 throw e.rethrowFromSystemServer(); 6204 } 6205 } 6206 6207 /** 6208 * Allow callers to unregister a previously registered callback. After calling this method, 6209 * applications will no longer receive local only hotspot events. 6210 * 6211 * <p> 6212 * 6213 * @param callback Callback to unregister for soft AP events 6214 * 6215 * @hide 6216 */ 6217 @SystemApi 6218 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 6219 @RequiresPermission(NEARBY_WIFI_DEVICES) unregisterLocalOnlyHotspotSoftApCallback(@onNull SoftApCallback callback)6220 public void unregisterLocalOnlyHotspotSoftApCallback(@NonNull SoftApCallback callback) { 6221 if (!SdkLevel.isAtLeastT()) { 6222 throw new UnsupportedOperationException(); 6223 } 6224 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 6225 Log.v(TAG, "unregisterLocalOnlyHotspotSoftApCallback: callback=" + callback); 6226 6227 try { 6228 synchronized (sLocalOnlyHotspotSoftApCallbackMap) { 6229 int callbackIdentifier = System.identityHashCode(callback); 6230 if (!sLocalOnlyHotspotSoftApCallbackMap.contains(callbackIdentifier)) { 6231 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 6232 return; 6233 } 6234 Bundle extras = new Bundle(); 6235 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 6236 mContext.getAttributionSource()); 6237 mService.unregisterLocalOnlyHotspotSoftApCallback( 6238 sLocalOnlyHotspotSoftApCallbackMap.get(callbackIdentifier), extras); 6239 sLocalOnlyHotspotSoftApCallbackMap.remove(callbackIdentifier); 6240 } 6241 } catch (RemoteException e) { 6242 throw e.rethrowFromSystemServer(); 6243 } 6244 } 6245 6246 /** 6247 * Allow callers (Settings UI) to watch LocalOnlyHotspot state changes. Callers will 6248 * receive a {@link LocalOnlyHotspotSubscription} object as a parameter of the 6249 * {@link LocalOnlyHotspotObserver#onRegistered(LocalOnlyHotspotSubscription)}. The registered 6250 * callers will receive the {@link LocalOnlyHotspotObserver#onStarted(SoftApConfiguration)} and 6251 * {@link LocalOnlyHotspotObserver#onStopped()} callbacks. 6252 * <p> 6253 * Applications should have the 6254 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} 6255 * permission. Callers without the permission will trigger a 6256 * {@link java.lang.SecurityException}. 6257 * <p> 6258 * @param observer LocalOnlyHotspotObserver callback. 6259 * @param handler Handler to use for callbacks 6260 * 6261 * @hide 6262 */ watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer, @Nullable Handler handler)6263 public void watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer, 6264 @Nullable Handler handler) { 6265 Executor executor = handler == null ? mContext.getMainExecutor() 6266 : new HandlerExecutor(handler); 6267 synchronized (mLock) { 6268 mLOHSObserverProxy = 6269 new LocalOnlyHotspotObserverProxy(this, executor, observer); 6270 try { 6271 mService.startWatchLocalOnlyHotspot(mLOHSObserverProxy); 6272 mLOHSObserverProxy.registered(); 6273 } catch (RemoteException e) { 6274 mLOHSObserverProxy = null; 6275 throw e.rethrowFromSystemServer(); 6276 } 6277 } 6278 } 6279 6280 /** 6281 * Allow callers to stop watching LocalOnlyHotspot state changes. After calling this method, 6282 * applications will no longer receive callbacks. 6283 * 6284 * @hide 6285 */ unregisterLocalOnlyHotspotObserver()6286 public void unregisterLocalOnlyHotspotObserver() { 6287 synchronized (mLock) { 6288 if (mLOHSObserverProxy == null) { 6289 // nothing to do, the callback was already cleaned up 6290 return; 6291 } 6292 mLOHSObserverProxy = null; 6293 try { 6294 mService.stopWatchLocalOnlyHotspot(); 6295 } catch (RemoteException e) { 6296 throw e.rethrowFromSystemServer(); 6297 } 6298 } 6299 } 6300 6301 /** 6302 * Gets the tethered Wi-Fi hotspot enabled state. 6303 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 6304 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 6305 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 6306 * @see #isWifiApEnabled() 6307 * 6308 * @hide 6309 */ 6310 @SystemApi 6311 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) getWifiApState()6312 public int getWifiApState() { 6313 try { 6314 return mService.getWifiApEnabledState(); 6315 } catch (RemoteException e) { 6316 throw e.rethrowFromSystemServer(); 6317 } 6318 } 6319 6320 /** 6321 * Return whether tethered Wi-Fi AP is enabled or disabled. 6322 * @return {@code true} if tethered Wi-Fi AP is enabled 6323 * @see #getWifiApState() 6324 * 6325 * @hide 6326 */ 6327 @SystemApi 6328 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) isWifiApEnabled()6329 public boolean isWifiApEnabled() { 6330 return getWifiApState() == WIFI_AP_STATE_ENABLED; 6331 } 6332 6333 /** 6334 * Gets the tethered Wi-Fi AP Configuration. 6335 * @return AP details in WifiConfiguration 6336 * 6337 * Note that AP detail may contain configuration which is cannot be represented 6338 * by the legacy WifiConfiguration, in such cases a null will be returned. 6339 * 6340 * @deprecated This API is deprecated. Use {@link #getSoftApConfiguration()} instead. 6341 * @hide 6342 */ 6343 @Nullable 6344 @SystemApi 6345 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 6346 @Deprecated getWifiApConfiguration()6347 public WifiConfiguration getWifiApConfiguration() { 6348 try { 6349 return mService.getWifiApConfiguration(); 6350 } catch (RemoteException e) { 6351 throw e.rethrowFromSystemServer(); 6352 } 6353 } 6354 6355 /** 6356 * Gets the Wi-Fi tethered AP Configuration. 6357 * @return AP details in {@link SoftApConfiguration} 6358 * 6359 * @hide 6360 */ 6361 @NonNull 6362 @SystemApi 6363 @RequiresPermission(anyOf = { 6364 android.Manifest.permission.NETWORK_SETTINGS, 6365 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 6366 }) getSoftApConfiguration()6367 public SoftApConfiguration getSoftApConfiguration() { 6368 try { 6369 return mService.getSoftApConfiguration(); 6370 } catch (RemoteException e) { 6371 throw e.rethrowFromSystemServer(); 6372 } 6373 } 6374 6375 /** 6376 * Gets the last configured Wi-Fi tethered AP passphrase. 6377 * 6378 * Note: It may be null when there is no passphrase changed since 6379 * device boot. 6380 * 6381 * @param executor The executor on which callback will be invoked. 6382 * @param resultCallback An asynchronous callback that will return the last configured 6383 * Wi-Fi tethered AP passphrase. 6384 * 6385 * @throws SecurityException if the caller does not have permission. 6386 * @throws NullPointerException if the caller provided invalid inputs. 6387 * 6388 * @hide 6389 */ 6390 @Nullable 6391 @SystemApi 6392 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) queryLastConfiguredTetheredApPassphraseSinceBoot( @onNull @allbackExecutor Executor executor, @NonNull Consumer<String> resultCallback)6393 public void queryLastConfiguredTetheredApPassphraseSinceBoot( 6394 @NonNull @CallbackExecutor Executor executor, 6395 @NonNull Consumer<String> resultCallback) { 6396 Objects.requireNonNull(executor, "executor cannot be null"); 6397 Objects.requireNonNull(resultCallback, "resultsCallback cannot be null"); 6398 try { 6399 mService.queryLastConfiguredTetheredApPassphraseSinceBoot( 6400 new IStringListener.Stub() { 6401 @Override 6402 public void onResult(String value) { 6403 Binder.clearCallingIdentity(); 6404 executor.execute(() -> { 6405 resultCallback.accept(value); 6406 }); 6407 } 6408 }); 6409 } catch (RemoteException e) { 6410 throw e.rethrowFromSystemServer(); 6411 } 6412 } 6413 6414 /** 6415 * Sets the tethered Wi-Fi AP Configuration. 6416 * @return {@code true} if the operation succeeded, {@code false} otherwise 6417 * 6418 * @deprecated This API is deprecated. Use {@link #setSoftApConfiguration(SoftApConfiguration)} 6419 * instead. 6420 * @hide 6421 */ 6422 @SystemApi 6423 @RequiresPermission(CHANGE_WIFI_STATE) 6424 @Deprecated setWifiApConfiguration(WifiConfiguration wifiConfig)6425 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { 6426 try { 6427 return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName()); 6428 } catch (RemoteException e) { 6429 throw e.rethrowFromSystemServer(); 6430 } 6431 } 6432 6433 /** 6434 * Sets the tethered Wi-Fi AP Configuration. 6435 * 6436 * If the API is called while the tethered soft AP is enabled, the configuration will apply to 6437 * the current soft AP if the new configuration only includes 6438 * {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} 6439 * or {@link SoftApConfiguration.Builder#setShutdownTimeoutMillis(long)} 6440 * or {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)} 6441 * or {@link SoftApConfiguration.Builder#setBlockedClientList(List)} 6442 * or {@link SoftApConfiguration.Builder#setAllowedClientList(List)} 6443 * or {@link SoftApConfiguration.Builder#setAutoShutdownEnabled(boolean)} 6444 * or {@link SoftApConfiguration.Builder#setBridgedModeOpportunisticShutdownEnabled(boolean)} 6445 * 6446 * Otherwise, the configuration changes will be applied when the Soft AP is next started 6447 * (the framework will not stop/start the AP). 6448 * 6449 * Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid 6450 * unexpected error due to invalid configuration. 6451 * 6452 * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP. 6453 * @return {@code true} if the operation succeeded, {@code false} otherwise 6454 * 6455 * @hide 6456 */ 6457 @SystemApi 6458 @RequiresPermission(anyOf = { 6459 android.Manifest.permission.NETWORK_SETTINGS, 6460 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 6461 }) setSoftApConfiguration(@onNull SoftApConfiguration softApConfig)6462 public boolean setSoftApConfiguration(@NonNull SoftApConfiguration softApConfig) { 6463 try { 6464 return mService.setSoftApConfiguration( 6465 softApConfig, mContext.getOpPackageName()); 6466 } catch (RemoteException e) { 6467 throw e.rethrowFromSystemServer(); 6468 } 6469 } 6470 6471 /** 6472 * Enable/Disable TDLS on a specific local route. 6473 * 6474 * <p> 6475 * TDLS enables two wireless endpoints to talk to each other directly 6476 * without going through the access point that is managing the local 6477 * network. It saves bandwidth and improves quality of the link. 6478 * </p> 6479 * <p> 6480 * This API enables/disables the option of using TDLS. If enabled, the 6481 * underlying hardware is free to use TDLS or a hop through the access 6482 * point. If disabled, existing TDLS session is torn down and 6483 * hardware is restricted to use access point for transferring wireless 6484 * packets. Default value for all routes is 'disabled', meaning restricted 6485 * to use access point for transferring packets. 6486 * </p> 6487 * 6488 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 6489 * @param enable true = setup and false = tear down TDLS 6490 */ setTdlsEnabled(InetAddress remoteIPAddress, boolean enable)6491 public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) { 6492 try { 6493 mService.enableTdls(remoteIPAddress.getHostAddress(), enable); 6494 } catch (RemoteException e) { 6495 throw e.rethrowFromSystemServer(); 6496 } 6497 } 6498 6499 /** 6500 * Enable/Disable TDLS on a specific local route. 6501 * 6502 * Similar to {@link #setTdlsEnabled(InetAddress, boolean)}, except 6503 * this version sends the result of the Enable/Disable request. 6504 * 6505 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 6506 * @param enable true = setup and false = tear down TDLS 6507 * @param executor The executor on which callback will be invoked. 6508 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 6509 * whether TDLS was successfully enabled or disabled. 6510 * {@code true} for success, {@code false} for failure. 6511 * 6512 * @throws NullPointerException if the caller provided invalid inputs. 6513 */ setTdlsEnabled(@onNull InetAddress remoteIPAddress, boolean enable, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)6514 public void setTdlsEnabled(@NonNull InetAddress remoteIPAddress, boolean enable, 6515 @NonNull @CallbackExecutor Executor executor, 6516 @NonNull Consumer<Boolean> resultsCallback) { 6517 Objects.requireNonNull(executor, "executor cannot be null"); 6518 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6519 Objects.requireNonNull(remoteIPAddress, "remote IP address cannot be null"); 6520 try { 6521 mService.enableTdlsWithRemoteIpAddress(remoteIPAddress.getHostAddress(), enable, 6522 new IBooleanListener.Stub() { 6523 @Override 6524 public void onResult(boolean value) { 6525 Binder.clearCallingIdentity(); 6526 executor.execute(() -> { 6527 resultsCallback.accept(value); 6528 }); 6529 } 6530 }); 6531 } catch (RemoteException e) { 6532 throw e.rethrowFromSystemServer(); 6533 } 6534 } 6535 6536 /** 6537 * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except 6538 * this version allows you to specify remote endpoint with a MAC address. 6539 * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab 6540 * @param enable true = setup and false = tear down TDLS 6541 */ setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable)6542 public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) { 6543 try { 6544 mService.enableTdlsWithMacAddress(remoteMacAddress, enable); 6545 } catch (RemoteException e) { 6546 throw e.rethrowFromSystemServer(); 6547 } 6548 } 6549 6550 /** 6551 * Enable/Disable TDLS with a specific peer Mac Address. 6552 * 6553 * Similar to {@link #setTdlsEnabledWithMacAddress(String, boolean)}, except 6554 * this version sends the result of the Enable/Disable request. 6555 * 6556 * @param remoteMacAddress Mac address of the endpoint to setup TDLS with 6557 * @param enable true = setup and false = tear down TDLS 6558 * @param executor The executor on which callback will be invoked. 6559 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 6560 * whether TDLS was successfully enabled or disabled. 6561 * {@code true} for success, {@code false} for failure. 6562 * 6563 * @throws NullPointerException if the caller provided invalid inputs. 6564 */ setTdlsEnabledWithMacAddress(@onNull String remoteMacAddress, boolean enable, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)6565 public void setTdlsEnabledWithMacAddress(@NonNull String remoteMacAddress, boolean enable, 6566 @NonNull @CallbackExecutor Executor executor, 6567 @NonNull Consumer<Boolean> resultsCallback) { 6568 Objects.requireNonNull(executor, "executor cannot be null"); 6569 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6570 Objects.requireNonNull(remoteMacAddress, "remote Mac address cannot be null"); 6571 try { 6572 mService.enableTdlsWithRemoteMacAddress(remoteMacAddress, enable, 6573 new IBooleanListener.Stub() { 6574 @Override 6575 public void onResult(boolean value) { 6576 Binder.clearCallingIdentity(); 6577 executor.execute(() -> { 6578 resultsCallback.accept(value); 6579 }); 6580 } 6581 }); 6582 } catch (RemoteException e) { 6583 throw e.rethrowFromSystemServer(); 6584 } 6585 } 6586 6587 /** 6588 * Check if a TDLS session can be established at this time via 6589 * {@link #setTdlsEnabled(InetAddress, boolean)} or 6590 * {@link #setTdlsEnabledWithMacAddress(String, boolean)} or 6591 * {@link #setTdlsEnabled(InetAddress, boolean, Executor, Consumer)} or 6592 * {@link #setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)} 6593 * 6594 * Internally framework checks the STA connected state, device support for TDLS and 6595 * the number of TDLS sessions available in driver/firmware. 6596 * 6597 * @param executor The executor on which callback will be invoked. 6598 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 6599 * whether a TDLS session can be established at this time. 6600 * {@code true} for available, {@code false} for not available. 6601 * 6602 * @throws NullPointerException if the caller provided invalid inputs. 6603 */ isTdlsOperationCurrentlyAvailable(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)6604 public void isTdlsOperationCurrentlyAvailable(@NonNull @CallbackExecutor Executor executor, 6605 @NonNull Consumer<Boolean> resultsCallback) { 6606 Objects.requireNonNull(executor, "executor cannot be null"); 6607 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6608 try { 6609 mService.isTdlsOperationCurrentlyAvailable( 6610 new IBooleanListener.Stub() { 6611 @Override 6612 public void onResult(boolean value) { 6613 Binder.clearCallingIdentity(); 6614 executor.execute(() -> { 6615 resultsCallback.accept(value); 6616 }); 6617 } 6618 }); 6619 } catch (RemoteException e) { 6620 throw e.rethrowFromSystemServer(); 6621 } 6622 } 6623 6624 /** 6625 * Return the maximum number of concurrent TDLS sessions supported by the device. 6626 * 6627 * @param executor The executor on which callback will be invoked. 6628 * @param resultsCallback An asynchronous callback that will return the maximum number of 6629 * concurrent TDLS sessions supported by the device. Returns 6630 * {@code -1} if information is not available, 6631 * e.g. if the driver/firmware doesn't provide this information. 6632 * 6633 * @throws NullPointerException if the caller provided invalid inputs. 6634 * @throws UnsupportedOperationException if the feature is not available. 6635 */ 6636 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) getMaxSupportedConcurrentTdlsSessions(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)6637 public void getMaxSupportedConcurrentTdlsSessions(@NonNull @CallbackExecutor Executor executor, 6638 @NonNull Consumer<Integer> resultsCallback) { 6639 Objects.requireNonNull(executor, "executor cannot be null"); 6640 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6641 try { 6642 mService.getMaxSupportedConcurrentTdlsSessions( 6643 new IIntegerListener.Stub() { 6644 @Override 6645 public void onResult(int value) { 6646 Binder.clearCallingIdentity(); 6647 executor.execute(() -> { 6648 resultsCallback.accept(value); 6649 }); 6650 } 6651 }); 6652 } catch (RemoteException e) { 6653 throw e.rethrowFromSystemServer(); 6654 } 6655 } 6656 6657 /** 6658 * Return the number of currently enabled TDLS sessions. 6659 * 6660 * Tracks the number of peers enabled for TDLS session via 6661 * {@link #setTdlsEnabled(InetAddress, boolean) }, 6662 * {@link #setTdlsEnabledWithMacAddress(String, boolean) }, 6663 * {@link #setTdlsEnabled(InetAddress, boolean, Executor, Consumer) } and 6664 * {@link #setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer) } 6665 * 6666 * @param executor The executor on which callback will be invoked. 6667 * @param resultsCallback An asynchronous callback that will return the number of Peer 6668 * Mac addresses configured in the driver for TDLS session. 6669 * 6670 * @throws NullPointerException if the caller provided invalid inputs. 6671 */ getNumberOfEnabledTdlsSessions(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)6672 public void getNumberOfEnabledTdlsSessions(@NonNull @CallbackExecutor Executor executor, 6673 @NonNull Consumer<Integer> resultsCallback) { 6674 Objects.requireNonNull(executor, "executor cannot be null"); 6675 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6676 try { 6677 mService.getNumberOfEnabledTdlsSessions( 6678 new IIntegerListener.Stub() { 6679 @Override 6680 public void onResult(int value) { 6681 Binder.clearCallingIdentity(); 6682 executor.execute(() -> { 6683 resultsCallback.accept(value); 6684 }); 6685 } 6686 }); 6687 } catch (RemoteException e) { 6688 throw e.rethrowFromSystemServer(); 6689 } 6690 } 6691 6692 /** @hide */ 6693 @Retention(RetentionPolicy.SOURCE) 6694 @IntDef({ActionListener.FAILURE_INTERNAL_ERROR, 6695 ActionListener.FAILURE_IN_PROGRESS, 6696 ActionListener.FAILURE_BUSY, 6697 ActionListener.FAILURE_INVALID_ARGS, 6698 ActionListener.FAILURE_NOT_AUTHORIZED}) 6699 public @interface ActionListenerFailureReason {} 6700 6701 /* WPS specific errors */ 6702 /** WPS overlap detected 6703 * @deprecated This is deprecated 6704 */ 6705 public static final int WPS_OVERLAP_ERROR = 3; 6706 /** WEP on WPS is prohibited 6707 * @deprecated This is deprecated 6708 */ 6709 public static final int WPS_WEP_PROHIBITED = 4; 6710 /** TKIP only prohibited 6711 * @deprecated This is deprecated 6712 */ 6713 public static final int WPS_TKIP_ONLY_PROHIBITED = 5; 6714 /** Authentication failure on WPS 6715 * @deprecated This is deprecated 6716 */ 6717 public static final int WPS_AUTH_FAILURE = 6; 6718 /** WPS timed out 6719 * @deprecated This is deprecated 6720 */ 6721 public static final int WPS_TIMED_OUT = 7; 6722 6723 /** 6724 * Interface for callback invocation on an application action. 6725 * @hide 6726 */ 6727 @SystemApi 6728 public interface ActionListener { 6729 /** 6730 * Passed with {@link #onFailure}. 6731 * Indicates that the operation failed due to an internal error. 6732 */ 6733 int FAILURE_INTERNAL_ERROR = 0; 6734 6735 /** 6736 * Passed with {@link #onFailure}. 6737 * Indicates that the operation is already in progress. 6738 */ 6739 int FAILURE_IN_PROGRESS = 1; 6740 6741 /** 6742 * Passed with {@link #onFailure}. 6743 * Indicates that the operation failed because the framework is busy and is unable to 6744 * service the request. 6745 */ 6746 int FAILURE_BUSY = 2; 6747 6748 /** 6749 * Passed with {@link #onFailure}. 6750 * Indicates that the operation failed due to invalid inputs. 6751 */ 6752 int FAILURE_INVALID_ARGS = 3; 6753 6754 /** 6755 * Passed with {@link #onFailure}. 6756 * Indicates that the operation failed due to insufficient user permissions. 6757 */ 6758 int FAILURE_NOT_AUTHORIZED = 4; 6759 6760 /** 6761 * The operation succeeded. 6762 */ onSuccess()6763 void onSuccess(); 6764 /** 6765 * The operation failed. 6766 * @param reason The reason for failure depends on the operation. 6767 */ onFailure(@ctionListenerFailureReason int reason)6768 void onFailure(@ActionListenerFailureReason int reason); 6769 } 6770 6771 /** Interface for callback invocation on a start WPS action 6772 * @deprecated This is deprecated 6773 */ 6774 public static abstract class WpsCallback { 6775 6776 /** WPS start succeeded 6777 * @deprecated This API is deprecated 6778 */ onStarted(String pin)6779 public abstract void onStarted(String pin); 6780 6781 /** WPS operation completed successfully 6782 * @deprecated This API is deprecated 6783 */ onSucceeded()6784 public abstract void onSucceeded(); 6785 6786 /** 6787 * WPS operation failed 6788 * @param reason The reason for failure could be one of 6789 * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR}, 6790 * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE} 6791 * and some generic errors. 6792 * @deprecated This API is deprecated 6793 */ onFailed(int reason)6794 public abstract void onFailed(int reason); 6795 } 6796 6797 /** 6798 * Base class for soft AP callback. Should be extended by applications and set when calling 6799 * {@link WifiManager#registerSoftApCallback(Executor, SoftApCallback)}. 6800 * 6801 * @hide 6802 */ 6803 @SystemApi 6804 public interface SoftApCallback { 6805 /** 6806 * Called when soft AP state changes. 6807 * 6808 * @param state the new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, 6809 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 6810 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 6811 * @param failureReason reason when in failed state. One of 6812 * {@link #SAP_START_FAILURE_GENERAL}, 6813 * {@link #SAP_START_FAILURE_NO_CHANNEL}, 6814 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}, 6815 * {@link #SAP_START_FAILURE_USER_REJECTED} 6816 */ onStateChanged(@ifiApState int state, @SapStartFailure int failureReason)6817 default void onStateChanged(@WifiApState int state, @SapStartFailure int failureReason) {} 6818 6819 /** 6820 * Called when soft AP state changes. 6821 * <p> 6822 * This provides the same state and failure reason as {@link #onStateChanged(int, int)}, but 6823 * also provides extra information such as interface name and TetheringRequest in order to 6824 * replace usage of the WIFI_AP_STATE_CHANGED_ACTION broadcast. If this method is overridden 6825 * then {@link #onStateChanged(int, int)} will no longer be called. 6826 * 6827 * @param state the new state. 6828 */ 6829 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) onStateChanged(@onNull SoftApState state)6830 default void onStateChanged(@NonNull SoftApState state) { 6831 onStateChanged(state.mState, state.mFailureReason); 6832 } 6833 6834 /** 6835 * Called when the connected clients to soft AP changes. 6836 * 6837 * @param clients the currently connected clients 6838 * 6839 * @deprecated This API is deprecated. 6840 * Use {@link #onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} instead. 6841 */ 6842 @Deprecated onConnectedClientsChanged(@onNull List<WifiClient> clients)6843 default void onConnectedClientsChanged(@NonNull List<WifiClient> clients) {} 6844 6845 6846 /** 6847 * Called when the connected clients for a soft AP instance change. 6848 * 6849 * When the Soft AP is configured in single AP mode, this callback is invoked 6850 * with the same {@link SoftApInfo} for all connected clients changes. 6851 * When the Soft AP is configured as multiple Soft AP instances (using 6852 * {@link SoftApConfiguration.Builder#setBands(int[])} or 6853 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}), this 6854 * callback is invoked with the corresponding {@link SoftApInfo} for the instance in which 6855 * the connected clients changed. 6856 * 6857 * @param info The {@link SoftApInfo} of the AP. 6858 * @param clients The currently connected clients on the AP instance specified by 6859 * {@code info}. 6860 */ onConnectedClientsChanged(@onNull SoftApInfo info, @NonNull List<WifiClient> clients)6861 default void onConnectedClientsChanged(@NonNull SoftApInfo info, 6862 @NonNull List<WifiClient> clients) {} 6863 6864 /** 6865 * Called when the Soft AP information changes. 6866 * 6867 * Note: this API remains valid only when the Soft AP is configured as a single AP - 6868 * not as multiple Soft APs (which are bridged to each other). When multiple Soft APs are 6869 * configured (using {@link SoftApConfiguration.Builder#setBands(int[])} or 6870 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}) 6871 * this callback will not be triggered - use the 6872 * {@link #onInfoChanged(List<SoftApInfo>)} callback in that case. 6873 * 6874 * @param softApInfo is the Soft AP information. {@link SoftApInfo} 6875 * 6876 * @deprecated This API is deprecated. Use {@link #onInfoChanged(List<SoftApInfo>)} 6877 * instead. 6878 */ 6879 @Deprecated onInfoChanged(@onNull SoftApInfo softApInfo)6880 default void onInfoChanged(@NonNull SoftApInfo softApInfo) { 6881 // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. 6882 } 6883 6884 /** 6885 * Called when the Soft AP information changes. 6886 * 6887 * Returns information on all configured Soft AP instances. The number of the elements in 6888 * the list depends on Soft AP configuration and state: 6889 * <ul> 6890 * <li>An empty list will be returned when the Soft AP is disabled. 6891 * <li>One information element will be returned in the list when the Soft AP is configured 6892 * as a single AP or when a single Soft AP remains active. 6893 * <li>Two information elements will be returned in the list when the multiple Soft APs are 6894 * configured and are active. 6895 * (configured using {@link SoftApConfiguration.Builder#setBands(int[])} or 6896 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}). 6897 * </ul> 6898 * 6899 * Note: When multiple Soft AP instances are configured, one of the Soft APs may 6900 * be shut down independently of the other by the framework. This can happen if no devices 6901 * are connected to it for some duration. In that case, one information element will be 6902 * returned. 6903 * 6904 * See {@link #isBridgedApConcurrencySupported()} for support info of multiple (bridged) AP. 6905 * 6906 * @param softApInfoList is the list of the Soft AP information elements - 6907 * {@link SoftApInfo}. 6908 */ onInfoChanged(@onNull List<SoftApInfo> softApInfoList)6909 default void onInfoChanged(@NonNull List<SoftApInfo> softApInfoList) { 6910 // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. 6911 } 6912 6913 /** 6914 * Called when capability of Soft AP changes. 6915 * 6916 * @param softApCapability is the Soft AP capability. {@link SoftApCapability} 6917 */ onCapabilityChanged(@onNull SoftApCapability softApCapability)6918 default void onCapabilityChanged(@NonNull SoftApCapability softApCapability) { 6919 // Do nothing: can be updated to add SoftApCapability details (e.g. meximum supported 6920 // client number) to the UI. 6921 } 6922 6923 /** 6924 * Called when client trying to connect but device blocked the client with specific reason. 6925 * 6926 * Can be used to ask user to update client to allowed list or blocked list 6927 * when reason is {@link SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER}, or 6928 * indicate the block due to maximum supported client number limitation when reason is 6929 * {@link SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS}. 6930 * 6931 * @param client the currently blocked client. 6932 * @param blockedReason one of blocked reason from {@link SapClientBlockedReason} 6933 */ onBlockedClientConnecting(@onNull WifiClient client, @SapClientBlockedReason int blockedReason)6934 default void onBlockedClientConnecting(@NonNull WifiClient client, 6935 @SapClientBlockedReason int blockedReason) { 6936 // Do nothing: can be used to ask user to update client to allowed list or blocked list. 6937 } 6938 6939 /** 6940 * Called when clients disconnect from a soft AP instance. 6941 * 6942 * @param info The {@link SoftApInfo} of the AP. 6943 * @param clients The clients that have disconnected from the AP instance specified by 6944 * {@code info}. 6945 */ 6946 @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) onClientsDisconnected(@onNull SoftApInfo info, @NonNull List<WifiClient> clients)6947 default void onClientsDisconnected(@NonNull SoftApInfo info, 6948 @NonNull List<WifiClient> clients) {} 6949 } 6950 6951 /** 6952 * Callback proxy for SoftApCallback objects. 6953 * 6954 * @hide 6955 */ 6956 private class SoftApCallbackProxy extends ISoftApCallback.Stub { 6957 private final Executor mExecutor; 6958 private final SoftApCallback mCallback; 6959 // Either {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}. 6960 private final int mIpMode; 6961 private Map<String, List<WifiClient>> mCurrentClients = new HashMap<>(); 6962 private Map<String, SoftApInfo> mCurrentInfos = new HashMap<>(); 6963 getConnectedClientList(Map<String, List<WifiClient>> clientsMap)6964 private List<WifiClient> getConnectedClientList(Map<String, List<WifiClient>> clientsMap) { 6965 List<WifiClient> connectedClientList = new ArrayList<>(); 6966 for (List<WifiClient> it : clientsMap.values()) { 6967 connectedClientList.addAll(it); 6968 } 6969 return connectedClientList; 6970 } 6971 SoftApCallbackProxy(Executor executor, SoftApCallback callback, int mode)6972 SoftApCallbackProxy(Executor executor, SoftApCallback callback, int mode) { 6973 mExecutor = executor; 6974 mCallback = callback; 6975 mIpMode = mode; 6976 } 6977 6978 @Override onStateChanged(SoftApState state)6979 public void onStateChanged(SoftApState state) { 6980 if (mVerboseLoggingEnabled) { 6981 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6982 + ", onStateChanged: " + state); 6983 } 6984 6985 Binder.clearCallingIdentity(); 6986 mExecutor.execute(() -> { 6987 mCallback.onStateChanged(state); 6988 }); 6989 } 6990 6991 @Override onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration)6992 public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, 6993 Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration) { 6994 if (mVerboseLoggingEnabled) { 6995 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6996 + ", onConnectedClientsOrInfoChanged: clients: " 6997 + clients + ", infos: " + infos + ", isBridged is " + isBridged 6998 + ", isRegistration is " + isRegistration); 6999 } 7000 7001 List<SoftApInfo> changedInfoList = new ArrayList<>(infos.values()); 7002 Map<SoftApInfo, List<WifiClient>> changedInfoClients = new HashMap<>(); 7003 // Some devices may not support infos callback, allow them to support client 7004 // connection changed callback. 7005 boolean areClientsChangedWithoutInfosChanged = 7006 infos.size() == 0 && getConnectedClientList(clients).size() 7007 != getConnectedClientList(mCurrentClients).size(); 7008 boolean isInfoChanged = infos.size() != mCurrentInfos.size(); 7009 7010 if (isRegistration) { 7011 // Check if there are clients connected, put it to changedInfoClients 7012 for (SoftApInfo currentInfo : infos.values()) { 7013 String instance = currentInfo.getApInstanceIdentifier(); 7014 if (clients.getOrDefault(instance, Collections.emptyList()).size() > 0) { 7015 changedInfoClients.put(currentInfo, clients.get(instance)); 7016 } 7017 } 7018 } 7019 7020 // Check if old info removed or not (client changed case) 7021 for (SoftApInfo info : mCurrentInfos.values()) { 7022 String changedInstance = info.getApInstanceIdentifier(); 7023 List<WifiClient> changedClientList = clients.getOrDefault( 7024 changedInstance, Collections.emptyList()); 7025 if (!changedInfoList.contains(info)) { 7026 isInfoChanged = true; 7027 if (mCurrentClients.getOrDefault(changedInstance, 7028 Collections.emptyList()).size() > 0) { 7029 SoftApInfo changedInfo = infos.get(changedInstance); 7030 if (changedInfo == null || changedInfo.getFrequency() == 0) { 7031 Log.d(TAG, "SoftApCallbackProxy on mode " + mIpMode 7032 + ", info changed on client connected instance(AP disabled)"); 7033 // Send old info with empty client list for shutdown case 7034 changedInfoClients.put(info, Collections.emptyList()); 7035 } else { 7036 Log.d(TAG, "SoftApCallbackProxy on mode " + mIpMode 7037 + ", info changed on client connected instance"); 7038 changedInfoClients.put(changedInfo, changedClientList); 7039 } 7040 } 7041 } else { 7042 // info doesn't change, check client list 7043 if (changedClientList.size() 7044 != mCurrentClients 7045 .getOrDefault(changedInstance, Collections.emptyList()).size()) { 7046 // Here should notify client changed on new info(same as old info) 7047 changedInfoClients.put(info, changedClientList); 7048 } 7049 } 7050 } 7051 7052 mCurrentClients = clients; 7053 mCurrentInfos = infos; 7054 if (!isInfoChanged && changedInfoClients.isEmpty() 7055 && !isRegistration && !areClientsChangedWithoutInfosChanged) { 7056 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 7057 + ", No changed & Not Registration don't need to notify the client"); 7058 return; 7059 } 7060 Binder.clearCallingIdentity(); 7061 // Notify the clients changed first for old info shutdown case 7062 for (SoftApInfo changedInfo : changedInfoClients.keySet()) { 7063 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 7064 + ", send onConnectedClientsChanged, changedInfo is " 7065 + changedInfo + " and clients are " + changedInfoClients.get(changedInfo)); 7066 mExecutor.execute(() -> { 7067 mCallback.onConnectedClientsChanged( 7068 changedInfo, changedInfoClients.get(changedInfo)); 7069 }); 7070 } 7071 7072 if (isInfoChanged || isRegistration) { 7073 if (!isBridged) { 7074 SoftApInfo newInfo = changedInfoList.isEmpty() 7075 ? new SoftApInfo() : changedInfoList.get(0); 7076 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 7077 + ", send InfoChanged, newInfo: " + newInfo); 7078 mExecutor.execute(() -> { 7079 mCallback.onInfoChanged(newInfo); 7080 }); 7081 } 7082 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 7083 + ", send InfoChanged, changedInfoList: " + changedInfoList); 7084 mExecutor.execute(() -> { 7085 mCallback.onInfoChanged(changedInfoList); 7086 }); 7087 } 7088 7089 if (isRegistration || !changedInfoClients.isEmpty() 7090 || areClientsChangedWithoutInfosChanged) { 7091 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 7092 + ", send onConnectedClientsChanged(clients): " 7093 + getConnectedClientList(clients)); 7094 mExecutor.execute(() -> { 7095 mCallback.onConnectedClientsChanged(getConnectedClientList(clients)); 7096 }); 7097 } 7098 } 7099 7100 @Override onCapabilityChanged(SoftApCapability capability)7101 public void onCapabilityChanged(SoftApCapability capability) { 7102 if (mVerboseLoggingEnabled) { 7103 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 7104 + ", onCapabilityChanged: SoftApCapability = " + capability); 7105 } 7106 7107 Binder.clearCallingIdentity(); 7108 mExecutor.execute(() -> { 7109 mCallback.onCapabilityChanged(capability); 7110 }); 7111 } 7112 7113 @Override onBlockedClientConnecting(@onNull WifiClient client, int blockedReason)7114 public void onBlockedClientConnecting(@NonNull WifiClient client, int blockedReason) { 7115 if (mVerboseLoggingEnabled) { 7116 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 7117 + ", onBlockedClientConnecting: client =" + client 7118 + " with reason = " + blockedReason); 7119 } 7120 7121 Binder.clearCallingIdentity(); 7122 mExecutor.execute(() -> { 7123 mCallback.onBlockedClientConnecting(client, blockedReason); 7124 }); 7125 } 7126 7127 @Override onClientsDisconnected(SoftApInfo info, List<WifiClient> clients)7128 public void onClientsDisconnected(SoftApInfo info, List<WifiClient> clients) { 7129 if (mVerboseLoggingEnabled) { 7130 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 7131 + ", onClientsDisconnected: info =" + info 7132 + " with clients = " + clients); 7133 } 7134 7135 Binder.clearCallingIdentity(); 7136 mExecutor.execute(() -> mCallback.onClientsDisconnected(info, clients)); 7137 } 7138 } 7139 7140 /** 7141 * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the 7142 * following callbacks on registration: 7143 * <ul> 7144 * <li> {@link SoftApCallback#onStateChanged(int, int)}</li> 7145 * <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li> 7146 * <li> {@link SoftApCallback#onInfoChanged(SoftApInfo)}</li> 7147 * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li> 7148 * <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li> 7149 * </ul> 7150 * 7151 * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know 7152 * if there are any clients connected to a specific bridged instance of this AP 7153 * (if bridged AP is enabled). 7154 * 7155 * Note: Caller will receive the callback 7156 * {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} 7157 * on registration when there are clients connected to AP. 7158 * 7159 * These will be dispatched on registration to provide the caller with the current state 7160 * (and are not an indication of any current change). Note that receiving an immediate 7161 * WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start 7162 * soft AP has failed. Caller can unregister a previously registered callback using 7163 * {@link #unregisterSoftApCallback} 7164 * <p> 7165 * Applications should have the 7166 * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers 7167 * without the permission will trigger a {@link java.lang.SecurityException}. 7168 * <p> 7169 * 7170 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 7171 * object. 7172 * @param callback Callback for soft AP events 7173 * @hide 7174 */ 7175 @SystemApi 7176 @RequiresPermission(anyOf = { 7177 android.Manifest.permission.NETWORK_SETTINGS, 7178 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 7179 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 7180 }) registerSoftApCallback(@onNull @allbackExecutor Executor executor, @NonNull SoftApCallback callback)7181 public void registerSoftApCallback(@NonNull @CallbackExecutor Executor executor, 7182 @NonNull SoftApCallback callback) { 7183 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 7184 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 7185 Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", executor=" + executor); 7186 7187 try { 7188 synchronized (sSoftApCallbackMap) { 7189 ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback, 7190 IFACE_IP_MODE_TETHERED); 7191 sSoftApCallbackMap.put(System.identityHashCode(callback), binderCallback); 7192 mService.registerSoftApCallback(binderCallback); 7193 } 7194 } catch (RemoteException e) { 7195 throw e.rethrowFromSystemServer(); 7196 } 7197 } 7198 7199 /** 7200 * Allow callers to unregister a previously registered callback. After calling this method, 7201 * applications will no longer receive soft AP events. 7202 * 7203 * @param callback Callback to unregister for soft AP events 7204 * 7205 * @hide 7206 */ 7207 @SystemApi 7208 @RequiresPermission(anyOf = { 7209 android.Manifest.permission.NETWORK_SETTINGS, 7210 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 7211 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 7212 }) unregisterSoftApCallback(@onNull SoftApCallback callback)7213 public void unregisterSoftApCallback(@NonNull SoftApCallback callback) { 7214 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 7215 Log.v(TAG, "unregisterSoftApCallback: callback=" + callback); 7216 7217 try { 7218 synchronized (sSoftApCallbackMap) { 7219 int callbackIdentifier = System.identityHashCode(callback); 7220 if (!sSoftApCallbackMap.contains(callbackIdentifier)) { 7221 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 7222 return; 7223 } 7224 mService.unregisterSoftApCallback(sSoftApCallbackMap.get(callbackIdentifier)); 7225 sSoftApCallbackMap.remove(callbackIdentifier); 7226 } 7227 } catch (RemoteException e) { 7228 throw e.rethrowFromSystemServer(); 7229 } 7230 } 7231 7232 /** 7233 * LocalOnlyHotspotReservation that contains the {@link SoftApConfiguration} for the active 7234 * LocalOnlyHotspot request. 7235 * <p> 7236 * Applications requesting LocalOnlyHotspot for sharing will receive an instance of the 7237 * LocalOnlyHotspotReservation in the 7238 * {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call. This 7239 * reservation contains the relevant {@link SoftApConfiguration}. 7240 * When an application is done with the LocalOnlyHotspot, they should call {@link 7241 * LocalOnlyHotspotReservation#close()}. Once this happens, the application will not receive 7242 * any further callbacks. If the LocalOnlyHotspot is stopped due to a 7243 * user triggered mode change, applications will be notified via the {@link 7244 * LocalOnlyHotspotCallback#onStopped()} callback. 7245 */ 7246 public class LocalOnlyHotspotReservation implements AutoCloseable { 7247 7248 private final CloseGuard mCloseGuard = new CloseGuard(); 7249 private final SoftApConfiguration mSoftApConfig; 7250 private final WifiConfiguration mWifiConfig; 7251 private boolean mClosed = false; 7252 7253 /** @hide */ 7254 @VisibleForTesting LocalOnlyHotspotReservation(SoftApConfiguration config)7255 public LocalOnlyHotspotReservation(SoftApConfiguration config) { 7256 mSoftApConfig = config; 7257 mWifiConfig = config.toWifiConfiguration(); 7258 mCloseGuard.open("close"); 7259 } 7260 7261 /** 7262 * Returns the {@link WifiConfiguration} of the current Local Only Hotspot (LOHS). 7263 * May be null if hotspot enabled and security type is not 7264 * {@code WifiConfiguration.KeyMgmt.None} or {@code WifiConfiguration.KeyMgmt.WPA2_PSK}. 7265 * 7266 * @deprecated Use {@code WifiManager#getSoftApConfiguration()} to get the 7267 * LOHS configuration. 7268 */ 7269 @Deprecated 7270 @Nullable getWifiConfiguration()7271 public WifiConfiguration getWifiConfiguration() { 7272 return mWifiConfig; 7273 } 7274 7275 /** 7276 * Returns the {@link SoftApConfiguration} of the current Local Only Hotspot (LOHS). 7277 */ 7278 @NonNull getSoftApConfiguration()7279 public SoftApConfiguration getSoftApConfiguration() { 7280 return mSoftApConfig; 7281 } 7282 7283 @Override close()7284 public void close() { 7285 try { 7286 synchronized (mLock) { 7287 if (!mClosed) { 7288 mClosed = true; 7289 stopLocalOnlyHotspot(); 7290 mCloseGuard.close(); 7291 } 7292 } 7293 } catch (Exception e) { 7294 Log.e(TAG, "Failed to stop Local Only Hotspot."); 7295 } finally { 7296 Reference.reachabilityFence(this); 7297 } 7298 } 7299 7300 @Override finalize()7301 protected void finalize() throws Throwable { 7302 try { 7303 if (mCloseGuard != null) { 7304 mCloseGuard.warnIfOpen(); 7305 } 7306 close(); 7307 } finally { 7308 super.finalize(); 7309 } 7310 } 7311 } 7312 7313 /** 7314 * Callback class for applications to receive updates about the LocalOnlyHotspot status. 7315 */ 7316 public static class LocalOnlyHotspotCallback { 7317 /** @hide */ 7318 public static final int REQUEST_REGISTERED = 0; 7319 7320 public static final int ERROR_NO_CHANNEL = 1; 7321 public static final int ERROR_GENERIC = 2; 7322 public static final int ERROR_INCOMPATIBLE_MODE = 3; 7323 public static final int ERROR_TETHERING_DISALLOWED = 4; 7324 7325 /** LocalOnlyHotspot start succeeded. */ onStarted(LocalOnlyHotspotReservation reservation)7326 public void onStarted(LocalOnlyHotspotReservation reservation) {}; 7327 7328 /** 7329 * LocalOnlyHotspot stopped. 7330 * <p> 7331 * The LocalOnlyHotspot can be disabled at any time by the user. When this happens, 7332 * applications will be notified that it was stopped. This will not be invoked when an 7333 * application calls {@link LocalOnlyHotspotReservation#close()}. 7334 */ onStopped()7335 public void onStopped() {}; 7336 7337 /** 7338 * LocalOnlyHotspot failed to start. 7339 * <p> 7340 * Applications can attempt to call 7341 * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} again at 7342 * a later time. 7343 * <p> 7344 * @param reason The reason for failure could be one of: {@link 7345 * #ERROR_TETHERING_DISALLOWED}, {@link #ERROR_INCOMPATIBLE_MODE}, 7346 * {@link #ERROR_NO_CHANNEL}, or {@link #ERROR_GENERIC}. 7347 */ onFailed(int reason)7348 public void onFailed(int reason) { }; 7349 } 7350 7351 /** 7352 * Callback proxy for LocalOnlyHotspotCallback objects. 7353 */ 7354 private static class LocalOnlyHotspotCallbackProxy extends ILocalOnlyHotspotCallback.Stub { 7355 private final WeakReference<WifiManager> mWifiManager; 7356 private final Executor mExecutor; 7357 private final LocalOnlyHotspotCallback mCallback; 7358 7359 /** 7360 * Constructs a {@link LocalOnlyHotspotCallbackProxy} using the specified executor. All 7361 * callbacks will run using the given executor. 7362 * 7363 * @param manager WifiManager 7364 * @param executor Executor for delivering callbacks. 7365 * @param callback LocalOnlyHotspotCallback to notify the calling application, or null. 7366 */ LocalOnlyHotspotCallbackProxy( @onNull WifiManager manager, @NonNull @CallbackExecutor Executor executor, @Nullable LocalOnlyHotspotCallback callback)7367 LocalOnlyHotspotCallbackProxy( 7368 @NonNull WifiManager manager, 7369 @NonNull @CallbackExecutor Executor executor, 7370 @Nullable LocalOnlyHotspotCallback callback) { 7371 mWifiManager = new WeakReference<>(manager); 7372 mExecutor = executor; 7373 mCallback = callback; 7374 } 7375 7376 @Override onHotspotStarted(SoftApConfiguration config)7377 public void onHotspotStarted(SoftApConfiguration config) { 7378 WifiManager manager = mWifiManager.get(); 7379 if (manager == null) return; 7380 7381 if (config == null) { 7382 Log.e(TAG, "LocalOnlyHotspotCallbackProxy: config cannot be null."); 7383 onHotspotFailed(LocalOnlyHotspotCallback.ERROR_GENERIC); 7384 return; 7385 } 7386 final LocalOnlyHotspotReservation reservation = 7387 manager.new LocalOnlyHotspotReservation(config); 7388 if (mCallback == null) return; 7389 mExecutor.execute(() -> mCallback.onStarted(reservation)); 7390 } 7391 7392 @Override onHotspotStopped()7393 public void onHotspotStopped() { 7394 WifiManager manager = mWifiManager.get(); 7395 if (manager == null) return; 7396 7397 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: hotspot stopped"); 7398 if (mCallback == null) return; 7399 mExecutor.execute(() -> mCallback.onStopped()); 7400 } 7401 7402 @Override onHotspotFailed(int reason)7403 public void onHotspotFailed(int reason) { 7404 WifiManager manager = mWifiManager.get(); 7405 if (manager == null) return; 7406 7407 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: failed to start. reason: " 7408 + reason); 7409 if (mCallback == null) return; 7410 mExecutor.execute(() -> mCallback.onFailed(reason)); 7411 } 7412 } 7413 7414 /** 7415 * LocalOnlyHotspotSubscription that is an AutoCloseable object for tracking applications 7416 * watching for LocalOnlyHotspot changes. 7417 * 7418 * @hide 7419 */ 7420 public class LocalOnlyHotspotSubscription implements AutoCloseable { 7421 private final CloseGuard mCloseGuard = new CloseGuard(); 7422 7423 /** @hide */ 7424 @VisibleForTesting LocalOnlyHotspotSubscription()7425 public LocalOnlyHotspotSubscription() { 7426 mCloseGuard.open("close"); 7427 } 7428 7429 @Override close()7430 public void close() { 7431 try { 7432 unregisterLocalOnlyHotspotObserver(); 7433 mCloseGuard.close(); 7434 } catch (Exception e) { 7435 Log.e(TAG, "Failed to unregister LocalOnlyHotspotObserver."); 7436 } finally { 7437 Reference.reachabilityFence(this); 7438 } 7439 } 7440 7441 @Override finalize()7442 protected void finalize() throws Throwable { 7443 try { 7444 if (mCloseGuard != null) { 7445 mCloseGuard.warnIfOpen(); 7446 } 7447 close(); 7448 } finally { 7449 super.finalize(); 7450 } 7451 } 7452 } 7453 7454 /** 7455 * Class to notify calling applications that watch for changes in LocalOnlyHotspot of updates. 7456 * 7457 * @hide 7458 */ 7459 public static class LocalOnlyHotspotObserver { 7460 /** 7461 * Confirm registration for LocalOnlyHotspotChanges by returning a 7462 * LocalOnlyHotspotSubscription. 7463 */ onRegistered(LocalOnlyHotspotSubscription subscription)7464 public void onRegistered(LocalOnlyHotspotSubscription subscription) {}; 7465 7466 /** 7467 * LocalOnlyHotspot started with the supplied config. 7468 */ onStarted(SoftApConfiguration config)7469 public void onStarted(SoftApConfiguration config) {}; 7470 7471 /** 7472 * LocalOnlyHotspot stopped. 7473 */ onStopped()7474 public void onStopped() {}; 7475 } 7476 7477 /** 7478 * Callback proxy for LocalOnlyHotspotObserver objects. 7479 */ 7480 private static class LocalOnlyHotspotObserverProxy extends ILocalOnlyHotspotCallback.Stub { 7481 private final WeakReference<WifiManager> mWifiManager; 7482 private final Executor mExecutor; 7483 private final LocalOnlyHotspotObserver mObserver; 7484 7485 /** 7486 * Constructs a {@link LocalOnlyHotspotObserverProxy} using the specified looper. 7487 * All callbacks will be delivered on the thread of the specified looper. 7488 * 7489 * @param manager WifiManager 7490 * @param executor Executor for delivering callbacks 7491 * @param observer LocalOnlyHotspotObserver to notify the calling application. 7492 */ LocalOnlyHotspotObserverProxy(WifiManager manager, Executor executor, final LocalOnlyHotspotObserver observer)7493 LocalOnlyHotspotObserverProxy(WifiManager manager, Executor executor, 7494 final LocalOnlyHotspotObserver observer) { 7495 mWifiManager = new WeakReference<>(manager); 7496 mExecutor = executor; 7497 mObserver = observer; 7498 } 7499 registered()7500 public void registered() throws RemoteException { 7501 WifiManager manager = mWifiManager.get(); 7502 if (manager == null) return; 7503 7504 mExecutor.execute(() -> 7505 mObserver.onRegistered(manager.new LocalOnlyHotspotSubscription())); 7506 } 7507 7508 @Override onHotspotStarted(SoftApConfiguration config)7509 public void onHotspotStarted(SoftApConfiguration config) { 7510 WifiManager manager = mWifiManager.get(); 7511 if (manager == null) return; 7512 7513 if (config == null) { 7514 Log.e(TAG, "LocalOnlyHotspotObserverProxy: config cannot be null."); 7515 return; 7516 } 7517 mExecutor.execute(() -> mObserver.onStarted(config)); 7518 } 7519 7520 @Override onHotspotStopped()7521 public void onHotspotStopped() { 7522 WifiManager manager = mWifiManager.get(); 7523 if (manager == null) return; 7524 7525 mExecutor.execute(() -> mObserver.onStopped()); 7526 } 7527 7528 @Override onHotspotFailed(int reason)7529 public void onHotspotFailed(int reason) { 7530 // do nothing 7531 } 7532 } 7533 7534 /** 7535 * Callback proxy for ActionListener objects. 7536 */ 7537 private class ActionListenerProxy extends IActionListener.Stub { 7538 private final String mActionTag; 7539 private final Handler mHandler; 7540 private final ActionListener mCallback; 7541 ActionListenerProxy(String actionTag, Looper looper, ActionListener callback)7542 ActionListenerProxy(String actionTag, Looper looper, ActionListener callback) { 7543 mActionTag = actionTag; 7544 mHandler = new Handler(looper); 7545 mCallback = callback; 7546 } 7547 7548 @Override onSuccess()7549 public void onSuccess() { 7550 if (mVerboseLoggingEnabled) { 7551 Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onSuccess"); 7552 } 7553 mHandler.post(() -> { 7554 mCallback.onSuccess(); 7555 }); 7556 } 7557 7558 @Override onFailure(@ctionListenerFailureReason int reason)7559 public void onFailure(@ActionListenerFailureReason int reason) { 7560 if (mVerboseLoggingEnabled) { 7561 Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onFailure=" + reason); 7562 } 7563 mHandler.post(() -> { 7564 mCallback.onFailure(reason); 7565 }); 7566 } 7567 } 7568 connectInternal(@ullable WifiConfiguration config, int networkId, @Nullable ActionListener listener)7569 private void connectInternal(@Nullable WifiConfiguration config, int networkId, 7570 @Nullable ActionListener listener) { 7571 ActionListenerProxy listenerProxy = null; 7572 if (listener != null) { 7573 listenerProxy = new ActionListenerProxy("connect", mContext.getMainLooper(), listener); 7574 } 7575 try { 7576 Bundle extras = new Bundle(); 7577 if (SdkLevel.isAtLeastS()) { 7578 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 7579 mContext.getAttributionSource()); 7580 } 7581 mService.connect(config, networkId, listenerProxy, mContext.getOpPackageName(), extras); 7582 } catch (RemoteException e) { 7583 if (listenerProxy != null) { 7584 listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7585 } 7586 } catch (SecurityException e) { 7587 if (listenerProxy != null) { 7588 listenerProxy.onFailure(ActionListener.FAILURE_NOT_AUTHORIZED); 7589 } 7590 } 7591 } 7592 7593 /** 7594 * Connect to a network with the given configuration. The network also 7595 * gets added to the list of configured networks for the foreground user. 7596 * 7597 * For a new network, this function is used instead of a 7598 * sequence of addNetwork(), enableNetwork(), and reconnect() 7599 * 7600 * @param config the set of variables that describe the configuration, 7601 * contained in a {@link WifiConfiguration} object. 7602 * @param listener for callbacks on success or failure. Can be null. 7603 * @throws IllegalStateException if the WifiManager instance needs to be 7604 * initialized again 7605 * 7606 * @hide 7607 */ 7608 @SystemApi 7609 @RequiresPermission(anyOf = { 7610 android.Manifest.permission.NETWORK_SETTINGS, 7611 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7612 android.Manifest.permission.NETWORK_STACK 7613 }) connect(@onNull WifiConfiguration config, @Nullable ActionListener listener)7614 public void connect(@NonNull WifiConfiguration config, @Nullable ActionListener listener) { 7615 if (config == null) throw new IllegalArgumentException("config cannot be null"); 7616 connectInternal(config, WifiConfiguration.INVALID_NETWORK_ID, listener); 7617 } 7618 7619 /** 7620 * Connect to a network with the given networkId. 7621 * 7622 * This function is used instead of a enableNetwork() and reconnect() 7623 * 7624 * <li> This API will cause reconnect if the credentials of the current active 7625 * connection has been changed.</li> 7626 * <li> This API will cause reconnect if the current active connection is marked metered.</li> 7627 * 7628 * @param networkId the ID of the network as returned by {@link #addNetwork} or {@link 7629 * #getConfiguredNetworks()}. 7630 * @param listener for callbacks on success or failure. Can be null. 7631 * @throws IllegalStateException if the WifiManager instance needs to be 7632 * initialized again 7633 * @hide 7634 */ 7635 @SystemApi 7636 @RequiresPermission(anyOf = { 7637 android.Manifest.permission.NETWORK_SETTINGS, 7638 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7639 android.Manifest.permission.NETWORK_STACK 7640 }) connect(int networkId, @Nullable ActionListener listener)7641 public void connect(int networkId, @Nullable ActionListener listener) { 7642 if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 7643 connectInternal(null, networkId, listener); 7644 } 7645 7646 /** 7647 * Temporarily disable autojoin for all currently visible and provisioned (saved, suggested) 7648 * wifi networks except merged carrier networks from the provided subscription ID. 7649 * 7650 * Disabled networks will get automatically re-enabled when they are out of range for a period 7651 * of time, or after the maximum disable duration specified in the framework. 7652 * 7653 * Calling {@link #stopRestrictingAutoJoinToSubscriptionId()} will immediately re-enable 7654 * autojoin on all disabled networks. 7655 * 7656 * @param subscriptionId the subscription ID of the carrier whose merged wifi networks won't be 7657 * disabled {@link android.telephony.SubscriptionInfo#getSubscriptionId()} 7658 * @hide 7659 */ 7660 @SystemApi 7661 @RequiresPermission(anyOf = { 7662 android.Manifest.permission.NETWORK_SETTINGS, 7663 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 7664 @RequiresApi(Build.VERSION_CODES.S) startRestrictingAutoJoinToSubscriptionId(int subscriptionId)7665 public void startRestrictingAutoJoinToSubscriptionId(int subscriptionId) { 7666 try { 7667 mService.startRestrictingAutoJoinToSubscriptionId(subscriptionId); 7668 } catch (RemoteException e) { 7669 throw e.rethrowFromSystemServer(); 7670 } 7671 } 7672 7673 /** 7674 * Re-enable autojoin for all non carrier merged wifi networks temporarily disconnected by 7675 * {@link #startRestrictingAutoJoinToSubscriptionId(int)}. 7676 * @hide 7677 */ 7678 @SystemApi 7679 @RequiresPermission(anyOf = { 7680 android.Manifest.permission.NETWORK_SETTINGS, 7681 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 7682 @RequiresApi(Build.VERSION_CODES.S) stopRestrictingAutoJoinToSubscriptionId()7683 public void stopRestrictingAutoJoinToSubscriptionId() { 7684 try { 7685 mService.stopRestrictingAutoJoinToSubscriptionId(); 7686 } catch (RemoteException e) { 7687 throw e.rethrowFromSystemServer(); 7688 } 7689 } 7690 7691 /** 7692 * Save the given network to the list of configured networks for the 7693 * foreground user. If the network already exists, the configuration 7694 * is updated. Any new network is enabled by default. 7695 * 7696 * For a new network, this function is used instead of a 7697 * sequence of addNetwork() and enableNetwork(). 7698 * 7699 * For an existing network, it accomplishes the task of updateNetwork() 7700 * 7701 * <li> This API will cause reconnect if the credentials of the current active 7702 * connection has been changed.</li> 7703 * <li> This API will cause disconnect if the current active connection is marked metered.</li> 7704 * 7705 * @param config the set of variables that describe the configuration, 7706 * contained in a {@link WifiConfiguration} object. 7707 * @param listener for callbacks on success or failure. Can be null. 7708 * @throws IllegalStateException if the WifiManager instance needs to be 7709 * initialized again 7710 * @hide 7711 */ 7712 @SystemApi 7713 @RequiresPermission(anyOf = { 7714 android.Manifest.permission.NETWORK_SETTINGS, 7715 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7716 android.Manifest.permission.NETWORK_STACK 7717 }) save(@onNull WifiConfiguration config, @Nullable ActionListener listener)7718 public void save(@NonNull WifiConfiguration config, @Nullable ActionListener listener) { 7719 if (config == null) throw new IllegalArgumentException("config cannot be null"); 7720 ActionListenerProxy listenerProxy = null; 7721 if (listener != null) { 7722 listenerProxy = new ActionListenerProxy("save", mContext.getMainLooper(), listener); 7723 } 7724 try { 7725 mService.save(config, listenerProxy, mContext.getOpPackageName()); 7726 } catch (RemoteException e) { 7727 if (listenerProxy != null) { 7728 listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7729 } 7730 } catch (SecurityException e) { 7731 if (listenerProxy != null) { 7732 listenerProxy.onFailure(ActionListener.FAILURE_NOT_AUTHORIZED); 7733 } 7734 } 7735 } 7736 7737 /** 7738 * Delete the network from the list of configured networks for the 7739 * foreground user. 7740 * 7741 * This function is used instead of a sequence of removeNetwork() 7742 * 7743 * @param config the set of variables that describe the configuration, 7744 * contained in a {@link WifiConfiguration} object. 7745 * @param listener for callbacks on success or failure. Can be null. 7746 * @throws IllegalStateException if the WifiManager instance needs to be 7747 * initialized again 7748 * @hide 7749 */ 7750 @SystemApi 7751 @RequiresPermission(anyOf = { 7752 android.Manifest.permission.NETWORK_SETTINGS, 7753 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7754 android.Manifest.permission.NETWORK_STACK 7755 }) forget(int netId, @Nullable ActionListener listener)7756 public void forget(int netId, @Nullable ActionListener listener) { 7757 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 7758 ActionListenerProxy listenerProxy = null; 7759 if (listener != null) { 7760 listenerProxy = new ActionListenerProxy("forget", mContext.getMainLooper(), listener); 7761 } 7762 try { 7763 mService.forget(netId, listenerProxy); 7764 } catch (RemoteException e) { 7765 if (listenerProxy != null) { 7766 listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7767 } 7768 } catch (SecurityException e) { 7769 if (listenerProxy != null) { 7770 listenerProxy.onFailure(ActionListener.FAILURE_NOT_AUTHORIZED); 7771 } 7772 } 7773 } 7774 7775 /** 7776 * Disable network 7777 * 7778 * @param netId is the network Id 7779 * @param listener for callbacks on success or failure. Can be null. 7780 * @throws IllegalStateException if the WifiManager instance needs to be 7781 * initialized again 7782 * @deprecated This API is deprecated. Use {@link #disableNetwork(int)} instead. 7783 * @hide 7784 */ 7785 @SystemApi 7786 @RequiresPermission(anyOf = { 7787 android.Manifest.permission.NETWORK_SETTINGS, 7788 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7789 android.Manifest.permission.NETWORK_STACK 7790 }) 7791 @Deprecated disable(int netId, @Nullable ActionListener listener)7792 public void disable(int netId, @Nullable ActionListener listener) { 7793 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 7794 // Simple wrapper which forwards the call to disableNetwork. This is a temporary 7795 // implementation until we can remove this API completely. 7796 boolean status = disableNetwork(netId); 7797 if (listener != null) { 7798 if (status) { 7799 listener.onSuccess(); 7800 } else { 7801 listener.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7802 } 7803 } 7804 } 7805 7806 /** 7807 * Control whether the device will automatically search for and connect to Wi-Fi networks - 7808 * auto-join Wi-Fi networks. Disabling this option will not impact manual connections - i.e. 7809 * the user will still be able to manually select and connect to a Wi-Fi network. Disabling 7810 * this option significantly impacts the device connectivity and is a restricted operation 7811 * (see below for permissions). Note that disabling this operation will also disable 7812 * connectivity initiated scanning operations. 7813 * <p> 7814 * Disabling the auto-join configuration is a temporary operation (with the exception of a 7815 * DO/PO caller): it will be reset (to enabled) when the device reboots or the user toggles 7816 * Wi-Fi off/on. When the caller is a DO/PO then toggling Wi-Fi will not reset the 7817 * configuration. Additionally, if a DO/PO disables auto-join then it cannot be (re)enabled by 7818 * a non-DO/PO caller. 7819 * 7820 * @param allowAutojoin true to allow auto-join, false to disallow auto-join 7821 * 7822 * Available for DO/PO apps. 7823 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 7824 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 7825 */ allowAutojoinGlobal(boolean allowAutojoin)7826 public void allowAutojoinGlobal(boolean allowAutojoin) { 7827 try { 7828 Bundle extras = new Bundle(); 7829 if (SdkLevel.isAtLeastS()) { 7830 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 7831 mContext.getAttributionSource()); 7832 } 7833 mService.allowAutojoinGlobal(allowAutojoin, mContext.getOpPackageName(), extras); 7834 } catch (RemoteException e) { 7835 throw e.rethrowFromSystemServer(); 7836 } 7837 } 7838 7839 /** 7840 * Query whether or not auto-join global is enabled/disabled 7841 * @see #allowAutojoinGlobal(boolean) 7842 * 7843 * Available for DO/PO apps. 7844 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 7845 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 7846 * 7847 * @param executor The executor on which callback will be invoked. 7848 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 7849 * whether auto-join global is enabled/disabled. 7850 * 7851 * @throws SecurityException if the caller does not have permission. 7852 * @throws NullPointerException if the caller provided invalid inputs. 7853 */ queryAutojoinGlobal(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)7854 public void queryAutojoinGlobal(@NonNull @CallbackExecutor Executor executor, 7855 @NonNull Consumer<Boolean> resultsCallback) { 7856 Objects.requireNonNull(executor, "executor cannot be null"); 7857 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 7858 try { 7859 mService.queryAutojoinGlobal( 7860 new IBooleanListener.Stub() { 7861 @Override 7862 public void onResult(boolean value) { 7863 Binder.clearCallingIdentity(); 7864 executor.execute(() -> { 7865 resultsCallback.accept(value); 7866 }); 7867 } 7868 }); 7869 } catch (RemoteException e) { 7870 throw e.rethrowFromSystemServer(); 7871 } 7872 } 7873 7874 /** 7875 * Sets the user choice for allowing auto-join to a network. 7876 * The updated choice will be made available through the updated config supplied by the 7877 * CONFIGURED_NETWORKS_CHANGED broadcast. 7878 * 7879 * @param netId the id of the network to allow/disallow auto-join for. 7880 * @param allowAutojoin true to allow auto-join, false to disallow auto-join 7881 * @hide 7882 */ 7883 @SystemApi 7884 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) allowAutojoin(int netId, boolean allowAutojoin)7885 public void allowAutojoin(int netId, boolean allowAutojoin) { 7886 try { 7887 mService.allowAutojoin(netId, allowAutojoin); 7888 } catch (RemoteException e) { 7889 throw e.rethrowFromSystemServer(); 7890 } 7891 } 7892 7893 /** 7894 * Configure auto-join settings for a Passpoint profile. 7895 * 7896 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 7897 * @param allowAutojoin true to enable auto-join, false to disable auto-join. 7898 * @hide 7899 */ 7900 @SystemApi 7901 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) allowAutojoinPasspoint(@onNull String fqdn, boolean allowAutojoin)7902 public void allowAutojoinPasspoint(@NonNull String fqdn, boolean allowAutojoin) { 7903 try { 7904 mService.allowAutojoinPasspoint(fqdn, allowAutojoin); 7905 } catch (RemoteException e) { 7906 throw e.rethrowFromSystemServer(); 7907 } 7908 } 7909 7910 /** 7911 * Configure MAC randomization setting for a Passpoint profile. 7912 * MAC randomization is enabled by default. 7913 * 7914 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 7915 * @param enable true to enable MAC randomization, false to disable MAC randomization. 7916 * @hide 7917 */ 7918 @SystemApi 7919 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setMacRandomizationSettingPasspointEnabled(@onNull String fqdn, boolean enable)7920 public void setMacRandomizationSettingPasspointEnabled(@NonNull String fqdn, boolean enable) { 7921 try { 7922 mService.setMacRandomizationSettingPasspointEnabled(fqdn, enable); 7923 } catch (RemoteException e) { 7924 throw e.rethrowFromSystemServer(); 7925 } 7926 } 7927 7928 /** 7929 * Sets the user's choice of metered override for a Passpoint profile. 7930 * 7931 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 7932 * @param meteredOverride One of three values: {@link WifiConfiguration#METERED_OVERRIDE_NONE}, 7933 * {@link WifiConfiguration#METERED_OVERRIDE_METERED}, 7934 * {@link WifiConfiguration#METERED_OVERRIDE_NOT_METERED} 7935 * @hide 7936 */ 7937 @SystemApi 7938 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setPasspointMeteredOverride(@onNull String fqdn, @WifiConfiguration.MeteredOverride int meteredOverride)7939 public void setPasspointMeteredOverride(@NonNull String fqdn, 7940 @WifiConfiguration.MeteredOverride int meteredOverride) { 7941 try { 7942 mService.setPasspointMeteredOverride(fqdn, meteredOverride); 7943 } catch (RemoteException e) { 7944 throw e.rethrowFromSystemServer(); 7945 } 7946 } 7947 7948 /** 7949 * Temporarily disable a network. Should always trigger with user disconnect network. 7950 * 7951 * @param network Input can be SSID or FQDN. And caller must ensure that the SSID passed thru 7952 * this API matched the WifiConfiguration.SSID rules, and thus be surrounded by 7953 * quotes. 7954 * @hide 7955 */ 7956 @SystemApi 7957 @RequiresPermission(anyOf = { 7958 android.Manifest.permission.NETWORK_SETTINGS, 7959 android.Manifest.permission.NETWORK_STACK 7960 }) disableEphemeralNetwork(@onNull String network)7961 public void disableEphemeralNetwork(@NonNull String network) { 7962 if (TextUtils.isEmpty(network)) { 7963 throw new IllegalArgumentException("SSID cannot be null or empty!"); 7964 } 7965 try { 7966 mService.disableEphemeralNetwork(network, mContext.getOpPackageName()); 7967 } catch (RemoteException e) { 7968 throw e.rethrowFromSystemServer(); 7969 } 7970 } 7971 7972 /** 7973 * WPS suport has been deprecated from Client mode and this method will immediately trigger 7974 * {@link WpsCallback#onFailed(int)} with a generic error. 7975 * 7976 * @param config WPS configuration (does not support {@link WpsInfo#LABEL}) 7977 * @param listener for callbacks on success or failure. Can be null. 7978 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 7979 * @deprecated This API is deprecated 7980 */ startWps(WpsInfo config, WpsCallback listener)7981 public void startWps(WpsInfo config, WpsCallback listener) { 7982 if (listener != null ) { 7983 listener.onFailed(ActionListener.FAILURE_INTERNAL_ERROR); 7984 } 7985 } 7986 7987 /** 7988 * WPS support has been deprecated from Client mode and this method will immediately trigger 7989 * {@link WpsCallback#onFailed(int)} with a generic error. 7990 * 7991 * @param listener for callbacks on success or failure. Can be null. 7992 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 7993 * @deprecated This API is deprecated 7994 */ cancelWps(WpsCallback listener)7995 public void cancelWps(WpsCallback listener) { 7996 if (listener != null) { 7997 listener.onFailed(ActionListener.FAILURE_INTERNAL_ERROR); 7998 } 7999 } 8000 8001 /** 8002 * Allows an application to keep the Wi-Fi radio awake. 8003 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 8004 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 8005 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 8006 * WifiLocks are held in any application. 8007 * <p> 8008 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 8009 * could function over a mobile network, if available. A program that needs to download large 8010 * files should hold a WifiLock to ensure that the download will complete, but a program whose 8011 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 8012 * affecting battery life. 8013 * <p> 8014 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 8015 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 8016 * is idle. 8017 * <p> 8018 * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK} 8019 * permission in an {@code <uses-permission>} element of the application's manifest. 8020 */ 8021 public class WifiLock { 8022 private String mTag; 8023 private final IBinder mBinder; 8024 private int mRefCount; 8025 int mLockType; 8026 private boolean mRefCounted; 8027 private boolean mHeld; 8028 private WorkSource mWorkSource; 8029 WifiLock(int lockType, String tag)8030 private WifiLock(int lockType, String tag) { 8031 mTag = tag; 8032 mLockType = lockType; 8033 mBinder = new Binder(); 8034 mRefCount = 0; 8035 mRefCounted = true; 8036 mHeld = false; 8037 } 8038 8039 /** 8040 * Locks the Wi-Fi radio on until {@link #release} is called. 8041 * 8042 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 8043 * reference count, and the radio will remain locked as long as the reference count is 8044 * above zero. 8045 * 8046 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 8047 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 8048 * will be required, regardless of the number of times that {@code acquire} is called. 8049 */ acquire()8050 public void acquire() { 8051 synchronized (mBinder) { 8052 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 8053 try { 8054 Bundle extras = new Bundle(); 8055 if (SdkLevel.isAtLeastS()) { 8056 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 8057 mContext.getAttributionSource()); 8058 } 8059 mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource, 8060 mContext.getOpPackageName(), extras); 8061 synchronized (WifiManager.this) { 8062 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 8063 mService.releaseWifiLock(mBinder); 8064 throw new UnsupportedOperationException( 8065 "Exceeded maximum number of wifi locks"); 8066 } 8067 mActiveLockCount++; 8068 } 8069 } catch (RemoteException e) { 8070 throw e.rethrowFromSystemServer(); 8071 } 8072 mHeld = true; 8073 } 8074 } 8075 } 8076 8077 /** 8078 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 8079 * 8080 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 8081 * reference count, and the radio will be unlocked only when the reference count reaches 8082 * zero. If the reference count goes below zero (that is, if {@code release} is called 8083 * a greater number of times than {@link #acquire}), an exception is thrown. 8084 * 8085 * If this WifiLock is not reference-counted, the first call to {@code release} (after 8086 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 8087 * calls will be ignored. 8088 */ release()8089 public void release() { 8090 synchronized (mBinder) { 8091 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 8092 try { 8093 mService.releaseWifiLock(mBinder); 8094 synchronized (WifiManager.this) { 8095 mActiveLockCount--; 8096 } 8097 } catch (RemoteException e) { 8098 throw e.rethrowFromSystemServer(); 8099 } 8100 mHeld = false; 8101 } 8102 if (mRefCount < 0) { 8103 throw new RuntimeException("WifiLock under-locked " + mTag); 8104 } 8105 } 8106 } 8107 8108 /** 8109 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 8110 * 8111 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 8112 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 8113 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 8114 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 8115 * radio whenever {@link #release} is called and it is locked. 8116 * 8117 * @param refCounted true if this WifiLock should keep a reference count 8118 */ setReferenceCounted(boolean refCounted)8119 public void setReferenceCounted(boolean refCounted) { 8120 mRefCounted = refCounted; 8121 } 8122 8123 /** 8124 * Checks whether this WifiLock is currently held. 8125 * 8126 * @return true if this WifiLock is held, false otherwise 8127 */ isHeld()8128 public boolean isHeld() { 8129 synchronized (mBinder) { 8130 return mHeld; 8131 } 8132 } 8133 setWorkSource(WorkSource ws)8134 public void setWorkSource(WorkSource ws) { 8135 synchronized (mBinder) { 8136 if (ws != null && ws.isEmpty()) { 8137 ws = null; 8138 } 8139 boolean changed = true; 8140 if (ws == null) { 8141 mWorkSource = null; 8142 } else { 8143 ws = ws.withoutNames(); 8144 if (mWorkSource == null) { 8145 changed = mWorkSource != null; 8146 mWorkSource = new WorkSource(ws); 8147 } else { 8148 changed = !mWorkSource.equals(ws); 8149 if (changed) { 8150 mWorkSource.set(ws); 8151 } 8152 } 8153 } 8154 if (changed && mHeld) { 8155 try { 8156 Bundle extras = new Bundle(); 8157 if (SdkLevel.isAtLeastS()) { 8158 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 8159 mContext.getAttributionSource()); 8160 } 8161 mService.updateWifiLockWorkSource(mBinder, mWorkSource, 8162 mContext.getOpPackageName(), extras); 8163 } catch (RemoteException e) { 8164 throw e.rethrowFromSystemServer(); 8165 } 8166 } 8167 } 8168 } 8169 toString()8170 public String toString() { 8171 String s1, s2, s3; 8172 synchronized (mBinder) { 8173 s1 = Integer.toHexString(System.identityHashCode(this)); 8174 s2 = mHeld ? "held; " : ""; 8175 if (mRefCounted) { 8176 s3 = "refcounted: refcount = " + mRefCount; 8177 } else { 8178 s3 = "not refcounted"; 8179 } 8180 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 8181 } 8182 } 8183 8184 @Override finalize()8185 protected void finalize() throws Throwable { 8186 super.finalize(); 8187 synchronized (mBinder) { 8188 if (mHeld) { 8189 try { 8190 mService.releaseWifiLock(mBinder); 8191 synchronized (WifiManager.this) { 8192 mActiveLockCount--; 8193 } 8194 } catch (RemoteException e) { 8195 throw e.rethrowFromSystemServer(); 8196 } 8197 } 8198 } 8199 } 8200 } 8201 8202 /** 8203 * Creates a new WifiLock. 8204 * 8205 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL_HIGH_PERF} 8206 * and {@link #WIFI_MODE_FULL_LOW_LATENCY} for descriptions of the types of Wi-Fi locks. 8207 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 8208 * never shown to the user under normal conditions, but should be descriptive 8209 * enough to identify your application and the specific WifiLock within it, if it 8210 * holds multiple WifiLocks. 8211 * 8212 * @return a new, unacquired WifiLock with the given tag. 8213 * 8214 * @see WifiLock 8215 */ createWifiLock(int lockType, String tag)8216 public WifiLock createWifiLock(int lockType, String tag) { 8217 return new WifiLock(lockType, tag); 8218 } 8219 8220 /** 8221 * Interface for low latency lock listener. Should be extended by application and set when 8222 * calling {@link WifiManager#addWifiLowLatencyLockListener(Executor, 8223 * WifiLowLatencyLockListener)}. 8224 * 8225 * @hide 8226 */ 8227 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 8228 @SystemApi 8229 public interface WifiLowLatencyLockListener { 8230 /** 8231 * Provides low latency mode is activated or not. Triggered when Wi-Fi chip enters into low 8232 * latency mode. 8233 * 8234 * <p>Note: Always called with current state when a new listener gets registered. 8235 */ 8236 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) onActivatedStateChanged(boolean activated)8237 void onActivatedStateChanged(boolean activated); 8238 8239 /** 8240 * Provides UIDs (lock owners) of the applications which currently acquired low latency 8241 * lock. Triggered when an application acquires or releases a lock. 8242 * 8243 * <p>Note: Always called with UIDs of the current acquired locks when a new listener gets 8244 * registered. 8245 * 8246 * @param ownerUids An array of UIDs. 8247 */ 8248 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) onOwnershipChanged(@onNull int[] ownerUids)8249 default void onOwnershipChanged(@NonNull int[] ownerUids) {} 8250 8251 /** 8252 * Provides UIDs of the applications which acquired the low latency lock and is currently 8253 * active. See {@link WifiManager#WIFI_MODE_FULL_LOW_LATENCY} for the conditions to be met 8254 * for low latency lock to be active. Triggered when application acquiring the lock 8255 * satisfies or does not satisfy low latency conditions when the low latency mode is 8256 * activated. Also gets triggered when the lock becomes active, immediately after the {@link 8257 * WifiLowLatencyLockListener#onActivatedStateChanged(boolean)} callback is triggered. 8258 * 8259 * <p>Note: Always called with UIDs of the current active locks when a new listener gets 8260 * registered if the Wi-Fi chip is in low latency mode. 8261 * 8262 * @param activeUids An array of UIDs. 8263 */ 8264 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) onActiveUsersChanged(@onNull int[] activeUids)8265 default void onActiveUsersChanged(@NonNull int[] activeUids) {} 8266 } 8267 8268 /** 8269 * Helper class to support wifi low latency lock listener. 8270 */ 8271 private static class OnWifiLowLatencyLockProxy extends IWifiLowLatencyLockListener.Stub { 8272 @NonNull 8273 private Executor mExecutor; 8274 @NonNull 8275 private WifiLowLatencyLockListener mListener; 8276 OnWifiLowLatencyLockProxy(@onNull Executor executor, @NonNull WifiLowLatencyLockListener listener)8277 OnWifiLowLatencyLockProxy(@NonNull Executor executor, 8278 @NonNull WifiLowLatencyLockListener listener) { 8279 Objects.requireNonNull(executor); 8280 Objects.requireNonNull(listener); 8281 mExecutor = executor; 8282 mListener = listener; 8283 } 8284 8285 @Override onActivatedStateChanged(boolean activated)8286 public void onActivatedStateChanged(boolean activated) { 8287 Binder.clearCallingIdentity(); 8288 mExecutor.execute(() -> mListener.onActivatedStateChanged(activated)); 8289 8290 } 8291 8292 @Override onOwnershipChanged(@onNull int[] ownerUids)8293 public void onOwnershipChanged(@NonNull int[] ownerUids) { 8294 Binder.clearCallingIdentity(); 8295 mExecutor.execute(() -> mListener.onOwnershipChanged(ownerUids)); 8296 8297 } 8298 8299 @Override onActiveUsersChanged(@onNull int[] activeUids)8300 public void onActiveUsersChanged(@NonNull int[] activeUids) { 8301 Binder.clearCallingIdentity(); 8302 mExecutor.execute(() -> mListener.onActiveUsersChanged(activeUids)); 8303 } 8304 } 8305 8306 /** 8307 * Add a listener for monitoring the low latency lock. The caller can unregister a previously 8308 * registered listener using {@link WifiManager#removeWifiLowLatencyLockListener( 8309 * WifiLowLatencyLockListener)}. 8310 * 8311 * <p>Applications should have the {@link android.Manifest.permission#NETWORK_SETTINGS} and 8312 * {@link android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. Callers without 8313 * the permission will trigger a {@link java.lang.SecurityException}. 8314 * 8315 * @param executor The Executor on which to execute the callbacks. 8316 * @param listener The listener for the latency mode change. 8317 * @throws IllegalArgumentException if incorrect input arguments are provided. 8318 * @throws SecurityException if the caller is not allowed to call this API 8319 * @hide 8320 */ 8321 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 8322 @SystemApi 8323 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 8324 @RequiresPermission( 8325 anyOf = {android.Manifest.permission.NETWORK_SETTINGS, MANAGE_WIFI_NETWORK_SELECTION}) addWifiLowLatencyLockListener( @onNull @allbackExecutor Executor executor, @NonNull WifiLowLatencyLockListener listener)8326 public void addWifiLowLatencyLockListener( 8327 @NonNull @CallbackExecutor Executor executor, 8328 @NonNull WifiLowLatencyLockListener listener) { 8329 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 8330 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 8331 if (mVerboseLoggingEnabled) { 8332 Log.d(TAG, "addWifiLowLatencyLockListener: listener=" + listener + ", executor=" 8333 + executor); 8334 } 8335 final int listenerIdentifier = System.identityHashCode(listener); 8336 try { 8337 synchronized (sWifiLowLatencyLockListenerMap) { 8338 IWifiLowLatencyLockListener.Stub listenerProxy = new OnWifiLowLatencyLockProxy( 8339 executor, 8340 listener); 8341 sWifiLowLatencyLockListenerMap.put(listenerIdentifier, listenerProxy); 8342 mService.addWifiLowLatencyLockListener(listenerProxy); 8343 } 8344 } catch (RemoteException e) { 8345 sWifiLowLatencyLockListenerMap.remove(listenerIdentifier); 8346 throw e.rethrowFromSystemServer(); 8347 } 8348 } 8349 8350 /** 8351 * Removes a listener added using {@link WifiManager#addWifiLowLatencyLockListener(Executor, 8352 * WifiLowLatencyLockListener)}. After calling this method, applications will no longer receive 8353 * low latency mode notifications. 8354 * 8355 * @param listener the listener to be removed. 8356 * @throws IllegalArgumentException if incorrect input arguments are provided. 8357 * @hide 8358 */ 8359 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 8360 @SystemApi 8361 @RequiresApi(Build.VERSION_CODES.TIRAMISU) removeWifiLowLatencyLockListener(@onNull WifiLowLatencyLockListener listener)8362 public void removeWifiLowLatencyLockListener(@NonNull WifiLowLatencyLockListener listener) { 8363 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 8364 if (mVerboseLoggingEnabled) { 8365 Log.d(TAG, "removeWifiLowLatencyLockListener: listener=" + listener); 8366 } 8367 final int listenerIdentifier = System.identityHashCode(listener); 8368 synchronized (sWifiLowLatencyLockListenerMap) { 8369 try { 8370 if (!sWifiLowLatencyLockListenerMap.contains(listenerIdentifier)) { 8371 Log.w(TAG, "Unknown external listener " + listenerIdentifier); 8372 return; 8373 } 8374 mService.removeWifiLowLatencyLockListener( 8375 sWifiLowLatencyLockListenerMap.get(listenerIdentifier)); 8376 8377 } catch (RemoteException e) { 8378 throw e.rethrowFromSystemServer(); 8379 } finally { 8380 sWifiLowLatencyLockListenerMap.remove(listenerIdentifier); 8381 } 8382 } 8383 } 8384 8385 /** 8386 * Creates a new WifiLock. 8387 * 8388 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 8389 * never shown to the user under normal conditions, but should be descriptive 8390 * enough to identify your application and the specific WifiLock within it, if it 8391 * holds multiple WifiLocks. 8392 * 8393 * @return a new, unacquired WifiLock with the given tag. 8394 * 8395 * @see WifiLock 8396 * 8397 * @deprecated This API is non-functional. 8398 */ 8399 @Deprecated createWifiLock(String tag)8400 public WifiLock createWifiLock(String tag) { 8401 return new WifiLock(WIFI_MODE_FULL, tag); 8402 } 8403 8404 /** 8405 * Create a new MulticastLock 8406 * 8407 * @param tag a tag for the MulticastLock to identify it in debugging 8408 * messages. This string is never shown to the user under 8409 * normal conditions, but should be descriptive enough to 8410 * identify your application and the specific MulticastLock 8411 * within it, if it holds multiple MulticastLocks. 8412 * 8413 * @return a new, unacquired MulticastLock with the given tag. 8414 * 8415 * @see MulticastLock 8416 */ createMulticastLock(String tag)8417 public MulticastLock createMulticastLock(String tag) { 8418 return new MulticastLock(tag); 8419 } 8420 8421 /** 8422 * Allows an application to receive Wifi Multicast packets. 8423 * Normally the Wifi stack filters out packets not explicitly 8424 * addressed to this device. Acquring a MulticastLock will 8425 * cause the stack to receive packets addressed to multicast 8426 * addresses. Processing these extra packets can cause a noticeable 8427 * battery drain and should be disabled when not needed. 8428 */ 8429 public class MulticastLock { 8430 private String mTag; 8431 private final IBinder mBinder; 8432 private int mRefCount; 8433 private boolean mRefCounted; 8434 private boolean mHeld; 8435 MulticastLock(String tag)8436 private MulticastLock(String tag) { 8437 mTag = tag; 8438 mBinder = new Binder(); 8439 mRefCount = 0; 8440 mRefCounted = true; 8441 mHeld = false; 8442 } 8443 8444 /** 8445 * Locks Wifi Multicast on until {@link #release} is called. 8446 * 8447 * If this MulticastLock is reference-counted each call to 8448 * {@code acquire} will increment the reference count, and the 8449 * wifi interface will receive multicast packets as long as the 8450 * reference count is above zero. 8451 * 8452 * If this MulticastLock is not reference-counted, the first call to 8453 * {@code acquire} will turn on the multicast packets, but subsequent 8454 * calls will be ignored. Only one call to {@link #release} will 8455 * be required, regardless of the number of times that {@code acquire} 8456 * is called. 8457 * 8458 * Note that other applications may also lock Wifi Multicast on. 8459 * Only they can relinquish their lock. 8460 * 8461 * Also note that applications cannot leave Multicast locked on. 8462 * When an app exits or crashes, any Multicast locks will be released. 8463 */ acquire()8464 public void acquire() { 8465 synchronized (mBinder) { 8466 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 8467 try { 8468 mService.acquireMulticastLock(mBinder, mTag, 8469 mContext.getAttributionTag(), mContext.getOpPackageName()); 8470 synchronized (WifiManager.this) { 8471 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 8472 mService.releaseMulticastLock(mBinder, mTag); 8473 throw new UnsupportedOperationException( 8474 "Exceeded maximum number of wifi locks"); 8475 } 8476 mActiveLockCount++; 8477 } 8478 } catch (RemoteException e) { 8479 throw e.rethrowFromSystemServer(); 8480 } 8481 mHeld = true; 8482 } 8483 } 8484 } 8485 8486 /** 8487 * Unlocks Wifi Multicast, restoring the filter of packets 8488 * not addressed specifically to this device and saving power. 8489 * 8490 * If this MulticastLock is reference-counted, each call to 8491 * {@code release} will decrement the reference count, and the 8492 * multicast packets will only stop being received when the reference 8493 * count reaches zero. If the reference count goes below zero (that 8494 * is, if {@code release} is called a greater number of times than 8495 * {@link #acquire}), an exception is thrown. 8496 * 8497 * If this MulticastLock is not reference-counted, the first call to 8498 * {@code release} (after the radio was multicast locked using 8499 * {@link #acquire}) will unlock the multicast, and subsequent calls 8500 * will be ignored. 8501 * 8502 * Note that if any other Wifi Multicast Locks are still outstanding 8503 * this {@code release} call will not have an immediate effect. Only 8504 * when all applications have released all their Multicast Locks will 8505 * the Multicast filter be turned back on. 8506 * 8507 * Also note that when an app exits or crashes all of its Multicast 8508 * Locks will be automatically released. 8509 */ release()8510 public void release() { 8511 synchronized (mBinder) { 8512 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 8513 try { 8514 mService.releaseMulticastLock(mBinder, mTag); 8515 synchronized (WifiManager.this) { 8516 mActiveLockCount--; 8517 } 8518 } catch (RemoteException e) { 8519 throw e.rethrowFromSystemServer(); 8520 } 8521 mHeld = false; 8522 } 8523 if (mRefCount < 0) { 8524 throw new RuntimeException("MulticastLock under-locked " 8525 + mTag); 8526 } 8527 } 8528 } 8529 8530 /** 8531 * Controls whether this is a reference-counted or non-reference- 8532 * counted MulticastLock. 8533 * 8534 * Reference-counted MulticastLocks keep track of the number of calls 8535 * to {@link #acquire} and {@link #release}, and only stop the 8536 * reception of multicast packets when every call to {@link #acquire} 8537 * has been balanced with a call to {@link #release}. Non-reference- 8538 * counted MulticastLocks allow the reception of multicast packets 8539 * whenever {@link #acquire} is called and stop accepting multicast 8540 * packets whenever {@link #release} is called. 8541 * 8542 * @param refCounted true if this MulticastLock should keep a reference 8543 * count 8544 */ setReferenceCounted(boolean refCounted)8545 public void setReferenceCounted(boolean refCounted) { 8546 mRefCounted = refCounted; 8547 } 8548 8549 /** 8550 * Checks whether this MulticastLock is currently held. 8551 * 8552 * @return true if this MulticastLock is held, false otherwise 8553 */ isHeld()8554 public boolean isHeld() { 8555 synchronized (mBinder) { 8556 return mHeld; 8557 } 8558 } 8559 toString()8560 public String toString() { 8561 String s1, s2, s3; 8562 synchronized (mBinder) { 8563 s1 = Integer.toHexString(System.identityHashCode(this)); 8564 s2 = mHeld ? "held; " : ""; 8565 if (mRefCounted) { 8566 s3 = "refcounted: refcount = " + mRefCount; 8567 } else { 8568 s3 = "not refcounted"; 8569 } 8570 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 8571 } 8572 } 8573 8574 @Override finalize()8575 protected void finalize() throws Throwable { 8576 super.finalize(); 8577 setReferenceCounted(false); 8578 release(); 8579 } 8580 } 8581 8582 /** 8583 * Check multicast filter status. 8584 * 8585 * @return true if multicast packets are allowed. 8586 * 8587 * @hide pending API council approval 8588 */ isMulticastEnabled()8589 public boolean isMulticastEnabled() { 8590 try { 8591 return mService.isMulticastEnabled(); 8592 } catch (RemoteException e) { 8593 throw e.rethrowFromSystemServer(); 8594 } 8595 } 8596 8597 /** 8598 * Initialize the multicast filtering to 'on' 8599 * @hide no intent to publish 8600 */ 8601 @UnsupportedAppUsage initializeMulticastFiltering()8602 public boolean initializeMulticastFiltering() { 8603 try { 8604 mService.initializeMulticastFiltering(); 8605 return true; 8606 } catch (RemoteException e) { 8607 throw e.rethrowFromSystemServer(); 8608 } 8609 } 8610 8611 /** 8612 * Set Wi-Fi verbose logging level from developer settings. 8613 * 8614 * @param enable true to enable verbose logging, false to disable. 8615 * 8616 * @hide 8617 */ 8618 @SystemApi 8619 @RequiresPermission(anyOf = { 8620 android.Manifest.permission.NETWORK_SETTINGS, 8621 android.Manifest.permission.DUMP 8622 }) setVerboseLoggingEnabled(boolean enable)8623 public void setVerboseLoggingEnabled(boolean enable) { 8624 enableVerboseLogging(enable ? VERBOSE_LOGGING_LEVEL_ENABLED 8625 : VERBOSE_LOGGING_LEVEL_DISABLED); 8626 } 8627 8628 /** 8629 * Set Wi-Fi verbose logging level from developer settings. 8630 * 8631 * @param verbose the verbose logging mode which could be 8632 * {@link #VERBOSE_LOGGING_LEVEL_DISABLED}, {@link #VERBOSE_LOGGING_LEVEL_ENABLED}, or 8633 * {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}. 8634 * 8635 * @hide 8636 */ 8637 @SystemApi 8638 @RequiresPermission(anyOf = { 8639 android.Manifest.permission.NETWORK_SETTINGS, 8640 android.Manifest.permission.DUMP 8641 }) setVerboseLoggingLevel(@erboseLoggingLevel int verbose)8642 public void setVerboseLoggingLevel(@VerboseLoggingLevel int verbose) { 8643 enableVerboseLogging(verbose); 8644 } 8645 8646 /** @hide */ 8647 @UnsupportedAppUsage( 8648 maxTargetSdk = Build.VERSION_CODES.Q, 8649 publicAlternatives = "Use {@code #setVerboseLoggingEnabled(boolean)} instead." 8650 ) 8651 @RequiresPermission(anyOf = { 8652 android.Manifest.permission.NETWORK_SETTINGS, 8653 android.Manifest.permission.DUMP 8654 }) enableVerboseLogging(@erboseLoggingLevel int verbose)8655 public void enableVerboseLogging(@VerboseLoggingLevel int verbose) { 8656 try { 8657 mService.enableVerboseLogging(verbose); 8658 mVerboseLoggingEnabled = 8659 verbose == VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY 8660 || verbose == VERBOSE_LOGGING_LEVEL_ENABLED; 8661 } catch (RemoteException e) { 8662 throw e.rethrowFromSystemServer(); 8663 } 8664 } 8665 8666 /** 8667 * Get the persisted Wi-Fi verbose logging level, set by 8668 * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}. 8669 * No permissions are required to call this method. 8670 * 8671 * @return true to indicate that verbose logging is enabled, false to indicate that verbose 8672 * logging is disabled. 8673 * 8674 * @hide 8675 */ 8676 @SystemApi isVerboseLoggingEnabled()8677 public boolean isVerboseLoggingEnabled() { 8678 int verboseLoggingLevel = getVerboseLoggingLevel(); 8679 return verboseLoggingLevel == VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY 8680 || verboseLoggingLevel == VERBOSE_LOGGING_LEVEL_ENABLED; 8681 } 8682 8683 /** 8684 * Get the persisted Wi-Fi verbose logging level, set by 8685 * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}. 8686 * No permissions are required to call this method. 8687 * 8688 * @return one of {@link #VERBOSE_LOGGING_LEVEL_DISABLED}, 8689 * {@link #VERBOSE_LOGGING_LEVEL_ENABLED}, 8690 * or {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}. 8691 * 8692 * @hide 8693 */ 8694 @SystemApi getVerboseLoggingLevel()8695 public @VerboseLoggingLevel int getVerboseLoggingLevel() { 8696 try { 8697 return mService.getVerboseLoggingLevel(); 8698 } catch (RemoteException e) { 8699 throw e.rethrowFromSystemServer(); 8700 } 8701 } 8702 8703 /** 8704 * Removes all saved Wi-Fi networks, Passpoint configurations, ephemeral networks, Network 8705 * Requests, and Network Suggestions. 8706 * 8707 * @hide 8708 */ 8709 @SystemApi 8710 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) factoryReset()8711 public void factoryReset() { 8712 try { 8713 mService.factoryReset(mContext.getOpPackageName()); 8714 } catch (RemoteException e) { 8715 throw e.rethrowFromSystemServer(); 8716 } 8717 } 8718 8719 /** 8720 * Get {@link Network} object of current wifi network, or null if not connected. 8721 * @hide 8722 */ 8723 @Nullable 8724 @SystemApi 8725 @RequiresPermission(anyOf = { 8726 android.Manifest.permission.NETWORK_SETTINGS, 8727 android.Manifest.permission.NETWORK_SETUP_WIZARD 8728 }) getCurrentNetwork()8729 public Network getCurrentNetwork() { 8730 try { 8731 return mService.getCurrentNetwork(); 8732 } catch (RemoteException e) { 8733 throw e.rethrowFromSystemServer(); 8734 } 8735 } 8736 8737 /** 8738 * Deprecated 8739 * returns false 8740 * @hide 8741 * @deprecated 8742 */ setEnableAutoJoinWhenAssociated(boolean enabled)8743 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 8744 return false; 8745 } 8746 8747 /** 8748 * Deprecated 8749 * returns false 8750 * @hide 8751 * @deprecated 8752 */ getEnableAutoJoinWhenAssociated()8753 public boolean getEnableAutoJoinWhenAssociated() { 8754 return false; 8755 } 8756 8757 /** 8758 * Returns a byte stream representing the data that needs to be backed up to save the 8759 * current Wifi state. 8760 * This Wifi state can be restored by calling {@link #restoreWifiBackupData(byte[])}. 8761 * @hide 8762 */ 8763 @SystemApi 8764 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 8765 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) 8766 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) retrieveWifiBackupData(@onNull @allbackExecutor Executor executor, @NonNull Consumer<byte[]> resultsCallback)8767 public void retrieveWifiBackupData(@NonNull @CallbackExecutor Executor executor, 8768 @NonNull Consumer<byte[]> resultsCallback) { 8769 if (!SdkLevel.isAtLeastV()) { 8770 throw new UnsupportedOperationException(); 8771 } 8772 8773 Objects.requireNonNull(executor, "executor cannot be null"); 8774 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 8775 try { 8776 mService.retrieveWifiBackupData( 8777 new IByteArrayListener.Stub() { 8778 @Override 8779 public void onResult(byte[] value) { 8780 Binder.clearCallingIdentity(); 8781 executor.execute(() -> { 8782 resultsCallback.accept(value); 8783 }); 8784 } 8785 }); 8786 } catch (RemoteException e) { 8787 throw e.rethrowFromSystemServer(); 8788 } 8789 } 8790 8791 /** 8792 * Restore state from the backed up data. 8793 * @param data byte stream in the same format produced by {@link #retrieveWifiBackupData()} 8794 * @hide 8795 */ 8796 @SystemApi 8797 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 8798 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) 8799 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) restoreWifiBackupData(@onNull byte[] data)8800 public void restoreWifiBackupData(@NonNull byte[] data) { 8801 if (!SdkLevel.isAtLeastV()) { 8802 throw new UnsupportedOperationException(); 8803 } 8804 try { 8805 mService.restoreWifiBackupData(data); 8806 } catch (RemoteException e) { 8807 throw e.rethrowFromSystemServer(); 8808 } 8809 } 8810 8811 /** 8812 * Returns a byte stream representing the data that needs to be backed up to save the 8813 * current Wifi state. 8814 * This Wifi state can be restored by calling {@link #restoreBackupData(byte[])}. 8815 * @hide 8816 */ 8817 @NonNull 8818 @SystemApi 8819 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) retrieveBackupData()8820 public byte[] retrieveBackupData() { 8821 try { 8822 return mService.retrieveBackupData(); 8823 } catch (RemoteException e) { 8824 throw e.rethrowFromSystemServer(); 8825 } 8826 } 8827 8828 /** 8829 * Restore state from the backed up data. 8830 * @param data byte stream in the same format produced by {@link #retrieveBackupData()} 8831 * @hide 8832 */ 8833 @SystemApi 8834 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreBackupData(@onNull byte[] data)8835 public void restoreBackupData(@NonNull byte[] data) { 8836 try { 8837 mService.restoreBackupData(data); 8838 } catch (RemoteException e) { 8839 throw e.rethrowFromSystemServer(); 8840 } 8841 } 8842 8843 /** 8844 * Returns a byte stream representing the data that needs to be backed up to save the 8845 * current soft ap config data. 8846 * 8847 * This soft ap config can be restored by calling {@link #restoreSoftApBackupData(byte[])} 8848 * @hide 8849 */ 8850 @NonNull 8851 @SystemApi 8852 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) retrieveSoftApBackupData()8853 public byte[] retrieveSoftApBackupData() { 8854 try { 8855 return mService.retrieveSoftApBackupData(); 8856 } catch (RemoteException e) { 8857 throw e.rethrowFromSystemServer(); 8858 } 8859 } 8860 8861 /** 8862 * Returns soft ap config from the backed up data or null if data is invalid. 8863 * @param data byte stream in the same format produced by {@link #retrieveSoftApBackupData()} 8864 * 8865 * @hide 8866 */ 8867 @Nullable 8868 @SystemApi 8869 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreSoftApBackupData(@onNull byte[] data)8870 public SoftApConfiguration restoreSoftApBackupData(@NonNull byte[] data) { 8871 try { 8872 return mService.restoreSoftApBackupData(data); 8873 } catch (RemoteException e) { 8874 throw e.rethrowFromSystemServer(); 8875 } 8876 } 8877 8878 /** 8879 * Restore state from the older version of back up data. 8880 * The old backup data was essentially a backup of wpa_supplicant.conf 8881 * and ipconfig.txt file. 8882 * @param supplicantData bytes representing wpa_supplicant.conf 8883 * @param ipConfigData bytes representing ipconfig.txt 8884 * @hide 8885 */ 8886 @SystemApi 8887 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreSupplicantBackupData( @onNull byte[] supplicantData, @NonNull byte[] ipConfigData)8888 public void restoreSupplicantBackupData( 8889 @NonNull byte[] supplicantData, @NonNull byte[] ipConfigData) { 8890 try { 8891 mService.restoreSupplicantBackupData(supplicantData, ipConfigData); 8892 } catch (RemoteException e) { 8893 throw e.rethrowFromSystemServer(); 8894 } 8895 } 8896 8897 /** 8898 * Start subscription provisioning flow 8899 * 8900 * @param provider {@link OsuProvider} to provision with 8901 * @param executor the Executor on which to run the callback. 8902 * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow 8903 * @hide 8904 */ 8905 @SystemApi 8906 @RequiresPermission(anyOf = { 8907 android.Manifest.permission.NETWORK_SETTINGS, 8908 android.Manifest.permission.NETWORK_SETUP_WIZARD 8909 }) startSubscriptionProvisioning(@onNull OsuProvider provider, @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback)8910 public void startSubscriptionProvisioning(@NonNull OsuProvider provider, 8911 @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback) { 8912 // Verify arguments 8913 if (executor == null) { 8914 throw new IllegalArgumentException("executor must not be null"); 8915 } 8916 if (callback == null) { 8917 throw new IllegalArgumentException("callback must not be null"); 8918 } 8919 try { 8920 mService.startSubscriptionProvisioning(provider, 8921 new ProvisioningCallbackProxy(executor, callback)); 8922 } catch (RemoteException e) { 8923 throw e.rethrowFromSystemServer(); 8924 } 8925 } 8926 8927 /** 8928 * Helper class to support OSU Provisioning callbacks 8929 */ 8930 private static class ProvisioningCallbackProxy extends IProvisioningCallback.Stub { 8931 private final Executor mExecutor; 8932 private final ProvisioningCallback mCallback; 8933 ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback)8934 ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback) { 8935 mExecutor = executor; 8936 mCallback = callback; 8937 } 8938 8939 @Override onProvisioningStatus(int status)8940 public void onProvisioningStatus(int status) { 8941 mExecutor.execute(() -> mCallback.onProvisioningStatus(status)); 8942 } 8943 8944 @Override onProvisioningFailure(int status)8945 public void onProvisioningFailure(int status) { 8946 mExecutor.execute(() -> mCallback.onProvisioningFailure(status)); 8947 } 8948 8949 @Override onProvisioningComplete()8950 public void onProvisioningComplete() { 8951 mExecutor.execute(() -> mCallback.onProvisioningComplete()); 8952 } 8953 } 8954 8955 /** 8956 * Interface for Traffic state callback. Should be extended by applications and set when 8957 * calling {@link #registerTrafficStateCallback(Executor, WifiManager.TrafficStateCallback)}. 8958 * @hide 8959 */ 8960 @SystemApi 8961 public interface TrafficStateCallback { 8962 /** @hide */ 8963 @Retention(RetentionPolicy.SOURCE) 8964 @IntDef(prefix = {"DATA_ACTIVITY_"}, value = { 8965 DATA_ACTIVITY_NONE, 8966 DATA_ACTIVITY_IN, 8967 DATA_ACTIVITY_OUT, 8968 DATA_ACTIVITY_INOUT}) 8969 @interface DataActivity {} 8970 8971 // Lowest bit indicates data reception and the second lowest bit indicates data transmitted 8972 /** No data in or out */ 8973 int DATA_ACTIVITY_NONE = 0x00; 8974 /** Data in, no data out */ 8975 int DATA_ACTIVITY_IN = 0x01; 8976 /** Data out, no data in */ 8977 int DATA_ACTIVITY_OUT = 0x02; 8978 /** Data in and out */ 8979 int DATA_ACTIVITY_INOUT = 0x03; 8980 8981 /** 8982 * Callback invoked to inform clients about the current traffic state. 8983 * 8984 * @param state One of the values: {@link #DATA_ACTIVITY_NONE}, {@link #DATA_ACTIVITY_IN}, 8985 * {@link #DATA_ACTIVITY_OUT} & {@link #DATA_ACTIVITY_INOUT}. 8986 */ onStateChanged(@ataActivity int state)8987 void onStateChanged(@DataActivity int state); 8988 } 8989 8990 /** 8991 * Callback proxy for TrafficStateCallback objects. 8992 * 8993 * @hide 8994 */ 8995 private class TrafficStateCallbackProxy extends ITrafficStateCallback.Stub { 8996 private final Executor mExecutor; 8997 private final TrafficStateCallback mCallback; 8998 TrafficStateCallbackProxy(Executor executor, TrafficStateCallback callback)8999 TrafficStateCallbackProxy(Executor executor, TrafficStateCallback callback) { 9000 mExecutor = executor; 9001 mCallback = callback; 9002 } 9003 9004 @Override onStateChanged(int state)9005 public void onStateChanged(int state) { 9006 if (mVerboseLoggingEnabled) { 9007 Log.v(TAG, "TrafficStateCallbackProxy: onStateChanged state=" + state); 9008 } 9009 Binder.clearCallingIdentity(); 9010 mExecutor.execute(() -> { 9011 mCallback.onStateChanged(state); 9012 }); 9013 } 9014 } 9015 9016 /** 9017 * Registers a callback for monitoring traffic state. See {@link TrafficStateCallback}. These 9018 * callbacks will be invoked periodically by platform to inform clients about the current 9019 * traffic state. Caller can unregister a previously registered callback using 9020 * {@link #unregisterTrafficStateCallback(TrafficStateCallback)} 9021 * <p> 9022 * Applications should have the 9023 * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers 9024 * without the permission will trigger a {@link java.lang.SecurityException}. 9025 * <p> 9026 * 9027 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 9028 * object. 9029 * @param callback Callback for traffic state events 9030 * @hide 9031 */ 9032 @SystemApi 9033 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) registerTrafficStateCallback(@onNull @allbackExecutor Executor executor, @NonNull TrafficStateCallback callback)9034 public void registerTrafficStateCallback(@NonNull @CallbackExecutor Executor executor, 9035 @NonNull TrafficStateCallback callback) { 9036 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 9037 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 9038 Log.v(TAG, "registerTrafficStateCallback: callback=" + callback + ", executor=" + executor); 9039 9040 try { 9041 synchronized (sTrafficStateCallbackMap) { 9042 ITrafficStateCallback.Stub binderCallback = new TrafficStateCallbackProxy(executor, 9043 callback); 9044 sTrafficStateCallbackMap.put(System.identityHashCode(callback), binderCallback); 9045 mService.registerTrafficStateCallback(binderCallback); 9046 } 9047 } catch (RemoteException e) { 9048 throw e.rethrowFromSystemServer(); 9049 } 9050 } 9051 9052 /** 9053 * Allow callers to unregister a previously registered callback. After calling this method, 9054 * applications will no longer receive traffic state notifications. 9055 * 9056 * @param callback Callback to unregister for traffic state events 9057 * @hide 9058 */ 9059 @SystemApi 9060 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) unregisterTrafficStateCallback(@onNull TrafficStateCallback callback)9061 public void unregisterTrafficStateCallback(@NonNull TrafficStateCallback callback) { 9062 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 9063 Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback); 9064 9065 try { 9066 synchronized (sTrafficStateCallbackMap) { 9067 int callbackIdentifier = System.identityHashCode(callback); 9068 if (!sTrafficStateCallbackMap.contains(callbackIdentifier)) { 9069 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 9070 return; 9071 } 9072 mService.unregisterTrafficStateCallback( 9073 sTrafficStateCallbackMap.get(callbackIdentifier)); 9074 sTrafficStateCallbackMap.remove(callbackIdentifier); 9075 } 9076 } catch (RemoteException e) { 9077 throw e.rethrowFromSystemServer(); 9078 } 9079 } 9080 9081 /** 9082 * Helper method to update the local verbose logging flag based on the verbose logging 9083 * level from wifi service. 9084 */ updateVerboseLoggingEnabledFromService()9085 private void updateVerboseLoggingEnabledFromService() { 9086 mVerboseLoggingEnabled = isVerboseLoggingEnabled(); 9087 } 9088 9089 /** 9090 * @return true if this device supports WPA3-Personal SAE 9091 */ isWpa3SaeSupported()9092 public boolean isWpa3SaeSupported() { 9093 return isFeatureSupported(WIFI_FEATURE_WPA3_SAE); 9094 } 9095 9096 /** 9097 * @return true if this device supports WPA3-Enterprise Suite-B-192 9098 */ isWpa3SuiteBSupported()9099 public boolean isWpa3SuiteBSupported() { 9100 return isFeatureSupported(WIFI_FEATURE_WPA3_SUITE_B); 9101 } 9102 9103 /** 9104 * @return true if this device supports Wi-Fi Enhanced Open (OWE) 9105 */ isEnhancedOpenSupported()9106 public boolean isEnhancedOpenSupported() { 9107 return isFeatureSupported(WIFI_FEATURE_OWE); 9108 } 9109 9110 /** 9111 * Wi-Fi Easy Connect (DPP) introduces standardized mechanisms to simplify the provisioning and 9112 * configuration of Wi-Fi devices. 9113 * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and 9114 * search for "Easy Connect" or "Device Provisioning Protocol specification". 9115 * 9116 * @return true if this device supports Wi-Fi Easy-connect (Device Provisioning Protocol) 9117 */ isEasyConnectSupported()9118 public boolean isEasyConnectSupported() { 9119 return isFeatureSupported(WIFI_FEATURE_DPP); 9120 } 9121 9122 /** 9123 * @return true if this device supports Wi-Fi Easy Connect (DPP) Enrollee Responder mode. 9124 */ isEasyConnectEnrolleeResponderModeSupported()9125 public boolean isEasyConnectEnrolleeResponderModeSupported() { 9126 return isFeatureSupported(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER); 9127 } 9128 9129 /** 9130 * @return true if this device supports WAPI. 9131 */ isWapiSupported()9132 public boolean isWapiSupported() { 9133 return isFeatureSupported(WIFI_FEATURE_WAPI); 9134 } 9135 9136 /** 9137 * @return true if this device supports WPA3 SAE Public Key. 9138 */ isWpa3SaePublicKeySupported()9139 public boolean isWpa3SaePublicKeySupported() { 9140 // This feature is not fully implemented in the framework yet. 9141 // After the feature complete, it returns whether WIFI_FEATURE_SAE_PK 9142 // is supported or not directly. 9143 return false; 9144 } 9145 9146 /** 9147 * @return true if this device supports Wi-Fi Passpoint Terms and Conditions feature. 9148 */ isPasspointTermsAndConditionsSupported()9149 public boolean isPasspointTermsAndConditionsSupported() { 9150 return isFeatureSupported(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS); 9151 } 9152 9153 /** 9154 * @return true if this device supports WPA3 SAE Hash-to-Element. 9155 */ isWpa3SaeH2eSupported()9156 public boolean isWpa3SaeH2eSupported() { 9157 return isFeatureSupported(WIFI_FEATURE_SAE_H2E); 9158 } 9159 9160 /** 9161 * @return true if this device supports Wi-Fi Display R2. 9162 */ isWifiDisplayR2Supported()9163 public boolean isWifiDisplayR2Supported() { 9164 return isFeatureSupported(WIFI_FEATURE_WFD_R2); 9165 } 9166 9167 /** 9168 * @return true if this device supports RFC 7542 decorated identity. 9169 */ isDecoratedIdentitySupported()9170 public boolean isDecoratedIdentitySupported() { 9171 return isFeatureSupported(WIFI_FEATURE_DECORATED_IDENTITY); 9172 } 9173 9174 /** 9175 * @return true if this device supports Trust On First Use (TOFU). 9176 */ isTrustOnFirstUseSupported()9177 public boolean isTrustOnFirstUseSupported() { 9178 return isFeatureSupported(WIFI_FEATURE_TRUST_ON_FIRST_USE); 9179 } 9180 9181 /** 9182 * Wi-Fi Easy Connect DPP AKM enables provisioning and configuration of Wi-Fi devices without 9183 * the need of using the device PSK passphrase. 9184 * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and 9185 * search for "Easy Connect" or "Device Provisioning Protocol specification". 9186 * 9187 * @return true if this device supports Wi-Fi Easy-connect DPP (Device Provisioning Protocol) 9188 * AKM, false otherwise. 9189 */ isEasyConnectDppAkmSupported()9190 public boolean isEasyConnectDppAkmSupported() { 9191 return isFeatureSupported(WIFI_FEATURE_DPP_AKM); 9192 } 9193 9194 /** 9195 * Indicate that whether or not settings required TLS minimum version is supported. 9196 * 9197 * If the device doesn't support this capability, the minimum accepted TLS version is 1.0. 9198 * 9199 * @return true if this device supports setting TLS minimum version. 9200 */ isTlsMinimumVersionSupported()9201 public boolean isTlsMinimumVersionSupported() { 9202 return isFeatureSupported(WIFI_FEATURE_SET_TLS_MINIMUM_VERSION); 9203 } 9204 9205 /** 9206 * Indicate that whether or not TLS v1.3 is supported. 9207 * 9208 * If requested minimum is not supported, it will default to the maximum supported version. 9209 * 9210 * @return true if this device supports TLS v1.3. 9211 */ isTlsV13Supported()9212 public boolean isTlsV13Supported() { 9213 return isFeatureSupported(WIFI_FEATURE_TLS_V1_3); 9214 } 9215 9216 /** 9217 * @return true if this device supports Dual Band Simultaneous (DBS) operation. 9218 */ isDualBandSimultaneousSupported()9219 public boolean isDualBandSimultaneousSupported() { 9220 return isFeatureSupported(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS); 9221 } 9222 9223 /** 9224 * @return true if this device supports TID-To-Link Mapping Negotiation. 9225 */ isTidToLinkMappingNegotiationSupported()9226 public boolean isTidToLinkMappingNegotiationSupported() { 9227 return isFeatureSupported(WIFI_FEATURE_T2LM_NEGOTIATION); 9228 } 9229 9230 9231 /** 9232 * @return true if this device supports connections to Wi-Fi WEP networks. 9233 */ 9234 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) isWepSupported()9235 public boolean isWepSupported() { 9236 return isFeatureSupported(WIFI_FEATURE_WEP); 9237 } 9238 9239 /** 9240 * @return true if this device supports connections to Wi-Fi WPA-Personal networks. 9241 * 9242 * Note that this is the older and less secure WPA-Personal protocol, not WPA2-Personal 9243 * or later protocols. 9244 */ 9245 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) isWpaPersonalSupported()9246 public boolean isWpaPersonalSupported() { 9247 return isFeatureSupported(WIFI_FEATURE_WPA_PERSONAL); 9248 } 9249 9250 /** 9251 * Gets the factory Wi-Fi MAC addresses. 9252 * @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array 9253 * if failed. 9254 * @hide 9255 */ 9256 @NonNull 9257 @SystemApi 9258 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) getFactoryMacAddresses()9259 public String[] getFactoryMacAddresses() { 9260 try { 9261 return mService.getFactoryMacAddresses(); 9262 } catch (RemoteException e) { 9263 throw e.rethrowFromSystemServer(); 9264 } 9265 } 9266 9267 /** @hide */ 9268 @Retention(RetentionPolicy.SOURCE) 9269 @IntDef(prefix = {"DEVICE_MOBILITY_STATE_"}, value = { 9270 DEVICE_MOBILITY_STATE_UNKNOWN, 9271 DEVICE_MOBILITY_STATE_HIGH_MVMT, 9272 DEVICE_MOBILITY_STATE_LOW_MVMT, 9273 DEVICE_MOBILITY_STATE_STATIONARY}) 9274 public @interface DeviceMobilityState {} 9275 9276 /** 9277 * Unknown device mobility state 9278 * 9279 * @see #setDeviceMobilityState(int) 9280 * 9281 * @hide 9282 */ 9283 @SystemApi 9284 public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0; 9285 9286 /** 9287 * High movement device mobility state. 9288 * e.g. on a bike, in a motor vehicle 9289 * 9290 * @see #setDeviceMobilityState(int) 9291 * 9292 * @hide 9293 */ 9294 @SystemApi 9295 public static final int DEVICE_MOBILITY_STATE_HIGH_MVMT = 1; 9296 9297 /** 9298 * Low movement device mobility state. 9299 * e.g. walking, running 9300 * 9301 * @see #setDeviceMobilityState(int) 9302 * 9303 * @hide 9304 */ 9305 @SystemApi 9306 public static final int DEVICE_MOBILITY_STATE_LOW_MVMT = 2; 9307 9308 /** 9309 * Stationary device mobility state 9310 * 9311 * @see #setDeviceMobilityState(int) 9312 * 9313 * @hide 9314 */ 9315 @SystemApi 9316 public static final int DEVICE_MOBILITY_STATE_STATIONARY = 3; 9317 9318 /** 9319 * Updates the device mobility state. Wifi uses this information to adjust the interval between 9320 * Wifi scans in order to balance power consumption with scan accuracy. 9321 * The default mobility state when the device boots is {@link #DEVICE_MOBILITY_STATE_UNKNOWN}. 9322 * This API should be called whenever there is a change in the mobility state. 9323 * @param state the updated device mobility state 9324 * @hide 9325 */ 9326 @SystemApi 9327 @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) setDeviceMobilityState(@eviceMobilityState int state)9328 public void setDeviceMobilityState(@DeviceMobilityState int state) { 9329 try { 9330 mService.setDeviceMobilityState(state); 9331 } catch (RemoteException e) { 9332 throw e.rethrowFromSystemServer(); 9333 } 9334 } 9335 9336 /* Easy Connect - AKA Device Provisioning Protocol (DPP) */ 9337 9338 /** 9339 * Easy Connect Network role: Station. 9340 * 9341 * @hide 9342 */ 9343 @SystemApi 9344 public static final int EASY_CONNECT_NETWORK_ROLE_STA = 0; 9345 9346 /** 9347 * Easy Connect Network role: Access Point. 9348 * 9349 * @hide 9350 */ 9351 @SystemApi 9352 public static final int EASY_CONNECT_NETWORK_ROLE_AP = 1; 9353 9354 /** @hide */ 9355 @IntDef(prefix = {"EASY_CONNECT_NETWORK_ROLE_"}, value = { 9356 EASY_CONNECT_NETWORK_ROLE_STA, 9357 EASY_CONNECT_NETWORK_ROLE_AP, 9358 }) 9359 @Retention(RetentionPolicy.SOURCE) 9360 public @interface EasyConnectNetworkRole { 9361 } 9362 9363 /** Easy Connect Device information maximum allowed length */ 9364 private static final int EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH = 40; 9365 9366 /** 9367 * Easy Connect Cryptography Curve name: prime256v1 9368 * 9369 * @hide 9370 */ 9371 @SystemApi 9372 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1 = 0; 9373 9374 /** 9375 * Easy Connect Cryptography Curve name: secp384r1 9376 * 9377 * @hide 9378 */ 9379 @SystemApi 9380 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1 = 1; 9381 9382 /** 9383 * Easy Connect Cryptography Curve name: secp521r1 9384 * 9385 * @hide 9386 */ 9387 @SystemApi 9388 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1 = 2; 9389 9390 9391 /** 9392 * Easy Connect Cryptography Curve name: brainpoolP256r1 9393 * 9394 * @hide 9395 */ 9396 @SystemApi 9397 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1 = 3; 9398 9399 9400 /** 9401 * Easy Connect Cryptography Curve name: brainpoolP384r1 9402 * 9403 * @hide 9404 */ 9405 @SystemApi 9406 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1 = 4; 9407 9408 9409 /** 9410 * Easy Connect Cryptography Curve name: brainpoolP512r1 9411 * 9412 * @hide 9413 */ 9414 @SystemApi 9415 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1 = 5; 9416 9417 /** @hide */ 9418 @IntDef(prefix = {"EASY_CONNECT_CRYPTOGRAPHY_CURVE_"}, value = { 9419 EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1, 9420 EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1, 9421 EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1, 9422 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1, 9423 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1, 9424 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1, 9425 }) 9426 @Retention(RetentionPolicy.SOURCE) 9427 public @interface EasyConnectCryptographyCurve { 9428 } 9429 9430 /** 9431 * Verbose logging mode: DISABLED. 9432 * @hide 9433 */ 9434 @SystemApi 9435 public static final int VERBOSE_LOGGING_LEVEL_DISABLED = 0; 9436 9437 /** 9438 * Verbose logging mode: ENABLED. 9439 * @hide 9440 */ 9441 @SystemApi 9442 public static final int VERBOSE_LOGGING_LEVEL_ENABLED = 1; 9443 9444 /** 9445 * Verbose logging mode: ENABLED_SHOW_KEY. This mode causes the Wi-Fi password and encryption 9446 * keys to be output to the logcat. This is security sensitive information useful for debugging. 9447 * This configuration is enabled for 30 seconds and then falls back to the regular verbose mode 9448 * (i.e. to {@link VERBOSE_LOGGING_LEVEL_ENABLED}). Show key mode is not persistent, i.e. 9449 * rebooting the device would fallback to the regular verbose mode. 9450 * 9451 * @hide 9452 */ 9453 @SystemApi public static final int VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY = 2; 9454 9455 /** 9456 * Verbose logging mode: only enable for Wi-Fi Aware feature. 9457 * 9458 * @hide 9459 */ 9460 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 9461 @SystemApi 9462 public static final int VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY = 3; 9463 9464 /** @hide */ 9465 @IntDef(prefix = {"VERBOSE_LOGGING_LEVEL_"}, value = { 9466 VERBOSE_LOGGING_LEVEL_DISABLED, 9467 VERBOSE_LOGGING_LEVEL_ENABLED, 9468 VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY, 9469 VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY, 9470 }) 9471 @Retention(RetentionPolicy.SOURCE) 9472 public @interface VerboseLoggingLevel { 9473 } 9474 9475 /** 9476 * Start Easy Connect (DPP) in Configurator-Initiator role. The current device will initiate 9477 * Easy Connect bootstrapping with a peer, and configure the peer with the SSID and password of 9478 * the specified network using the Easy Connect protocol on an encrypted link. 9479 * 9480 * @param enrolleeUri URI of the Enrollee obtained separately (e.g. QR code scanning) 9481 * @param selectedNetworkId Selected network ID to be sent to the peer 9482 * @param enrolleeNetworkRole The network role of the enrollee 9483 * @param callback Callback for status updates 9484 * @param executor The Executor on which to run the callback. 9485 * @hide 9486 */ 9487 @SystemApi 9488 @RequiresPermission(anyOf = { 9489 android.Manifest.permission.NETWORK_SETTINGS, 9490 android.Manifest.permission.NETWORK_SETUP_WIZARD}) startEasyConnectAsConfiguratorInitiator(@onNull String enrolleeUri, int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)9491 public void startEasyConnectAsConfiguratorInitiator(@NonNull String enrolleeUri, 9492 int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole, 9493 @NonNull @CallbackExecutor Executor executor, 9494 @NonNull EasyConnectStatusCallback callback) { 9495 Binder binder = new Binder(); 9496 try { 9497 mService.startDppAsConfiguratorInitiator(binder, mContext.getOpPackageName(), 9498 enrolleeUri, selectedNetworkId, enrolleeNetworkRole, 9499 new EasyConnectCallbackProxy(executor, callback)); 9500 } catch (RemoteException e) { 9501 throw e.rethrowFromSystemServer(); 9502 } 9503 } 9504 9505 /** 9506 * Start Easy Connect (DPP) in Enrollee-Initiator role. The current device will initiate Easy 9507 * Connect bootstrapping with a peer, and receive the SSID and password from the peer 9508 * configurator. 9509 * 9510 * @param configuratorUri URI of the Configurator obtained separately (e.g. QR code scanning) 9511 * @param callback Callback for status updates 9512 * @param executor The Executor on which to run the callback. 9513 * @hide 9514 */ 9515 @SystemApi 9516 @RequiresPermission(anyOf = { 9517 android.Manifest.permission.NETWORK_SETTINGS, 9518 android.Manifest.permission.NETWORK_SETUP_WIZARD}) startEasyConnectAsEnrolleeInitiator(@onNull String configuratorUri, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)9519 public void startEasyConnectAsEnrolleeInitiator(@NonNull String configuratorUri, 9520 @NonNull @CallbackExecutor Executor executor, 9521 @NonNull EasyConnectStatusCallback callback) { 9522 Binder binder = new Binder(); 9523 try { 9524 mService.startDppAsEnrolleeInitiator(binder, configuratorUri, 9525 new EasyConnectCallbackProxy(executor, callback)); 9526 } catch (RemoteException e) { 9527 throw e.rethrowFromSystemServer(); 9528 } 9529 } 9530 9531 /** 9532 * Start Easy Connect (DPP) in Enrollee-Responder role. 9533 * The device will: 9534 * 1. Generate a DPP bootstrap URI and return it using the 9535 * {@link EasyConnectStatusCallback#onBootstrapUriGenerated(Uri)} method. 9536 * 2. Start DPP as a Responder, waiting for an Initiator device to start the DPP 9537 * authentication process. 9538 * The caller should use the URI provided in step #1, for instance display it as a QR code 9539 * or communicate it in some other way to the initiator device. 9540 * 9541 * @param deviceInfo Device specific information to add to the DPP URI. This field allows 9542 * the users of the configurators to identify the device. 9543 * Optional - if not provided or in case of an empty string, 9544 * Info field (I:) will be skipped in the generated DPP URI. 9545 * Allowed Range of ASCII characters in deviceInfo - %x20-7E. 9546 * semicolon and space are not allowed. Due to the limitation of maximum 9547 * allowed characters in QR code, framework adds a limit to maximum 9548 * characters in deviceInfo. Users must call 9549 * {@link WifiManager#getEasyConnectMaxAllowedResponderDeviceInfoLength() 9550 * } method to know max allowed length. Violation of these rules will 9551 * result in an exception. 9552 * @param curve Elliptic curve cryptography used to generate DPP 9553 * public/private key pair. If application is not interested in a 9554 * specific curve, use specification mandated NIST P-256 elliptic curve, 9555 * {@link WifiManager#EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1}. 9556 * @param callback Callback for status updates 9557 * @param executor The Executor on which to run the callback. 9558 * @hide 9559 */ 9560 @SystemApi 9561 @RequiresPermission(anyOf = { 9562 android.Manifest.permission.NETWORK_SETTINGS, 9563 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 9564 @RequiresApi(Build.VERSION_CODES.S) startEasyConnectAsEnrolleeResponder(@ullable String deviceInfo, @EasyConnectCryptographyCurve int curve, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)9565 public void startEasyConnectAsEnrolleeResponder(@Nullable String deviceInfo, 9566 @EasyConnectCryptographyCurve int curve, 9567 @NonNull @CallbackExecutor Executor executor, 9568 @NonNull EasyConnectStatusCallback callback) { 9569 Binder binder = new Binder(); 9570 try { 9571 mService.startDppAsEnrolleeResponder(binder, deviceInfo, curve, 9572 new EasyConnectCallbackProxy(executor, callback)); 9573 } catch (RemoteException e) { 9574 throw e.rethrowFromSystemServer(); 9575 } 9576 } 9577 9578 /** 9579 * Maximum allowed length of Device specific information that can be added to the URI of 9580 * Easy Connect responder device. 9581 * @see #startEasyConnectAsEnrolleeResponder(String, int, Executor, EasyConnectStatusCallback)} 9582 * 9583 * @hide 9584 */ 9585 @SystemApi getEasyConnectMaxAllowedResponderDeviceInfoLength()9586 public static int getEasyConnectMaxAllowedResponderDeviceInfoLength() { 9587 return EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH; 9588 } 9589 9590 /** 9591 * Stop or abort a current Easy Connect (DPP) session. This call, once processed, will 9592 * terminate any ongoing transaction, and clean up all associated resources. Caller should not 9593 * expect any callbacks once this call is made. However, due to the asynchronous nature of 9594 * this call, a callback may be fired if it was already pending in the queue. 9595 * 9596 * @hide 9597 */ 9598 @SystemApi 9599 @RequiresPermission(anyOf = { 9600 android.Manifest.permission.NETWORK_SETTINGS, 9601 android.Manifest.permission.NETWORK_SETUP_WIZARD}) stopEasyConnectSession()9602 public void stopEasyConnectSession() { 9603 try { 9604 /* Request lower layers to stop/abort and clear resources */ 9605 mService.stopDppSession(); 9606 } catch (RemoteException e) { 9607 throw e.rethrowFromSystemServer(); 9608 } 9609 } 9610 9611 /** 9612 * Helper class to support Easy Connect (DPP) callbacks 9613 * 9614 * @hide 9615 */ 9616 private static class EasyConnectCallbackProxy extends IDppCallback.Stub { 9617 private final Executor mExecutor; 9618 private final EasyConnectStatusCallback mEasyConnectStatusCallback; 9619 EasyConnectCallbackProxy(Executor executor, EasyConnectStatusCallback easyConnectStatusCallback)9620 EasyConnectCallbackProxy(Executor executor, 9621 EasyConnectStatusCallback easyConnectStatusCallback) { 9622 mExecutor = executor; 9623 mEasyConnectStatusCallback = easyConnectStatusCallback; 9624 } 9625 9626 @Override onSuccessConfigReceived(int newNetworkId)9627 public void onSuccessConfigReceived(int newNetworkId) { 9628 Log.d(TAG, "Easy Connect onSuccessConfigReceived callback"); 9629 Binder.clearCallingIdentity(); 9630 mExecutor.execute(() -> { 9631 mEasyConnectStatusCallback.onEnrolleeSuccess(newNetworkId); 9632 }); 9633 } 9634 9635 @Override onSuccess(int status)9636 public void onSuccess(int status) { 9637 Log.d(TAG, "Easy Connect onSuccess callback"); 9638 Binder.clearCallingIdentity(); 9639 mExecutor.execute(() -> { 9640 mEasyConnectStatusCallback.onConfiguratorSuccess(status); 9641 }); 9642 } 9643 9644 @Override onFailure(int status, String ssid, String channelList, int[] operatingClassArray)9645 public void onFailure(int status, String ssid, String channelList, 9646 int[] operatingClassArray) { 9647 Log.d(TAG, "Easy Connect onFailure callback"); 9648 Binder.clearCallingIdentity(); 9649 mExecutor.execute(() -> { 9650 SparseArray<int[]> channelListArray = parseDppChannelList(channelList); 9651 mEasyConnectStatusCallback.onFailure(status, ssid, channelListArray, 9652 operatingClassArray); 9653 }); 9654 } 9655 9656 @Override onProgress(int status)9657 public void onProgress(int status) { 9658 Log.d(TAG, "Easy Connect onProgress callback"); 9659 Binder.clearCallingIdentity(); 9660 mExecutor.execute(() -> { 9661 mEasyConnectStatusCallback.onProgress(status); 9662 }); 9663 } 9664 9665 @Override onBootstrapUriGenerated(@onNull String uri)9666 public void onBootstrapUriGenerated(@NonNull String uri) { 9667 Log.d(TAG, "Easy Connect onBootstrapUriGenerated callback"); 9668 if (!SdkLevel.isAtLeastS()) { 9669 Log.e(TAG, "Easy Connect bootstrap URI callback supported only on S+"); 9670 return; 9671 } 9672 Binder.clearCallingIdentity(); 9673 mExecutor.execute(() -> { 9674 mEasyConnectStatusCallback.onBootstrapUriGenerated(Uri.parse(uri)); 9675 }); 9676 } 9677 } 9678 9679 /** 9680 * Interface for Wi-Fi usability statistics listener. Should be implemented by applications and 9681 * set when calling {@link WifiManager#addOnWifiUsabilityStatsListener(Executor, 9682 * OnWifiUsabilityStatsListener)}. 9683 * 9684 * @hide 9685 */ 9686 @SystemApi 9687 public interface OnWifiUsabilityStatsListener { 9688 /** 9689 * Called when Wi-Fi usability statistics is updated. 9690 * 9691 * @param seqNum The sequence number of statistics, used to derive the timing of updated 9692 * Wi-Fi usability statistics, set by framework and incremented by one after 9693 * each update. 9694 * @param isSameBssidAndFreq The flag to indicate whether the BSSID and the frequency of 9695 * network stays the same or not relative to the last update of 9696 * Wi-Fi usability stats. 9697 * @param stats The updated Wi-Fi usability statistics. 9698 */ onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, @NonNull WifiUsabilityStatsEntry stats)9699 void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, 9700 @NonNull WifiUsabilityStatsEntry stats); 9701 } 9702 9703 /** 9704 * Interface for Wi-Fi verbose logging status listener. Should be implemented by applications 9705 * and set when calling {@link WifiManager#addWifiVerboseLoggingStatusListener(Executor, 9706 * WifiVerboseLoggingStatusListener)}. 9707 * 9708 * @hide 9709 */ 9710 @SystemApi 9711 public interface WifiVerboseLoggingStatusChangedListener { 9712 /** 9713 * Called when Wi-Fi verbose logging setting is updated. 9714 * 9715 * @param enabled true if verbose logging is enabled, false if verbose logging is disabled. 9716 */ onWifiVerboseLoggingStatusChanged(boolean enabled)9717 void onWifiVerboseLoggingStatusChanged(boolean enabled); 9718 } 9719 9720 /** 9721 * Adds a listener for Wi-Fi usability statistics. See {@link OnWifiUsabilityStatsListener}. 9722 * Multiple listeners can be added. Callers will be invoked periodically by framework to 9723 * inform clients about the current Wi-Fi usability statistics. Callers can remove a previously 9724 * added listener using 9725 * {@link #removeOnWifiUsabilityStatsListener(OnWifiUsabilityStatsListener)}. 9726 * 9727 * @param executor The executor on which callback will be invoked. 9728 * @param listener Listener for Wifi usability statistics. 9729 * 9730 * @hide 9731 */ 9732 @SystemApi 9733 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) addOnWifiUsabilityStatsListener(@onNull @allbackExecutor Executor executor, @NonNull OnWifiUsabilityStatsListener listener)9734 public void addOnWifiUsabilityStatsListener(@NonNull @CallbackExecutor Executor executor, 9735 @NonNull OnWifiUsabilityStatsListener listener) { 9736 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 9737 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 9738 if (mVerboseLoggingEnabled) { 9739 Log.v(TAG, "addOnWifiUsabilityStatsListener: listener=" + listener); 9740 } 9741 try { 9742 synchronized (sOnWifiUsabilityStatsListenerMap) { 9743 IOnWifiUsabilityStatsListener.Stub binderCallback = 9744 new IOnWifiUsabilityStatsListener.Stub() { 9745 @Override 9746 public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, 9747 WifiUsabilityStatsEntry stats) { 9748 if (mVerboseLoggingEnabled) { 9749 Log.v(TAG, "OnWifiUsabilityStatsListener: " 9750 + "onWifiUsabilityStats: seqNum=" + seqNum); 9751 } 9752 Binder.clearCallingIdentity(); 9753 executor.execute(() -> listener.onWifiUsabilityStats( 9754 seqNum, isSameBssidAndFreq, stats)); 9755 } 9756 }; 9757 sOnWifiUsabilityStatsListenerMap.put(System.identityHashCode(listener), 9758 binderCallback); 9759 mService.addOnWifiUsabilityStatsListener(binderCallback); 9760 } 9761 } catch (RemoteException e) { 9762 throw e.rethrowFromSystemServer(); 9763 } 9764 } 9765 9766 /** 9767 * Allow callers to remove a previously registered listener. After calling this method, 9768 * applications will no longer receive Wi-Fi usability statistics. 9769 * 9770 * @param listener Listener to remove the Wi-Fi usability statistics. 9771 * 9772 * @hide 9773 */ 9774 @SystemApi 9775 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) removeOnWifiUsabilityStatsListener(@onNull OnWifiUsabilityStatsListener listener)9776 public void removeOnWifiUsabilityStatsListener(@NonNull OnWifiUsabilityStatsListener listener) { 9777 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 9778 if (mVerboseLoggingEnabled) { 9779 Log.v(TAG, "removeOnWifiUsabilityStatsListener: listener=" + listener); 9780 } 9781 try { 9782 synchronized (sOnWifiUsabilityStatsListenerMap) { 9783 int listenerIdentifier = System.identityHashCode(listener); 9784 if (!sOnWifiUsabilityStatsListenerMap.contains(listenerIdentifier)) { 9785 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 9786 return; 9787 } 9788 mService.removeOnWifiUsabilityStatsListener( 9789 sOnWifiUsabilityStatsListenerMap.get(listenerIdentifier)); 9790 sOnWifiUsabilityStatsListenerMap.remove(listenerIdentifier); 9791 } 9792 } catch (RemoteException e) { 9793 throw e.rethrowFromSystemServer(); 9794 } 9795 } 9796 9797 /** 9798 * Provide a Wi-Fi usability score information to be recorded (but not acted upon) by the 9799 * framework. The Wi-Fi usability score is derived from {@link OnWifiUsabilityStatsListener} 9800 * where a score is matched to Wi-Fi usability statistics using the sequence number. The score 9801 * is used to quantify whether Wi-Fi is usable in a future time. 9802 * 9803 * @param seqNum Sequence number of the Wi-Fi usability score. 9804 * @param score The Wi-Fi usability score, expected range: [0, 100]. 9805 * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score in second, 9806 * expected range: [0, 30]. 9807 * 9808 * @hide 9809 */ 9810 @SystemApi 9811 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec)9812 public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { 9813 try { 9814 mService.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec); 9815 } catch (RemoteException e) { 9816 throw e.rethrowFromSystemServer(); 9817 } 9818 } 9819 9820 /** 9821 * Gets the list of BSSIDs which are currently disabled for Wi-Fi auto-join connections. 9822 * 9823 * @param ssids If empty, then get all currently disabled BSSIDs. 9824 * If non-empty, then only get currently disabled BSSIDs with matching SSIDs. 9825 * @param executor The executor to execute the callback of the {@code resultListener} object. 9826 * @param resultListener callback to retrieve the blocked BSSIDs 9827 * 9828 * @hide 9829 */ 9830 @SystemApi 9831 @FlaggedApi(Flags.FLAG_GET_BSSID_BLOCKLIST_API) 9832 @RequiresPermission(anyOf = { 9833 android.Manifest.permission.NETWORK_SETTINGS, 9834 android.Manifest.permission.NETWORK_SETUP_WIZARD}) getBssidBlocklist(@onNull List<WifiSsid> ssids, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<List<MacAddress>> resultListener)9835 public void getBssidBlocklist(@NonNull List<WifiSsid> ssids, 9836 @NonNull @CallbackExecutor Executor executor, 9837 @NonNull Consumer<List<MacAddress>> resultListener) { 9838 Objects.requireNonNull(ssids, "ssids cannot be null"); 9839 Objects.requireNonNull(executor, "executor cannot be null"); 9840 Objects.requireNonNull(resultListener, "resultsCallback cannot be null"); 9841 try { 9842 mService.getBssidBlocklist( 9843 new ParceledListSlice<>(ssids), 9844 new IMacAddressListListener.Stub() { 9845 @Override 9846 public void onResult(ParceledListSlice<MacAddress> value) { 9847 Binder.clearCallingIdentity(); 9848 executor.execute(() -> { 9849 resultListener.accept(value.getList()); 9850 }); 9851 } 9852 }); 9853 } catch (RemoteException e) { 9854 throw e.rethrowFromSystemServer(); 9855 } 9856 } 9857 9858 /** 9859 * Abstract class for scan results callback. Should be extended by applications and set when 9860 * calling {@link WifiManager#registerScanResultsCallback(Executor, ScanResultsCallback)}. 9861 */ 9862 public abstract static class ScanResultsCallback { 9863 private final ScanResultsCallbackProxy mScanResultsCallbackProxy; 9864 ScanResultsCallback()9865 public ScanResultsCallback() { 9866 mScanResultsCallbackProxy = new ScanResultsCallbackProxy(); 9867 } 9868 9869 /** 9870 * Called when new scan results are available. 9871 * Clients should use {@link WifiManager#getScanResults()} to get the scan results. 9872 */ onScanResultsAvailable()9873 public abstract void onScanResultsAvailable(); 9874 getProxy()9875 /*package*/ @NonNull ScanResultsCallbackProxy getProxy() { 9876 return mScanResultsCallbackProxy; 9877 } 9878 9879 private static class ScanResultsCallbackProxy extends IScanResultsCallback.Stub { 9880 private final Object mLock = new Object(); 9881 @Nullable @GuardedBy("mLock") private Executor mExecutor; 9882 @Nullable @GuardedBy("mLock") private ScanResultsCallback mCallback; 9883 ScanResultsCallbackProxy()9884 ScanResultsCallbackProxy() { 9885 mCallback = null; 9886 mExecutor = null; 9887 } 9888 initProxy(@onNull Executor executor, @NonNull ScanResultsCallback callback)9889 /*package*/ void initProxy(@NonNull Executor executor, 9890 @NonNull ScanResultsCallback callback) { 9891 synchronized (mLock) { 9892 mExecutor = executor; 9893 mCallback = callback; 9894 } 9895 } 9896 cleanUpProxy()9897 /*package*/ void cleanUpProxy() { 9898 synchronized (mLock) { 9899 mExecutor = null; 9900 mCallback = null; 9901 } 9902 } 9903 9904 @Override onScanResultsAvailable()9905 public void onScanResultsAvailable() { 9906 ScanResultsCallback callback; 9907 Executor executor; 9908 synchronized (mLock) { 9909 executor = mExecutor; 9910 callback = mCallback; 9911 } 9912 if (callback == null || executor == null) { 9913 return; 9914 } 9915 Binder.clearCallingIdentity(); 9916 executor.execute(callback::onScanResultsAvailable); 9917 } 9918 } 9919 } 9920 9921 /** 9922 * Register a callback for Scan Results. See {@link ScanResultsCallback}. 9923 * Caller will receive the event when scan results are available. 9924 * Caller should use {@link WifiManager#getScanResults()} requires 9925 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} to get the scan results. 9926 * Caller can remove a previously registered callback using 9927 * {@link WifiManager#unregisterScanResultsCallback(ScanResultsCallback)} 9928 * Same caller can add multiple listeners. 9929 * <p> 9930 * Applications should have the 9931 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission. Callers 9932 * without the permission will trigger a {@link java.lang.SecurityException}. 9933 * <p> 9934 * 9935 * @param executor The executor to execute the callback of the {@code callback} object. 9936 * @param callback callback for Scan Results events 9937 */ 9938 9939 @RequiresPermission(ACCESS_WIFI_STATE) registerScanResultsCallback(@onNull @allbackExecutor Executor executor, @NonNull ScanResultsCallback callback)9940 public void registerScanResultsCallback(@NonNull @CallbackExecutor Executor executor, 9941 @NonNull ScanResultsCallback callback) { 9942 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 9943 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 9944 9945 Log.v(TAG, "registerScanResultsCallback: callback=" + callback 9946 + ", executor=" + executor); 9947 ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy(); 9948 proxy.initProxy(executor, callback); 9949 try { 9950 mService.registerScanResultsCallback(proxy); 9951 } catch (RemoteException e) { 9952 throw e.rethrowFromSystemServer(); 9953 } 9954 } 9955 9956 /** 9957 * Allow callers to unregister a previously registered callback. After calling this method, 9958 * applications will no longer receive Scan Results events. 9959 * 9960 * @param callback callback to unregister for Scan Results events 9961 */ 9962 @RequiresPermission(ACCESS_WIFI_STATE) unregisterScanResultsCallback(@onNull ScanResultsCallback callback)9963 public void unregisterScanResultsCallback(@NonNull ScanResultsCallback callback) { 9964 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 9965 Log.v(TAG, "unregisterScanResultsCallback: Callback=" + callback); 9966 ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy(); 9967 try { 9968 mService.unregisterScanResultsCallback(proxy); 9969 } catch (RemoteException e) { 9970 throw e.rethrowFromSystemServer(); 9971 } finally { 9972 proxy.cleanUpProxy(); 9973 } 9974 } 9975 9976 /** 9977 * Interface for suggestion connection status listener. 9978 * Should be implemented by applications and set when calling 9979 * {@link WifiManager#addSuggestionConnectionStatusListener( 9980 * Executor, SuggestionConnectionStatusListener)}. 9981 */ 9982 public interface SuggestionConnectionStatusListener { 9983 9984 /** 9985 * Called when the framework attempted to connect to a suggestion provided by the 9986 * registering app, but the connection to the suggestion failed. 9987 * @param wifiNetworkSuggestion The suggestion which failed to connect. 9988 * @param failureReason the connection failure reason code. 9989 */ onConnectionStatus( @onNull WifiNetworkSuggestion wifiNetworkSuggestion, @SuggestionConnectionStatusCode int failureReason)9990 void onConnectionStatus( 9991 @NonNull WifiNetworkSuggestion wifiNetworkSuggestion, 9992 @SuggestionConnectionStatusCode int failureReason); 9993 } 9994 9995 private class SuggestionConnectionStatusListenerProxy extends 9996 ISuggestionConnectionStatusListener.Stub { 9997 private final Executor mExecutor; 9998 private final SuggestionConnectionStatusListener mListener; 9999 SuggestionConnectionStatusListenerProxy(@onNull Executor executor, @NonNull SuggestionConnectionStatusListener listener)10000 SuggestionConnectionStatusListenerProxy(@NonNull Executor executor, 10001 @NonNull SuggestionConnectionStatusListener listener) { 10002 mExecutor = executor; 10003 mListener = listener; 10004 } 10005 10006 @Override onConnectionStatus(@onNull WifiNetworkSuggestion wifiNetworkSuggestion, int failureReason)10007 public void onConnectionStatus(@NonNull WifiNetworkSuggestion wifiNetworkSuggestion, 10008 int failureReason) { 10009 Binder.clearCallingIdentity(); 10010 mExecutor.execute(() -> 10011 mListener.onConnectionStatus(wifiNetworkSuggestion, failureReason)); 10012 } 10013 10014 } 10015 10016 /** 10017 * Interface for local-only connection failure listener. 10018 * Should be implemented by applications and set when calling 10019 * {@link WifiManager#addLocalOnlyConnectionFailureListener(Executor, LocalOnlyConnectionFailureListener)} 10020 */ 10021 public interface LocalOnlyConnectionFailureListener { 10022 10023 /** 10024 * Called when the framework attempted to connect to a local-only network requested by the 10025 * registering app, but the connection to the network failed. 10026 * @param wifiNetworkSpecifier The {@link WifiNetworkSpecifier} which failed to connect. 10027 * @param failureReason the connection failure reason code. 10028 */ onConnectionFailed( @onNull WifiNetworkSpecifier wifiNetworkSpecifier, @LocalOnlyConnectionStatusCode int failureReason)10029 void onConnectionFailed( 10030 @NonNull WifiNetworkSpecifier wifiNetworkSpecifier, 10031 @LocalOnlyConnectionStatusCode int failureReason); 10032 } 10033 10034 private static class LocalOnlyConnectionStatusListenerProxy extends 10035 ILocalOnlyConnectionStatusListener.Stub { 10036 private final Executor mExecutor; 10037 private final LocalOnlyConnectionFailureListener mListener; 10038 LocalOnlyConnectionStatusListenerProxy(@onNull Executor executor, @NonNull LocalOnlyConnectionFailureListener listener)10039 LocalOnlyConnectionStatusListenerProxy(@NonNull Executor executor, 10040 @NonNull LocalOnlyConnectionFailureListener listener) { 10041 mExecutor = executor; 10042 mListener = listener; 10043 } 10044 10045 @Override onConnectionStatus(@onNull WifiNetworkSpecifier networkSpecifier, int failureReason)10046 public void onConnectionStatus(@NonNull WifiNetworkSpecifier networkSpecifier, 10047 int failureReason) { 10048 Binder.clearCallingIdentity(); 10049 mExecutor.execute(() -> 10050 mListener.onConnectionFailed(networkSpecifier, failureReason)); 10051 } 10052 10053 } 10054 10055 /** 10056 * Add a listener listening to wifi verbose logging changes. 10057 * See {@link WifiVerboseLoggingStatusChangedListener}. 10058 * Caller can remove a previously registered listener using 10059 * {@link WifiManager#removeWifiVerboseLoggingStatusChangedListener( 10060 * WifiVerboseLoggingStatusChangedListener)} 10061 * Same caller can add multiple listeners to monitor the event. 10062 * <p> 10063 * Applications should have the 10064 * {@link android.Manifest.permission#ACCESS_WIFI_STATE}. 10065 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 10066 * <p> 10067 * @param executor The executor to execute the listener of the {@code listener} object. 10068 * @param listener listener for changes in wifi verbose logging. 10069 * 10070 * @hide 10071 */ 10072 @SystemApi 10073 @RequiresPermission(ACCESS_WIFI_STATE) addWifiVerboseLoggingStatusChangedListener( @onNull @allbackExecutor Executor executor, @NonNull WifiVerboseLoggingStatusChangedListener listener)10074 public void addWifiVerboseLoggingStatusChangedListener( 10075 @NonNull @CallbackExecutor Executor executor, 10076 @NonNull WifiVerboseLoggingStatusChangedListener listener) { 10077 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 10078 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 10079 if (mVerboseLoggingEnabled) { 10080 Log.v(TAG, "addWifiVerboseLoggingStatusChangedListener listener=" + listener 10081 + ", executor=" + executor); 10082 } 10083 try { 10084 synchronized (sWifiVerboseLoggingStatusChangedListenerMap) { 10085 IWifiVerboseLoggingStatusChangedListener.Stub binderCallback = 10086 new IWifiVerboseLoggingStatusChangedListener.Stub() { 10087 @Override 10088 public void onStatusChanged(boolean enabled) { 10089 if (mVerboseLoggingEnabled) { 10090 Log.v(TAG, "WifiVerboseLoggingStatusListener: " 10091 + "onVerboseLoggingStatusChanged: enabled=" + enabled); 10092 } 10093 Binder.clearCallingIdentity(); 10094 executor.execute(() -> listener.onWifiVerboseLoggingStatusChanged( 10095 enabled)); 10096 } 10097 }; 10098 sWifiVerboseLoggingStatusChangedListenerMap.put(System.identityHashCode(listener), 10099 binderCallback); 10100 mService.addWifiVerboseLoggingStatusChangedListener(binderCallback); 10101 } 10102 } catch (RemoteException e) { 10103 throw e.rethrowFromSystemServer(); 10104 } 10105 } 10106 10107 /** 10108 * Allow callers to remove a previously registered listener. 10109 * <p> 10110 * Applications should have the 10111 * {@link android.Manifest.permission#ACCESS_WIFI_STATE}. 10112 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 10113 * <p> 10114 * @param listener listener to remove. 10115 * 10116 * @hide 10117 */ 10118 @SystemApi 10119 @RequiresPermission(ACCESS_WIFI_STATE) removeWifiVerboseLoggingStatusChangedListener( @onNull WifiVerboseLoggingStatusChangedListener listener)10120 public void removeWifiVerboseLoggingStatusChangedListener( 10121 @NonNull WifiVerboseLoggingStatusChangedListener listener) { 10122 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 10123 Log.v(TAG, "removeWifiVerboseLoggingStatusChangedListener: listener=" + listener); 10124 try { 10125 synchronized (sWifiVerboseLoggingStatusChangedListenerMap) { 10126 int listenerIdentifier = System.identityHashCode(listener); 10127 if (!sWifiVerboseLoggingStatusChangedListenerMap.contains(listenerIdentifier)) { 10128 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 10129 return; 10130 } 10131 mService.removeWifiVerboseLoggingStatusChangedListener( 10132 sWifiVerboseLoggingStatusChangedListenerMap.get(listenerIdentifier)); 10133 sWifiVerboseLoggingStatusChangedListenerMap.remove(listenerIdentifier); 10134 } 10135 } catch (RemoteException e) { 10136 throw e.rethrowFromSystemServer(); 10137 } 10138 } 10139 10140 /** 10141 * Add a listener for suggestion networks. See {@link SuggestionConnectionStatusListener}. 10142 * Caller will receive the event when suggested network have connection failure. 10143 * Caller can remove a previously registered listener using 10144 * {@link WifiManager#removeSuggestionConnectionStatusListener( 10145 * SuggestionConnectionStatusListener)} 10146 * Same caller can add multiple listeners to monitor the event. 10147 * <p> 10148 * Applications should have the 10149 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and 10150 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permissions. 10151 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 10152 * <p> 10153 * 10154 * @param executor The executor to execute the listener of the {@code listener} object. 10155 * @param listener listener for suggestion network connection failure. 10156 */ 10157 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) addSuggestionConnectionStatusListener(@onNull @allbackExecutor Executor executor, @NonNull SuggestionConnectionStatusListener listener)10158 public void addSuggestionConnectionStatusListener(@NonNull @CallbackExecutor Executor executor, 10159 @NonNull SuggestionConnectionStatusListener listener) { 10160 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 10161 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 10162 Log.v(TAG, "addSuggestionConnectionStatusListener listener=" + listener 10163 + ", executor=" + executor); 10164 try { 10165 synchronized (sSuggestionConnectionStatusListenerMap) { 10166 ISuggestionConnectionStatusListener.Stub binderCallback = 10167 new SuggestionConnectionStatusListenerProxy(executor, listener); 10168 sSuggestionConnectionStatusListenerMap.put(System.identityHashCode(listener), 10169 binderCallback); 10170 mService.registerSuggestionConnectionStatusListener(binderCallback, 10171 mContext.getOpPackageName(), mContext.getAttributionTag()); 10172 } 10173 } catch (RemoteException e) { 10174 throw e.rethrowFromSystemServer(); 10175 } 10176 10177 } 10178 10179 /** 10180 * Allow callers to remove a previously registered listener. After calling this method, 10181 * applications will no longer receive suggestion connection events through that listener. 10182 * 10183 * @param listener listener to remove. 10184 */ 10185 @RequiresPermission(ACCESS_WIFI_STATE) removeSuggestionConnectionStatusListener( @onNull SuggestionConnectionStatusListener listener)10186 public void removeSuggestionConnectionStatusListener( 10187 @NonNull SuggestionConnectionStatusListener listener) { 10188 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 10189 Log.v(TAG, "removeSuggestionConnectionStatusListener: listener=" + listener); 10190 try { 10191 synchronized (sSuggestionConnectionStatusListenerMap) { 10192 int listenerIdentifier = System.identityHashCode(listener); 10193 if (!sSuggestionConnectionStatusListenerMap.contains(listenerIdentifier)) { 10194 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 10195 return; 10196 } 10197 mService.unregisterSuggestionConnectionStatusListener( 10198 sSuggestionConnectionStatusListenerMap.get(listenerIdentifier), 10199 mContext.getOpPackageName()); 10200 sSuggestionConnectionStatusListenerMap.remove(listenerIdentifier); 10201 } 10202 } catch (RemoteException e) { 10203 throw e.rethrowFromSystemServer(); 10204 } 10205 } 10206 10207 /** 10208 * Add a listener for local-only networks. See {@link WifiNetworkSpecifier}. 10209 * Specify the caller will only get connection failures for networks they requested. 10210 * Caller can remove a previously registered listener using 10211 * {@link WifiManager#removeLocalOnlyConnectionFailureListener(LocalOnlyConnectionFailureListener)} 10212 * Same caller can add multiple listeners to monitor the event. 10213 * <p> 10214 * Applications should have the {@link android.Manifest.permission#ACCESS_WIFI_STATE} 10215 * permissions. 10216 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 10217 * <p> 10218 * 10219 * @param executor The executor to execute the listener of the {@code listener} object. 10220 * @param listener listener for local-only network connection failure. 10221 */ 10222 @RequiresPermission(ACCESS_WIFI_STATE) addLocalOnlyConnectionFailureListener(@onNull @allbackExecutor Executor executor, @NonNull LocalOnlyConnectionFailureListener listener)10223 public void addLocalOnlyConnectionFailureListener(@NonNull @CallbackExecutor Executor executor, 10224 @NonNull LocalOnlyConnectionFailureListener listener) { 10225 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 10226 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 10227 try { 10228 synchronized (sLocalOnlyConnectionStatusListenerMap) { 10229 if (sLocalOnlyConnectionStatusListenerMap 10230 .contains(System.identityHashCode(listener))) { 10231 Log.w(TAG, "Same listener already registered"); 10232 return; 10233 } 10234 ILocalOnlyConnectionStatusListener.Stub binderCallback = 10235 new LocalOnlyConnectionStatusListenerProxy(executor, listener); 10236 sLocalOnlyConnectionStatusListenerMap.put(System.identityHashCode(listener), 10237 binderCallback); 10238 mService.addLocalOnlyConnectionStatusListener(binderCallback, 10239 mContext.getOpPackageName(), mContext.getAttributionTag()); 10240 } 10241 } catch (RemoteException e) { 10242 throw e.rethrowFromSystemServer(); 10243 } 10244 } 10245 10246 /** 10247 * Allow callers to remove a previously registered listener. After calling this method, 10248 * applications will no longer receive local-only connection events through that listener. 10249 * 10250 * @param listener listener to remove. 10251 */ 10252 @RequiresPermission(ACCESS_WIFI_STATE) removeLocalOnlyConnectionFailureListener( @onNull LocalOnlyConnectionFailureListener listener)10253 public void removeLocalOnlyConnectionFailureListener( 10254 @NonNull LocalOnlyConnectionFailureListener listener) { 10255 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 10256 try { 10257 synchronized (sLocalOnlyConnectionStatusListenerMap) { 10258 int listenerIdentifier = System.identityHashCode(listener); 10259 if (!sLocalOnlyConnectionStatusListenerMap.contains(listenerIdentifier)) { 10260 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 10261 return; 10262 } 10263 mService.removeLocalOnlyConnectionStatusListener( 10264 sLocalOnlyConnectionStatusListenerMap.get(listenerIdentifier), 10265 mContext.getOpPackageName()); 10266 sLocalOnlyConnectionStatusListenerMap.remove(listenerIdentifier); 10267 } 10268 } catch (RemoteException e) { 10269 throw e.rethrowFromSystemServer(); 10270 } 10271 } 10272 10273 /** 10274 * Parse the list of channels the DPP enrollee reports when it fails to find an AP. 10275 * 10276 * @param channelList List of channels in the format defined in the DPP specification. 10277 * @return A parsed sparse array, where the operating class is the key. 10278 * @hide 10279 */ 10280 @VisibleForTesting parseDppChannelList(String channelList)10281 public static SparseArray<int[]> parseDppChannelList(String channelList) { 10282 SparseArray<int[]> channelListArray = new SparseArray<>(); 10283 10284 if (TextUtils.isEmpty(channelList)) { 10285 return channelListArray; 10286 } 10287 StringTokenizer str = new StringTokenizer(channelList, ","); 10288 String classStr = null; 10289 List<Integer> channelsInClass = new ArrayList<>(); 10290 10291 try { 10292 while (str.hasMoreElements()) { 10293 String cur = str.nextToken(); 10294 10295 /** 10296 * Example for a channel list: 10297 * 10298 * 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, 10299 * 116,120,124,128,132,136,140,0/144,124/149,153,157,161,125/165 10300 * 10301 * Detect operating class by the delimiter of '/' and use a string tokenizer with 10302 * ',' as a delimiter. 10303 */ 10304 int classDelim = cur.indexOf('/'); 10305 if (classDelim != -1) { 10306 if (classStr != null) { 10307 // Store the last channel array in the sparse array, where the operating 10308 // class is the key (as an integer). 10309 int[] channelsArray = new int[channelsInClass.size()]; 10310 for (int i = 0; i < channelsInClass.size(); i++) { 10311 channelsArray[i] = channelsInClass.get(i); 10312 } 10313 channelListArray.append(Integer.parseInt(classStr), channelsArray); 10314 channelsInClass = new ArrayList<>(); 10315 } 10316 10317 // Init a new operating class and store the first channel 10318 classStr = cur.substring(0, classDelim); 10319 String channelStr = cur.substring(classDelim + 1); 10320 channelsInClass.add(Integer.parseInt(channelStr)); 10321 } else { 10322 if (classStr == null) { 10323 // Invalid format 10324 Log.e(TAG, "Cannot parse DPP channel list"); 10325 return new SparseArray<>(); 10326 } 10327 channelsInClass.add(Integer.parseInt(cur)); 10328 } 10329 } 10330 10331 // Store the last array 10332 if (classStr != null) { 10333 int[] channelsArray = new int[channelsInClass.size()]; 10334 for (int i = 0; i < channelsInClass.size(); i++) { 10335 channelsArray[i] = channelsInClass.get(i); 10336 } 10337 channelListArray.append(Integer.parseInt(classStr), channelsArray); 10338 } 10339 return channelListArray; 10340 } catch (NumberFormatException e) { 10341 Log.e(TAG, "Cannot parse DPP channel list"); 10342 return new SparseArray<>(); 10343 } 10344 } 10345 10346 /** 10347 * If isFullCapture is true, capture everything in ring buffer 10348 * 10349 * If isFullCapture is false, extract WifiUsabilityStatsEntries from ring buffer whose 10350 * timestamps are within [triggerStartTimeMillis, triggerStopTimeMillis) in WiFiMetrics, and 10351 * store them as upload candidates. 10352 * 10353 * Source of elapsed time since boot will be android.os.SystemClock.elapsedRealtime() 10354 * 10355 * @param executor The executor on which callback will be invoked. 10356 * @param resultsCallback An asynchronous callback that will return a execution result of 10357 * mWifiMetrics.storeCapturedData 10358 * @param triggerType data capture trigger type 10359 * @param isFullCapture if we do full capture on ring buffer or not 10360 * @param triggerStartTimeMillis data capture start timestamp, elapsed time since boot 10361 * @param triggerStopTimeMillis data capture stop timestamp, elapsed time since boot 10362 * @hide 10363 */ 10364 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) storeCapturedData(@onNull @allbackExecutor Executor executor, @NonNull IntConsumer resultsCallback, int triggerType, boolean isFullCapture, long triggerStartTimeMillis, long triggerStopTimeMillis)10365 public void storeCapturedData(@NonNull @CallbackExecutor Executor executor, 10366 @NonNull IntConsumer resultsCallback, int triggerType, boolean isFullCapture, 10367 long triggerStartTimeMillis, long triggerStopTimeMillis) { 10368 Objects.requireNonNull(executor, "executor cannot be null"); 10369 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 10370 try { 10371 mService.storeCapturedData(triggerType, isFullCapture, triggerStartTimeMillis, 10372 triggerStopTimeMillis, new IIntegerListener.Stub() { 10373 @Override 10374 public void onResult(int value) { 10375 Binder.clearCallingIdentity(); 10376 executor.execute(() -> { 10377 resultsCallback.accept(value); 10378 }); 10379 } 10380 }); 10381 } catch (RemoteException e) { 10382 throw e.rethrowFromSystemServer(); 10383 } 10384 } 10385 10386 /** 10387 * Callback interface for framework to receive network status updates and trigger of updating 10388 * {@link WifiUsabilityStatsEntry}. 10389 * 10390 * @hide 10391 */ 10392 @SystemApi 10393 public interface ScoreUpdateObserver { 10394 /** 10395 * Called by applications to indicate network status. For applications targeting 10396 * {@link android.os.Build.VERSION_CODES#S} or above: The score is not used to take action 10397 * on network selection but for the purpose of Wifi metric collection only; Network 10398 * selection is influenced by inputs from 10399 * {@link ScoreUpdateObserver#notifyStatusUpdate(int, boolean)}, 10400 * {@link ScoreUpdateObserver#requestNudOperation(int, boolean)}, and 10401 * {@link ScoreUpdateObserver#blocklistCurrentBssid(int)}. 10402 * 10403 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10404 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10405 * @param score The score representing link quality of current Wi-Fi network connection. 10406 * Populated by connected network scorer in applications.. 10407 */ notifyScoreUpdate(int sessionId, int score)10408 void notifyScoreUpdate(int sessionId, int score); 10409 10410 /** 10411 * Called by applications to trigger an update of {@link WifiUsabilityStatsEntry}. 10412 * To receive update applications need to add WifiUsabilityStatsEntry listener. See 10413 * {@link addOnWifiUsabilityStatsListener(Executor, OnWifiUsabilityStatsListener)}. 10414 * 10415 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10416 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10417 */ triggerUpdateOfWifiUsabilityStats(int sessionId)10418 void triggerUpdateOfWifiUsabilityStats(int sessionId); 10419 10420 /** 10421 * Called by applications to indicate whether current Wi-Fi network is usable or not. 10422 * 10423 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10424 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10425 * @param isUsable The boolean representing whether current Wi-Fi network is usable, and it 10426 * may be sent to ConnectivityService and used for setting default network. 10427 * Populated by connected network scorer in applications. 10428 */ 10429 @RequiresApi(Build.VERSION_CODES.S) notifyStatusUpdate(int sessionId, boolean isUsable)10430 default void notifyStatusUpdate(int sessionId, boolean isUsable) {} 10431 10432 /** 10433 * Called by applications to start a NUD (Neighbor Unreachability Detection) operation. The 10434 * framework throttles NUD operations to no more frequently than every five seconds 10435 * (see {@link WifiScoreReport#NUD_THROTTLE_MILLIS}). The framework keeps track of requests 10436 * and executes them as soon as possible based on the throttling criteria. 10437 * 10438 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10439 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10440 */ 10441 @RequiresApi(Build.VERSION_CODES.S) requestNudOperation(int sessionId)10442 default void requestNudOperation(int sessionId) {} 10443 10444 /** 10445 * Called by applications to blocklist currently connected BSSID. No blocklisting operation 10446 * if called after disconnection. 10447 * 10448 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10449 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10450 */ 10451 @RequiresApi(Build.VERSION_CODES.S) blocklistCurrentBssid(int sessionId)10452 default void blocklistCurrentBssid(int sessionId) {} 10453 } 10454 10455 /** 10456 * Callback proxy for {@link ScoreUpdateObserver} objects. 10457 * 10458 * @hide 10459 */ 10460 private class ScoreUpdateObserverProxy implements ScoreUpdateObserver { 10461 private final IScoreUpdateObserver mScoreUpdateObserver; 10462 ScoreUpdateObserverProxy(IScoreUpdateObserver observer)10463 private ScoreUpdateObserverProxy(IScoreUpdateObserver observer) { 10464 mScoreUpdateObserver = observer; 10465 } 10466 10467 @Override notifyScoreUpdate(int sessionId, int score)10468 public void notifyScoreUpdate(int sessionId, int score) { 10469 try { 10470 mScoreUpdateObserver.notifyScoreUpdate(sessionId, score); 10471 } catch (RemoteException e) { 10472 throw e.rethrowFromSystemServer(); 10473 } 10474 } 10475 10476 @Override triggerUpdateOfWifiUsabilityStats(int sessionId)10477 public void triggerUpdateOfWifiUsabilityStats(int sessionId) { 10478 try { 10479 mScoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(sessionId); 10480 } catch (RemoteException e) { 10481 throw e.rethrowFromSystemServer(); 10482 } 10483 } 10484 10485 @Override notifyStatusUpdate(int sessionId, boolean isUsable)10486 public void notifyStatusUpdate(int sessionId, boolean isUsable) { 10487 if (!SdkLevel.isAtLeastS()) { 10488 throw new UnsupportedOperationException(); 10489 } 10490 try { 10491 mScoreUpdateObserver.notifyStatusUpdate(sessionId, isUsable); 10492 } catch (RemoteException e) { 10493 throw e.rethrowFromSystemServer(); 10494 } 10495 } 10496 10497 @Override requestNudOperation(int sessionId)10498 public void requestNudOperation(int sessionId) { 10499 if (!SdkLevel.isAtLeastS()) { 10500 throw new UnsupportedOperationException(); 10501 } 10502 try { 10503 mScoreUpdateObserver.requestNudOperation(sessionId); 10504 } catch (RemoteException e) { 10505 throw e.rethrowFromSystemServer(); 10506 } 10507 } 10508 10509 @Override blocklistCurrentBssid(int sessionId)10510 public void blocklistCurrentBssid(int sessionId) { 10511 if (!SdkLevel.isAtLeastS()) { 10512 throw new UnsupportedOperationException(); 10513 } 10514 try { 10515 mScoreUpdateObserver.blocklistCurrentBssid(sessionId); 10516 } catch (RemoteException e) { 10517 throw e.rethrowFromSystemServer(); 10518 } 10519 } 10520 } 10521 10522 /** 10523 * Interface for Wi-Fi connected network scorer. Should be implemented by applications and set 10524 * when calling 10525 * {@link WifiManager#setWifiConnectedNetworkScorer(Executor, WifiConnectedNetworkScorer)}. 10526 * 10527 * @hide 10528 */ 10529 @SystemApi 10530 public interface WifiConnectedNetworkScorer { 10531 /** 10532 * Called by framework to indicate the start of a network connection. 10533 * @param sessionId The ID to indicate current Wi-Fi network connection. 10534 * @deprecated This API is deprecated. Please use 10535 * {@link WifiConnectedNetworkScorer#onStart(WifiConnectedSessionInfo)}. 10536 */ 10537 @Deprecated onStart(int sessionId)10538 default void onStart(int sessionId) {} 10539 10540 /** 10541 * Called by framework to indicate the start of a network connection. 10542 * @param sessionInfo The session information to indicate current Wi-Fi network connection. 10543 * See {@link WifiConnectedSessionInfo}. 10544 */ onStart(@onNull WifiConnectedSessionInfo sessionInfo)10545 default void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) { 10546 onStart(sessionInfo.getSessionId()); 10547 } 10548 10549 /** 10550 * Called by framework to indicate the end of a network connection. 10551 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10552 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10553 */ onStop(int sessionId)10554 void onStop(int sessionId); 10555 10556 /** 10557 * Framework sets callback for score change events after application sets its scorer. 10558 * @param observerImpl The instance for {@link WifiManager#ScoreUpdateObserver}. Should be 10559 * implemented and instantiated by framework. 10560 */ onSetScoreUpdateObserver(@onNull ScoreUpdateObserver observerImpl)10561 void onSetScoreUpdateObserver(@NonNull ScoreUpdateObserver observerImpl); 10562 10563 /** 10564 * Called by framework to indicate the user accepted a dialog to switch to a new network. 10565 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10566 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10567 * @param targetNetworkId Network ID of the target network. 10568 * @param targetBssid BSSID of the target network. 10569 */ onNetworkSwitchAccepted( int sessionId, int targetNetworkId, @NonNull String targetBssid)10570 default void onNetworkSwitchAccepted( 10571 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10572 // No-op. 10573 } 10574 10575 /** 10576 * Called by framework to indicate the user rejected a dialog to switch to new network. 10577 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 10578 * {@link WifiConnectedNetworkScorer#onStart(int)}. 10579 * @param targetNetworkId Network ID of the target network. 10580 * @param targetBssid BSSID of the target network. 10581 */ onNetworkSwitchRejected( int sessionId, int targetNetworkId, @NonNull String targetBssid)10582 default void onNetworkSwitchRejected( 10583 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10584 // No-op. 10585 } 10586 } 10587 10588 10589 /** 10590 * Callback registered with {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor, 10591 * PnoScanResultsCallback)}. Returns status and result information on offloaded external PNO 10592 * requests. 10593 * @hide 10594 */ 10595 @SystemApi 10596 public interface PnoScanResultsCallback { 10597 /** 10598 * A status code returned by {@link #onRegisterFailed(int)}. 10599 * Unknown failure. 10600 */ 10601 int REGISTER_PNO_CALLBACK_UNKNOWN = 0; 10602 10603 /** 10604 * A status code returned by {@link #onRegisterFailed(int)}. 10605 * A callback has already been registered by the caller. 10606 */ 10607 int REGISTER_PNO_CALLBACK_ALREADY_REGISTERED = 1; 10608 10609 /** 10610 * A status code returned by {@link #onRegisterFailed(int)}. 10611 * The platform is unable to serve this request because another app has a PNO scan request 10612 * active. 10613 */ 10614 int REGISTER_PNO_CALLBACK_RESOURCE_BUSY = 2; 10615 10616 /** 10617 * A status code returned by {@link #onRegisterFailed(int)}. 10618 * PNO scans are not supported on this device. 10619 */ 10620 int REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED = 3; 10621 10622 /** @hide */ 10623 @IntDef(prefix = { "REGISTER_PNO_CALLBACK_" }, value = { 10624 REGISTER_PNO_CALLBACK_UNKNOWN, 10625 REGISTER_PNO_CALLBACK_ALREADY_REGISTERED, 10626 REGISTER_PNO_CALLBACK_RESOURCE_BUSY, 10627 REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED 10628 }) 10629 @Retention(RetentionPolicy.SOURCE) 10630 public @interface RegisterFailureReason {} 10631 10632 /** 10633 * A status code returned by {@link #onRemoved(int)}. 10634 * Unknown reason. 10635 */ 10636 int REMOVE_PNO_CALLBACK_UNKNOWN = 0; 10637 10638 /** 10639 * A status code returned by {@link #onRemoved(int)}. 10640 * This Callback is automatically removed after results ScanResults are delivered. 10641 */ 10642 int REMOVE_PNO_CALLBACK_RESULTS_DELIVERED = 1; 10643 10644 /** 10645 * A status code returned by {@link #onRemoved(int)}. 10646 * This callback has been unregistered via {@link WifiManager#clearExternalPnoScanRequest()} 10647 */ 10648 int REMOVE_PNO_CALLBACK_UNREGISTERED = 2; 10649 10650 /** @hide */ 10651 @IntDef(prefix = { "REMOVE_PNO_CALLBACK_" }, value = { 10652 REMOVE_PNO_CALLBACK_UNKNOWN, 10653 REMOVE_PNO_CALLBACK_RESULTS_DELIVERED, 10654 REMOVE_PNO_CALLBACK_UNREGISTERED 10655 }) 10656 @Retention(RetentionPolicy.SOURCE) 10657 public @interface RemovalReason {} 10658 10659 /** 10660 * Called when PNO scan finds one of the requested SSIDs. This is a one time callback. 10661 * After results are reported the callback will be automatically unregistered. 10662 */ onScanResultsAvailable(@onNull List<ScanResult> scanResults)10663 void onScanResultsAvailable(@NonNull List<ScanResult> scanResults); 10664 10665 /** 10666 * Called when this callback has been successfully registered. 10667 */ onRegisterSuccess()10668 void onRegisterSuccess(); 10669 10670 /** 10671 * Called when this callback failed to register with the failure reason. 10672 * See {@link RegisterFailureReason} for details. 10673 */ onRegisterFailed(@egisterFailureReason int reason)10674 void onRegisterFailed(@RegisterFailureReason int reason); 10675 10676 /** 10677 * Called when this callback has been unregistered from the Wi-Fi subsystem. 10678 * See {@link RemovalReason} for details. 10679 */ onRemoved(@emovalReason int reason)10680 void onRemoved(@RemovalReason int reason); 10681 } 10682 10683 10684 private class PnoScanResultsCallbackProxy extends IPnoScanResultsCallback.Stub { 10685 private Executor mExecutor; 10686 private PnoScanResultsCallback mCallback; 10687 PnoScanResultsCallbackProxy(@onNull Executor executor, @NonNull PnoScanResultsCallback callback)10688 PnoScanResultsCallbackProxy(@NonNull Executor executor, 10689 @NonNull PnoScanResultsCallback callback) { 10690 mExecutor = executor; 10691 mCallback = callback; 10692 } 10693 10694 @Override onScanResultsAvailable(List<ScanResult> scanResults)10695 public void onScanResultsAvailable(List<ScanResult> scanResults) { 10696 if (mVerboseLoggingEnabled) { 10697 Log.v(TAG, "PnoScanResultsCallback: " + "onScanResultsAvailable"); 10698 } 10699 Binder.clearCallingIdentity(); 10700 mExecutor.execute(() -> mCallback.onScanResultsAvailable(scanResults)); 10701 } 10702 10703 @Override onRegisterSuccess()10704 public void onRegisterSuccess() { 10705 if (mVerboseLoggingEnabled) { 10706 Log.v(TAG, "PnoScanResultsCallback: " + "onRegisterSuccess"); 10707 } 10708 Binder.clearCallingIdentity(); 10709 mExecutor.execute(() -> mCallback.onRegisterSuccess()); 10710 } 10711 10712 @Override onRegisterFailed(int reason)10713 public void onRegisterFailed(int reason) { 10714 if (mVerboseLoggingEnabled) { 10715 Log.v(TAG, "PnoScanResultsCallback: " + "onRegisterFailed " + reason); 10716 } 10717 Binder.clearCallingIdentity(); 10718 mExecutor.execute(() -> mCallback.onRegisterFailed(reason)); 10719 } 10720 10721 @Override onRemoved(int reason)10722 public void onRemoved(int reason) { 10723 if (mVerboseLoggingEnabled) { 10724 Log.v(TAG, "PnoScanResultsCallback: " + "onRemoved"); 10725 } 10726 Binder.clearCallingIdentity(); 10727 mExecutor.execute(() -> mCallback.onRemoved(reason)); 10728 } 10729 } 10730 10731 /** 10732 * Callback proxy for {@link WifiConnectedNetworkScorer} objects. 10733 * 10734 * @hide 10735 */ 10736 private class WifiConnectedNetworkScorerProxy extends IWifiConnectedNetworkScorer.Stub { 10737 private Executor mExecutor; 10738 private WifiConnectedNetworkScorer mScorer; 10739 WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer)10740 WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer) { 10741 mExecutor = executor; 10742 mScorer = scorer; 10743 } 10744 10745 @Override onStart(@onNull WifiConnectedSessionInfo sessionInfo)10746 public void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) { 10747 if (mVerboseLoggingEnabled) { 10748 Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStart: sessionInfo=" + sessionInfo); 10749 } 10750 Binder.clearCallingIdentity(); 10751 mExecutor.execute(() -> mScorer.onStart(sessionInfo)); 10752 } 10753 10754 @Override onStop(int sessionId)10755 public void onStop(int sessionId) { 10756 if (mVerboseLoggingEnabled) { 10757 Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStop: sessionId=" + sessionId); 10758 } 10759 Binder.clearCallingIdentity(); 10760 mExecutor.execute(() -> mScorer.onStop(sessionId)); 10761 } 10762 10763 @Override onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl)10764 public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) { 10765 if (mVerboseLoggingEnabled) { 10766 Log.v(TAG, "WifiConnectedNetworkScorer: " 10767 + "onSetScoreUpdateObserver: observerImpl=" + observerImpl); 10768 } 10769 Binder.clearCallingIdentity(); 10770 mExecutor.execute(() -> mScorer.onSetScoreUpdateObserver( 10771 new ScoreUpdateObserverProxy(observerImpl))); 10772 } 10773 10774 @Override onNetworkSwitchAccepted( int sessionId, int targetNetworkId, @NonNull String targetBssid)10775 public void onNetworkSwitchAccepted( 10776 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10777 if (mVerboseLoggingEnabled) { 10778 Log.v(TAG, "WifiConnectedNetworkScorer: onNetworkSwitchAccepted:" 10779 + " sessionId=" + sessionId 10780 + " targetNetworkId=" + targetNetworkId 10781 + " targetBssid=" + targetBssid); 10782 } 10783 Binder.clearCallingIdentity(); 10784 mExecutor.execute(() -> mScorer.onNetworkSwitchAccepted( 10785 sessionId, targetNetworkId, targetBssid)); 10786 } 10787 @Override onNetworkSwitchRejected( int sessionId, int targetNetworkId, @NonNull String targetBssid)10788 public void onNetworkSwitchRejected( 10789 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10790 if (mVerboseLoggingEnabled) { 10791 Log.v(TAG, "WifiConnectedNetworkScorer: onNetworkSwitchRejected:" 10792 + " sessionId=" + sessionId 10793 + " targetNetworkId=" + targetNetworkId 10794 + " targetBssid=" + targetBssid); 10795 } 10796 Binder.clearCallingIdentity(); 10797 mExecutor.execute(() -> mScorer.onNetworkSwitchRejected( 10798 sessionId, targetNetworkId, targetBssid)); 10799 } 10800 } 10801 10802 /** 10803 * This API allows the caller to program up to 2 SSIDs for PNO scans. PNO scans are offloaded 10804 * to the Wi-Fi chip when the device is inactive (typically screen-off). 10805 * If the screen is currently off when this API is called, then a PNO scan including the 10806 * requested SSIDs will immediately get started. If the screen is on when this API is called, 10807 * the requested SSIDs will get included for PNO scans the next time the screen turns off. 10808 * <p> 10809 * Note, due to PNO being a limited resource, only one external PNO request is supported, and 10810 * calling this API will fail if an external PNO scan request is already registered by another 10811 * caller. If the caller that has already registered a callback calls this API again, the new 10812 * callback will override the previous one. 10813 * <p> 10814 * After this API is called, {@link PnoScanResultsCallback#onRegisterSuccess()} will be invoked 10815 * if the operation is successful, or {@link PnoScanResultsCallback#onRegisterFailed(int)} will 10816 * be invoked if the operation failed. 10817 * <p> 10818 * {@link PnoScanResultsCallback#onRemoved(int)} will be invoked to notify the caller when the 10819 * external PNO scan request is removed, which will happen when one of the following events 10820 * happen: 10821 * </p> 10822 * <ul> 10823 * <li>Upon finding any of the requested SSIDs through either a connectivity scan or PNO scan, 10824 * the matching ScanResults will be returned 10825 * via {@link PnoScanResultsCallback#onScanResultsAvailable(List)}, and the registered PNO 10826 * scan request will get automatically removed.</li> 10827 * <li>The external PNO scan request is removed by a call to 10828 * {@link #clearExternalPnoScanRequest()}</li> 10829 * </ul> 10830 * 10831 * @param ssids The list of SSIDs to request for PNO scan. 10832 * @param frequencies Provide as hint a list of up to 10 frequencies to be used for PNO scan. 10833 * Each frequency should be in MHz. For example 2412 and 5180 are valid 10834 * frequencies. {@link WifiInfo#getFrequency()} is a location where this 10835 * information could be obtained. If a null or empty array is provided, the 10836 * Wi-Fi framework will automatically decide the list of frequencies to scan. 10837 * @param executor The executor on which callback will be invoked. 10838 * @param callback For the calling application to receive results and status updates. 10839 * 10840 * @throws SecurityException if the caller does not have permission. 10841 * @throws IllegalArgumentException if the caller provided invalid inputs. 10842 * @throws UnsupportedOperationException if this API is not supported on this SDK version. 10843 * @hide 10844 */ 10845 @SystemApi 10846 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, 10847 REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}) 10848 @RequiresApi(Build.VERSION_CODES.TIRAMISU) setExternalPnoScanRequest(@onNull List<WifiSsid> ssids, @Nullable int[] frequencies, @NonNull @CallbackExecutor Executor executor, @NonNull PnoScanResultsCallback callback)10849 public void setExternalPnoScanRequest(@NonNull List<WifiSsid> ssids, 10850 @Nullable int[] frequencies, @NonNull @CallbackExecutor Executor executor, 10851 @NonNull PnoScanResultsCallback callback) { 10852 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 10853 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 10854 try { 10855 mService.setExternalPnoScanRequest(new Binder(), 10856 new PnoScanResultsCallbackProxy(executor, callback), 10857 ssids, frequencies == null ? new int[0] : frequencies, 10858 mContext.getOpPackageName(), mContext.getAttributionTag()); 10859 } catch (RemoteException e) { 10860 throw e.rethrowFromSystemServer(); 10861 } 10862 } 10863 10864 /** 10865 * Wi-Fi Preferred Network Offload (PNO) scanning offloads scanning to the chip to save power 10866 * when Wi-Fi is disconnected and the screen is off. See 10867 * {@link https://source.android.com/docs/core/connect/wifi-scan} for more details. 10868 * <p> 10869 * This API can be used to enable or disable PNO scanning. After boot, PNO scanning is enabled 10870 * by default. When PNO scanning is disabled, the Wi-Fi framework will not trigger scans at all 10871 * when the screen is off. This can be used to save power on devices with small batteries. 10872 * 10873 * @param enabled True - enable PNO scanning 10874 * False - disable PNO scanning 10875 * @param enablePnoScanAfterWifiToggle True - Wifi being enabled by 10876 * {@link #setWifiEnabled(boolean)} will re-enable PNO 10877 * scanning. 10878 * False - Wifi being enabled by 10879 * {@link #setWifiEnabled(boolean)} will not re-enable PNO 10880 * scanning. 10881 * 10882 * @throws SecurityException if the caller does not have permission. 10883 * @hide 10884 */ 10885 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 10886 @SystemApi 10887 @RequiresPermission( 10888 anyOf = {MANAGE_WIFI_NETWORK_SELECTION, NETWORK_SETTINGS, NETWORK_SETUP_WIZARD}) setPnoScanState(@noScanState int pnoScanState)10889 public void setPnoScanState(@PnoScanState int pnoScanState) { 10890 try { 10891 boolean enabled = false; 10892 boolean enablePnoScanAfterWifiToggle = false; 10893 switch (pnoScanState) { 10894 case PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT: 10895 break; 10896 case PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE: 10897 enablePnoScanAfterWifiToggle = true; 10898 break; 10899 case PNO_SCAN_STATE_ENABLED: 10900 enabled = true; 10901 break; 10902 default: 10903 throw new IllegalArgumentException("Invalid PnoScanState"); 10904 } 10905 mService.setPnoScanEnabled(enabled, enablePnoScanAfterWifiToggle, 10906 mContext.getOpPackageName()); 10907 } catch (RemoteException e) { 10908 throw e.rethrowFromSystemServer(); 10909 } 10910 } 10911 10912 /** 10913 * Wi-Fi Preferred Network Offload (PNO) scanning offloads scanning to the chip to save power 10914 * when Wi-Fi is disconnected and the screen is off. See 10915 * {@link https://source.android.com/docs/core/connect/wifi-scan} for more details. 10916 * <p> 10917 * This API can be used to enable or disable PNO scanning. After boot, PNO scanning is enabled 10918 * by default. When PNO scanning is disabled, the Wi-Fi framework will not trigger scans at all 10919 * when the screen is off. This can be used to save power on devices with small batteries. 10920 * 10921 * @param enabled True - enable PNO scanning 10922 * False - disable PNO scanning 10923 * @param enablePnoScanAfterWifiToggle True - Wifi being enabled by 10924 * {@link #setWifiEnabled(boolean)} will re-enable PNO 10925 * scanning. 10926 * False - Wifi being enabled by 10927 * {@link #setWifiEnabled(boolean)} will not re-enable PNO 10928 * scanning. 10929 * 10930 * @throws SecurityException if the caller does not have permission. 10931 * @hide 10932 */ 10933 @RequiresPermission( 10934 anyOf = {MANAGE_WIFI_NETWORK_SELECTION, NETWORK_SETTINGS, NETWORK_SETUP_WIZARD}) setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle)10935 public void setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle) { 10936 try { 10937 mService.setPnoScanEnabled(enabled, enablePnoScanAfterWifiToggle, 10938 mContext.getOpPackageName()); 10939 } catch (RemoteException e) { 10940 throw e.rethrowFromSystemServer(); 10941 } 10942 } 10943 10944 /** 10945 * Clear the current PNO scan request that's been set by the calling UID. Note, the call will 10946 * be no-op if the current PNO scan request is set by a different UID. 10947 * 10948 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 10949 * @hide 10950 */ 10951 @SystemApi 10952 @RequiresApi(Build.VERSION_CODES.TIRAMISU) clearExternalPnoScanRequest()10953 public void clearExternalPnoScanRequest() { 10954 try { 10955 mService.clearExternalPnoScanRequest(); 10956 } catch (RemoteException e) { 10957 throw e.rethrowFromSystemServer(); 10958 } 10959 } 10960 10961 /** 10962 * Returns information about the last caller of an API. 10963 * 10964 * @param apiType The type of API to request information for the last caller. 10965 * @param executor The executor on which callback will be invoked. 10966 * @param resultsCallback An asynchronous callback that will return 2 arguments. 10967 * {@code String} the name of the package that performed the last API 10968 * call. {@code Boolean} the value associated with the last API call. 10969 * 10970 * @throws SecurityException if the caller does not have permission. 10971 * @throws IllegalArgumentException if the caller provided invalid inputs. 10972 * @hide 10973 */ 10974 @SystemApi 10975 @RequiresPermission(anyOf = { 10976 android.Manifest.permission.NETWORK_SETTINGS, 10977 android.Manifest.permission.NETWORK_STACK, 10978 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) getLastCallerInfoForApi(@piType int apiType, @NonNull @CallbackExecutor Executor executor, @NonNull BiConsumer<String, Boolean> resultsCallback)10979 public void getLastCallerInfoForApi(@ApiType int apiType, 10980 @NonNull @CallbackExecutor Executor executor, 10981 @NonNull BiConsumer<String, Boolean> resultsCallback) { 10982 if (executor == null) { 10983 throw new IllegalArgumentException("executor can't be null"); 10984 } 10985 if (resultsCallback == null) { 10986 throw new IllegalArgumentException("resultsCallback can't be null"); 10987 } 10988 try { 10989 mService.getLastCallerInfoForApi(apiType, 10990 new ILastCallerListener.Stub() { 10991 @Override 10992 public void onResult(String packageName, boolean enabled) { 10993 Binder.clearCallingIdentity(); 10994 executor.execute(() -> { 10995 resultsCallback.accept(packageName, enabled); 10996 }); 10997 } 10998 }); 10999 } catch (RemoteException e) { 11000 throw e.rethrowFromSystemServer(); 11001 } 11002 } 11003 11004 /** 11005 * Set a callback for Wi-Fi connected network scorer. See {@link WifiConnectedNetworkScorer}. 11006 * Only a single scorer can be set. Caller will be invoked periodically by framework to inform 11007 * client about start and stop of Wi-Fi connection. Caller can clear a previously set scorer 11008 * using {@link clearWifiConnectedNetworkScorer()}. 11009 * 11010 * @param executor The executor on which callback will be invoked. 11011 * @param scorer Scorer for Wi-Fi network implemented by application. 11012 * @return true Scorer is set successfully. 11013 * 11014 * @hide 11015 */ 11016 @SystemApi 11017 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) setWifiConnectedNetworkScorer(@onNull @allbackExecutor Executor executor, @NonNull WifiConnectedNetworkScorer scorer)11018 public boolean setWifiConnectedNetworkScorer(@NonNull @CallbackExecutor Executor executor, 11019 @NonNull WifiConnectedNetworkScorer scorer) { 11020 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 11021 if (scorer == null) throw new IllegalArgumentException("scorer cannot be null"); 11022 if (mVerboseLoggingEnabled) { 11023 Log.v(TAG, "setWifiConnectedNetworkScorer: scorer=" + scorer); 11024 } 11025 try { 11026 return mService.setWifiConnectedNetworkScorer(new Binder(), 11027 new WifiConnectedNetworkScorerProxy(executor, scorer)); 11028 } catch (RemoteException e) { 11029 throw e.rethrowFromSystemServer(); 11030 } 11031 } 11032 11033 /** 11034 * Allow caller to clear a previously set scorer. After calling this method, 11035 * client will no longer receive information about start and stop of Wi-Fi connection. 11036 * 11037 * @hide 11038 */ 11039 @SystemApi 11040 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) clearWifiConnectedNetworkScorer()11041 public void clearWifiConnectedNetworkScorer() { 11042 if (mVerboseLoggingEnabled) { 11043 Log.v(TAG, "clearWifiConnectedNetworkScorer"); 11044 } 11045 try { 11046 mService.clearWifiConnectedNetworkScorer(); 11047 } catch (RemoteException e) { 11048 throw e.rethrowFromSystemServer(); 11049 } 11050 } 11051 11052 /** 11053 * Enable/disable wifi scan throttling from 3rd party apps. 11054 * 11055 * <p> 11056 * The throttling limits for apps are described in 11057 * <a href="Wi-Fi Scan Throttling"> 11058 * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a> 11059 * </p> 11060 * 11061 * @param enable true to allow scan throttling, false to disallow scan throttling. 11062 * @hide 11063 */ 11064 @SystemApi 11065 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setScanThrottleEnabled(boolean enable)11066 public void setScanThrottleEnabled(boolean enable) { 11067 try { 11068 mService.setScanThrottleEnabled(enable); 11069 } catch (RemoteException e) { 11070 throw e.rethrowFromSystemServer(); 11071 } 11072 } 11073 11074 /** 11075 * Get the persisted Wi-Fi scan throttle state. Defaults to true, unless changed by the user via 11076 * Developer options. 11077 * 11078 * <p> 11079 * The throttling limits for apps are described in 11080 * <a href="Wi-Fi Scan Throttling"> 11081 * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a> 11082 * </p> 11083 * 11084 * @return true to indicate that scan throttling is enabled, false to indicate that scan 11085 * throttling is disabled. 11086 */ 11087 @RequiresPermission(ACCESS_WIFI_STATE) isScanThrottleEnabled()11088 public boolean isScanThrottleEnabled() { 11089 try { 11090 return mService.isScanThrottleEnabled(); 11091 } catch (RemoteException e) { 11092 throw e.rethrowFromSystemServer(); 11093 } 11094 } 11095 11096 /** 11097 * Enable/disable wifi auto wakeup feature. 11098 * 11099 * <p> 11100 * The feature is described in 11101 * <a href="Wi-Fi Turn on automatically"> 11102 * https://source.android.com/devices/tech/connect/wifi-infrastructure 11103 * #turn_on_wi-fi_automatically 11104 * </a> 11105 * 11106 * @param enable true to enable, false to disable. 11107 * @hide 11108 */ 11109 @SystemApi 11110 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setAutoWakeupEnabled(boolean enable)11111 public void setAutoWakeupEnabled(boolean enable) { 11112 try { 11113 mService.setAutoWakeupEnabled(enable); 11114 } catch (RemoteException e) { 11115 throw e.rethrowFromSystemServer(); 11116 } 11117 } 11118 11119 /** 11120 * Get the persisted Wi-Fi auto wakeup feature state. Defaults to false, unless changed by the 11121 * user via Settings. 11122 * 11123 * <p> 11124 * The feature is described in 11125 * <a href="Wi-Fi Turn on automatically"> 11126 * https://source.android.com/devices/tech/connect/wifi-infrastructure 11127 * #turn_on_wi-fi_automatically 11128 * </a> 11129 * 11130 * @return true to indicate that wakeup feature is enabled, false to indicate that wakeup 11131 * feature is disabled. 11132 */ 11133 @RequiresPermission(ACCESS_WIFI_STATE) isAutoWakeupEnabled()11134 public boolean isAutoWakeupEnabled() { 11135 try { 11136 return mService.isAutoWakeupEnabled(); 11137 } catch (RemoteException e) { 11138 throw e.rethrowFromSystemServer(); 11139 } 11140 } 11141 11142 /** 11143 * Sets the state of carrier offload on merged or unmerged networks for specified subscription. 11144 * 11145 * <p> 11146 * When a subscription's carrier network offload is disabled, all network suggestions related to 11147 * this subscription will not be considered for auto join. 11148 * <p> 11149 * If calling app want disable all carrier network offload from a specified subscription, should 11150 * call this API twice to disable both merged and unmerged carrier network suggestions. 11151 * 11152 * @param subscriptionId See {@link SubscriptionInfo#getSubscriptionId()}. 11153 * @param merged True for carrier merged network, false otherwise. 11154 * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} 11155 * @param enabled True for enable carrier network offload, false otherwise. 11156 * @see #isCarrierNetworkOffloadEnabled(int, boolean) 11157 * @hide 11158 */ 11159 @SystemApi 11160 @RequiresPermission(anyOf = { 11161 android.Manifest.permission.NETWORK_SETTINGS, 11162 android.Manifest.permission.NETWORK_SETUP_WIZARD}) setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, boolean enabled)11163 public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, 11164 boolean enabled) { 11165 try { 11166 mService.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled); 11167 } catch (RemoteException e) { 11168 throw e.rethrowFromSystemServer(); 11169 } 11170 } 11171 11172 /** 11173 * Get the carrier network offload state for merged or unmerged networks for specified 11174 * subscription. 11175 * @param subscriptionId subscription ID see {@link SubscriptionInfo#getSubscriptionId()} 11176 * @param merged True for carrier merged network, false otherwise. 11177 * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} 11178 * @return True to indicate that carrier network offload is enabled, false otherwise. 11179 */ 11180 @RequiresPermission(ACCESS_WIFI_STATE) isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged)11181 public boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged) { 11182 try { 11183 return mService.isCarrierNetworkOffloadEnabled(subscriptionId, merged); 11184 } catch (RemoteException e) { 11185 throw e.rethrowFromSystemServer(); 11186 } 11187 } 11188 11189 /** 11190 * Interface for network suggestion user approval status change listener. 11191 * Should be implemented by applications and registered using 11192 * {@link #addSuggestionUserApprovalStatusListener(Executor, 11193 * SuggestionUserApprovalStatusListener)} ( 11194 */ 11195 public interface SuggestionUserApprovalStatusListener { 11196 11197 /** 11198 * Called when the user approval status of the App has changed. 11199 * @param status The current status code for the user approval. One of the 11200 * {@code STATUS_SUGGESTION_APPROVAL_} values. 11201 */ onUserApprovalStatusChange(@uggestionUserApprovalStatus int status)11202 void onUserApprovalStatusChange(@SuggestionUserApprovalStatus int status); 11203 } 11204 11205 private class SuggestionUserApprovalStatusListenerProxy extends 11206 ISuggestionUserApprovalStatusListener.Stub { 11207 private final Executor mExecutor; 11208 private final SuggestionUserApprovalStatusListener mListener; 11209 SuggestionUserApprovalStatusListenerProxy(@onNull Executor executor, @NonNull SuggestionUserApprovalStatusListener listener)11210 SuggestionUserApprovalStatusListenerProxy(@NonNull Executor executor, 11211 @NonNull SuggestionUserApprovalStatusListener listener) { 11212 mExecutor = executor; 11213 mListener = listener; 11214 } 11215 11216 @Override onUserApprovalStatusChange(int status)11217 public void onUserApprovalStatusChange(int status) { 11218 mExecutor.execute(() -> mListener.onUserApprovalStatusChange(status)); 11219 } 11220 11221 } 11222 11223 /** 11224 * Add a listener for Wi-Fi network suggestion user approval status. 11225 * See {@link SuggestionUserApprovalStatusListener}. 11226 * Caller will receive a callback immediately after adding a listener and when the user approval 11227 * status of the caller has changed. 11228 * Caller can remove a previously registered listener using 11229 * {@link WifiManager#removeSuggestionUserApprovalStatusListener( 11230 * SuggestionUserApprovalStatusListener)} 11231 * A caller can add multiple listeners to monitor the event. 11232 * @param executor The executor to execute the listener of the {@code listener} object. 11233 * @param listener listener for suggestion user approval status changes. 11234 */ 11235 @RequiresPermission(ACCESS_WIFI_STATE) addSuggestionUserApprovalStatusListener( @onNull @allbackExecutor Executor executor, @NonNull SuggestionUserApprovalStatusListener listener)11236 public void addSuggestionUserApprovalStatusListener( 11237 @NonNull @CallbackExecutor Executor executor, 11238 @NonNull SuggestionUserApprovalStatusListener listener) { 11239 if (listener == null) throw new NullPointerException("Listener cannot be null"); 11240 if (executor == null) throw new NullPointerException("Executor cannot be null"); 11241 Log.v(TAG, "addSuggestionUserApprovalStatusListener listener=" + listener 11242 + ", executor=" + executor); 11243 try { 11244 synchronized (sSuggestionUserApprovalStatusListenerMap) { 11245 ISuggestionUserApprovalStatusListener.Stub binderCallback = 11246 new SuggestionUserApprovalStatusListenerProxy(executor, listener); 11247 sSuggestionUserApprovalStatusListenerMap.put(System.identityHashCode(listener), 11248 binderCallback); 11249 mService.addSuggestionUserApprovalStatusListener(binderCallback, 11250 mContext.getOpPackageName()); 11251 } 11252 } catch (RemoteException e) { 11253 throw e.rethrowFromSystemServer(); 11254 } 11255 11256 } 11257 11258 /** 11259 * Allow callers to remove a previously registered listener using 11260 * {@link #addSuggestionUserApprovalStatusListener(Executor, 11261 * SuggestionUserApprovalStatusListener)}. After calling this method, 11262 * applications will no longer receive network suggestion user approval status change through 11263 * that listener. 11264 */ 11265 @RequiresPermission(ACCESS_WIFI_STATE) removeSuggestionUserApprovalStatusListener( @onNull SuggestionUserApprovalStatusListener listener)11266 public void removeSuggestionUserApprovalStatusListener( 11267 @NonNull SuggestionUserApprovalStatusListener listener) { 11268 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 11269 Log.v(TAG, "removeSuggestionUserApprovalStatusListener: listener=" + listener); 11270 try { 11271 synchronized (sSuggestionUserApprovalStatusListenerMap) { 11272 int listenerIdentifier = System.identityHashCode(listener); 11273 if (!sSuggestionUserApprovalStatusListenerMap.contains(listenerIdentifier)) { 11274 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 11275 return; 11276 } 11277 mService.removeSuggestionUserApprovalStatusListener( 11278 sSuggestionUserApprovalStatusListenerMap.get(listenerIdentifier), 11279 mContext.getOpPackageName()); 11280 sSuggestionUserApprovalStatusListenerMap.remove(listenerIdentifier); 11281 } 11282 } catch (RemoteException e) { 11283 throw e.rethrowFromSystemServer(); 11284 } 11285 } 11286 11287 /** 11288 * Indicates the start/end of an emergency scan request being processed by {@link WifiScanner}. 11289 * The wifi stack should ensure that the wifi chip remains on for the duration of the scan. 11290 * WifiScanner detects emergency scan requests via 11291 * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag. 11292 * 11293 * If the wifi stack is off (because location & wifi toggles are off) when this indication is 11294 * received, the wifi stack will temporarily move to a scan only mode. Since location toggle 11295 * is off, only scan with 11296 * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag set will be 11297 * allowed to be processed for this duration. 11298 * 11299 * @hide 11300 */ 11301 @RequiresPermission(android.Manifest.permission.NETWORK_STACK) setEmergencyScanRequestInProgress(boolean inProgress)11302 public void setEmergencyScanRequestInProgress(boolean inProgress) { 11303 try { 11304 mService.setEmergencyScanRequestInProgress(inProgress); 11305 } catch (RemoteException e) { 11306 throw e.rethrowFromSystemServer(); 11307 } 11308 } 11309 11310 /** 11311 * Enable or disable Wi-Fi scoring. Wi-Fi network status is evaluated by Wi-Fi scoring 11312 * {@link WifiScoreReport}. This API enables/disables Wi-Fi scoring to take action on network 11313 * selection. 11314 * 11315 * @param enabled {@code true} to enable, {@code false} to disable. 11316 * @return true The status of Wifi scoring is set successfully. 11317 * @hide 11318 */ 11319 @SystemApi 11320 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setWifiScoringEnabled(boolean enabled)11321 public boolean setWifiScoringEnabled(boolean enabled) { 11322 if (mVerboseLoggingEnabled) { 11323 Log.v(TAG, "setWifiScoringEnabled: " + enabled); 11324 } 11325 try { 11326 return mService.setWifiScoringEnabled(enabled); 11327 } catch (RemoteException e) { 11328 throw e.rethrowFromSystemServer(); 11329 } 11330 } 11331 11332 /** 11333 * Flush Passpoint ANQP cache, and clear pending ANQP requests. Allows the caller to reset the 11334 * Passpoint ANQP state, if required. 11335 * 11336 * Notes: 11337 * 1. Flushing the ANQP cache may cause delays in discovering and connecting to Passpoint 11338 * networks. 11339 * 2. Intended to be used by Device Owner (DO), Profile Owner (PO), Settings and provisioning 11340 * apps. 11341 */ 11342 @RequiresPermission(anyOf = { 11343 android.Manifest.permission.NETWORK_SETTINGS, 11344 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, 11345 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING 11346 }, conditional = true) flushPasspointAnqpCache()11347 public void flushPasspointAnqpCache() { 11348 try { 11349 mService.flushPasspointAnqpCache(mContext.getOpPackageName()); 11350 } catch (RemoteException e) { 11351 throw e.rethrowFromSystemServer(); 11352 } 11353 } 11354 11355 /** 11356 * Returns a list of {@link WifiAvailableChannel} for the specified band and operational 11357 * mode(s), that is allowed for the current regulatory domain. An empty list implies that there 11358 * are no available channels for use. 11359 * 11360 * Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*} 11361 * constant is limited to one of the band values specified below. Specifically, if the 5GHz 11362 * band is included then it must include the DFS channels - an exception will be thrown 11363 * otherwise. The caller should not make any assumptions about whether DFS channels are allowed. 11364 * This API will indicate whether DFS channels are allowed for the specified operation mode(s) 11365 * per device policy. 11366 * 11367 * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} 11368 * constants. 11369 * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED}=0 - no band specified; Looks for the 11370 * channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz 11371 * 2. {@code WifiScanner#WIFI_BAND_24_GHZ}=1 11372 * 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}=6 11373 * 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}=7 11374 * 5. {@code WifiScanner#WIFI_BAND_6_GHZ}=8 11375 * 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}=15 11376 * 7. {@code WifiScanner#WIFI_BAND_60_GHZ}=16 11377 * 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}=31 11378 * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants 11379 * e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE} 11380 * @return a list of {@link WifiAvailableChannel} 11381 * 11382 * @throws UnsupportedOperationException - if this API is not supported on this device 11383 * or IllegalArgumentException - if the band specified is not one among the list 11384 * of bands mentioned above. 11385 */ 11386 @RequiresApi(Build.VERSION_CODES.S) 11387 @NonNull 11388 @RequiresPermission(NEARBY_WIFI_DEVICES) getAllowedChannels( int band, @WifiAvailableChannel.OpMode int mode)11389 public List<WifiAvailableChannel> getAllowedChannels( 11390 int band, 11391 @WifiAvailableChannel.OpMode int mode) { 11392 if (!SdkLevel.isAtLeastS()) { 11393 throw new UnsupportedOperationException(); 11394 } 11395 try { 11396 Bundle extras = new Bundle(); 11397 if (SdkLevel.isAtLeastS()) { 11398 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 11399 mContext.getAttributionSource()); 11400 } 11401 return mService.getUsableChannels(band, mode, 11402 WifiAvailableChannel.FILTER_REGULATORY, mContext.getOpPackageName(), extras); 11403 } catch (RemoteException e) { 11404 throw e.rethrowFromSystemServer(); 11405 } 11406 } 11407 11408 /** 11409 * Returns a list of {@link WifiAvailableChannel} for the specified band and operational 11410 * mode(s) per the current regulatory domain and device-specific constraints such as concurrency 11411 * state and interference due to other radios. An empty list implies that there are no available 11412 * channels for use. 11413 * 11414 * Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*} 11415 * constant is limited to one of the band values specified below. Specifically, if the 5GHz 11416 * band is included then it must include the DFS channels - an exception will be thrown 11417 * otherwise. The caller should not make any assumptions about whether DFS channels are allowed. 11418 * This API will indicate whether DFS channels are allowed for the specified operation mode(s) 11419 * per device policy. 11420 * 11421 * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} 11422 * constants. 11423 * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED}=0 - no band specified; Looks for the 11424 * channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz 11425 * 2. {@code WifiScanner#WIFI_BAND_24_GHZ}=1 11426 * 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}=6 11427 * 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}=7 11428 * 5. {@code WifiScanner#WIFI_BAND_6_GHZ}=8 11429 * 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}=15 11430 * 7. {@code WifiScanner#WIFI_BAND_60_GHZ}=16 11431 * 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}=31 11432 * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants 11433 * e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE} 11434 * @return a list of {@link WifiAvailableChannel} 11435 * 11436 * @throws UnsupportedOperationException - if this API is not supported on this device 11437 * or IllegalArgumentException - if the band specified is not one among the list 11438 * of bands mentioned above. 11439 */ 11440 @RequiresApi(Build.VERSION_CODES.S) 11441 @NonNull 11442 @RequiresPermission(NEARBY_WIFI_DEVICES) getUsableChannels( int band, @WifiAvailableChannel.OpMode int mode)11443 public List<WifiAvailableChannel> getUsableChannels( 11444 int band, 11445 @WifiAvailableChannel.OpMode int mode) { 11446 if (!SdkLevel.isAtLeastS()) { 11447 throw new UnsupportedOperationException(); 11448 } 11449 try { 11450 Bundle extras = new Bundle(); 11451 if (SdkLevel.isAtLeastS()) { 11452 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 11453 mContext.getAttributionSource()); 11454 } 11455 return mService.getUsableChannels(band, mode, 11456 WifiAvailableChannel.getUsableFilter(), mContext.getOpPackageName(), extras); 11457 } catch (RemoteException e) { 11458 throw e.rethrowFromSystemServer(); 11459 } 11460 } 11461 11462 /** 11463 * If the device supports Wi-Fi Passpoint, the user can explicitly enable or disable it. 11464 * That status can be queried using this method. 11465 * @return {@code true} if Wi-Fi Passpoint is enabled 11466 * 11467 */ 11468 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) isWifiPasspointEnabled()11469 public boolean isWifiPasspointEnabled() { 11470 try { 11471 return mService.isWifiPasspointEnabled(); 11472 } catch (RemoteException e) { 11473 throw e.rethrowFromSystemServer(); 11474 } 11475 } 11476 11477 /** 11478 * Explicitly enable or disable Wi-Fi Passpoint as a global switch. 11479 * The global Passpoint enabling/disabling overrides individual configuration 11480 * enabling/disabling. 11481 * Passpoint global status can be queried by {@link WifiManager#isWifiPasspointEnabled }. 11482 * 11483 * @param enabled {@code true} to enable, {@code false} to disable. 11484 * @hide 11485 */ 11486 @SystemApi 11487 @RequiresPermission(anyOf = { 11488 android.Manifest.permission.NETWORK_SETTINGS, 11489 android.Manifest.permission.NETWORK_SETUP_WIZARD 11490 }) setWifiPasspointEnabled(boolean enabled)11491 public void setWifiPasspointEnabled(boolean enabled) { 11492 if (mVerboseLoggingEnabled) { 11493 Log.v(TAG, "setWifiPasspointEnabled: " + enabled); 11494 } 11495 try { 11496 mService.setWifiPasspointEnabled(enabled); 11497 } catch (RemoteException e) { 11498 throw e.rethrowFromSystemServer(); 11499 } 11500 } 11501 11502 /** 11503 * The device may support concurrent connections to multiple internet-providing Wi-Fi 11504 * networks (APs) - that is indicated by 11505 * {@link WifiManager#isStaConcurrencyForMultiInternetSupported()}. 11506 * This method indicates whether or not the feature is currently enabled. 11507 * A value of {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DISABLED} indicates that the feature 11508 * is disabled, a value of {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DBS_AP} or 11509 * {@link WifiManager#WIFI_MULTI_INTERNET_MODE_MULTI_AP} indicates that the feature is enabled. 11510 * 11511 * The app can register to receive the corresponding Wi-Fi networks using the 11512 * {@link ConnectivityManager#registerNetworkCallback(NetworkRequest, NetworkCallback)} API with 11513 * a {@link WifiNetworkSpecifier} configured using the 11514 * {@link WifiNetworkSpecifier.Builder#setBand(int)} method. 11515 */ 11516 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11517 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) getStaConcurrencyForMultiInternetMode()11518 public @WifiMultiInternetMode int getStaConcurrencyForMultiInternetMode() { 11519 try { 11520 return mService.getStaConcurrencyForMultiInternetMode(); 11521 } catch (RemoteException e) { 11522 throw e.rethrowFromSystemServer(); 11523 } 11524 } 11525 11526 /** 11527 * Check if the currently connected network meets the minimum required Wi-Fi security level set. 11528 * If not, the current network will be disconnected. 11529 * 11530 * @throws SecurityException if the caller does not have permission. 11531 * @hide 11532 */ 11533 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11534 @SystemApi 11535 @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) notifyMinimumRequiredWifiSecurityLevelChanged(int level)11536 public void notifyMinimumRequiredWifiSecurityLevelChanged(int level) { 11537 if (mVerboseLoggingEnabled) { 11538 Log.v(TAG, "notifyMinimumRequiredWifiSecurityLevelChanged"); 11539 } 11540 try { 11541 mService.notifyMinimumRequiredWifiSecurityLevelChanged(level); 11542 } catch (RemoteException e) { 11543 throw e.rethrowFromSystemServer(); 11544 } 11545 } 11546 11547 /** 11548 * Check if the currently connected network meets the Wi-Fi SSID policy set. 11549 * If not, the current network will be disconnected. 11550 * 11551 * @throws SecurityException if the caller does not have permission. 11552 * @hide 11553 */ 11554 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11555 @SystemApi 11556 @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) notifyWifiSsidPolicyChanged(@onNull WifiSsidPolicy policy)11557 public void notifyWifiSsidPolicyChanged(@NonNull WifiSsidPolicy policy) { 11558 if (mVerboseLoggingEnabled) { 11559 Log.v(TAG, "notifyWifiSsidPolicyChanged"); 11560 } 11561 try { 11562 if (policy != null) { 11563 mService.notifyWifiSsidPolicyChanged(policy.getPolicyType(), 11564 new ParceledListSlice<>(new ArrayList<>(policy.getSsids()))); 11565 } 11566 } catch (RemoteException e) { 11567 throw e.rethrowFromSystemServer(); 11568 } 11569 } 11570 11571 /** 11572 * Configure whether or not concurrent multiple connections to internet-providing Wi-Fi 11573 * networks (AP) is enabled. 11574 * Use {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DISABLED} to disable, and either 11575 * {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DBS_AP} or 11576 * {@link WifiManager#WIFI_MULTI_INTERNET_MODE_MULTI_AP} to enable in different modes. 11577 * The {@link WifiManager#getStaConcurrencyForMultiInternetMode() } can be used to retrieve 11578 * the current mode. 11579 * 11580 * @param mode Multi internet mode. 11581 * @return true when the mode is set successfully, false when failed. 11582 * @hide 11583 */ 11584 @SystemApi 11585 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11586 @RequiresPermission(anyOf = { 11587 android.Manifest.permission.NETWORK_SETTINGS, 11588 android.Manifest.permission.NETWORK_SETUP_WIZARD 11589 }) setStaConcurrencyForMultiInternetMode(@ifiMultiInternetMode int mode)11590 public boolean setStaConcurrencyForMultiInternetMode(@WifiMultiInternetMode int mode) { 11591 if (mVerboseLoggingEnabled) { 11592 Log.v(TAG, "setStaConcurrencyForMultiInternetMode: " + mode); 11593 } 11594 try { 11595 return mService.setStaConcurrencyForMultiInternetMode(mode); 11596 } catch (RemoteException e) { 11597 throw e.rethrowFromSystemServer(); 11598 } 11599 } 11600 11601 /** 11602 * Intent action to launch a dialog from the WifiDialog app. 11603 * Must include EXTRA_DIALOG_ID, EXTRA_DIALOG_TYPE, and appropriate extras for the dialog type. 11604 * @hide 11605 */ 11606 public static final String ACTION_LAUNCH_DIALOG = 11607 "android.net.wifi.action.LAUNCH_DIALOG"; 11608 11609 /** 11610 * Intent action to dismiss an existing dialog from the WifiDialog app. 11611 * Must include EXTRA_DIALOG_ID. 11612 * @hide 11613 */ 11614 public static final String ACTION_DISMISS_DIALOG = 11615 "android.net.wifi.action.DISMISS_DIALOG"; 11616 11617 /** 11618 * Unknown DialogType. 11619 * @hide 11620 */ 11621 public static final int DIALOG_TYPE_UNKNOWN = 0; 11622 11623 /** 11624 * DialogType for a simple dialog. 11625 * @see {@link com.android.server.wifi.WifiDialogManager#createSimpleDialog} 11626 * @hide 11627 */ 11628 public static final int DIALOG_TYPE_SIMPLE = 1; 11629 11630 /** 11631 * DialogType for a P2P Invitation Sent dialog. 11632 * @see {@link com.android.server.wifi.WifiDialogManager#createP2pInvitationSentDialog} 11633 * @hide 11634 */ 11635 public static final int DIALOG_TYPE_P2P_INVITATION_SENT = 2; 11636 11637 /** 11638 * DialogType for a P2P Invitation Received dialog. 11639 * @see {@link com.android.server.wifi.WifiDialogManager#createP2pInvitationReceivedDialog} 11640 * @hide 11641 */ 11642 public static final int DIALOG_TYPE_P2P_INVITATION_RECEIVED = 3; 11643 11644 /** @hide */ 11645 @IntDef(prefix = { "DIALOG_TYPE_" }, value = { 11646 DIALOG_TYPE_UNKNOWN, 11647 DIALOG_TYPE_SIMPLE, 11648 DIALOG_TYPE_P2P_INVITATION_SENT, 11649 DIALOG_TYPE_P2P_INVITATION_RECEIVED, 11650 }) 11651 @Retention(RetentionPolicy.SOURCE) 11652 public @interface DialogType {} 11653 11654 /** 11655 * Dialog positive button was clicked. 11656 * @hide 11657 */ 11658 public static final int DIALOG_REPLY_POSITIVE = 0; 11659 11660 /** 11661 * Dialog negative button was clicked. 11662 * @hide 11663 */ 11664 public static final int DIALOG_REPLY_NEGATIVE = 1; 11665 11666 /** 11667 * Dialog neutral button was clicked. 11668 * @hide 11669 */ 11670 public static final int DIALOG_REPLY_NEUTRAL = 2; 11671 11672 /** 11673 * Dialog was cancelled. 11674 * @hide 11675 */ 11676 public static final int DIALOG_REPLY_CANCELLED = 3; 11677 11678 /** 11679 * Indication of a reply to a dialog. 11680 * See {@link WifiManager#replyToSimpleDialog(int, int)} 11681 * @hide 11682 */ 11683 @IntDef(prefix = { "DIALOG_TYPE_" }, value = { 11684 DIALOG_REPLY_POSITIVE, 11685 DIALOG_REPLY_NEGATIVE, 11686 DIALOG_REPLY_NEUTRAL, 11687 DIALOG_REPLY_CANCELLED, 11688 }) 11689 @Retention(RetentionPolicy.SOURCE) 11690 public @interface DialogReply {} 11691 11692 /** 11693 * Invalid dialog id for dialogs that are not currently active. 11694 * @hide 11695 */ 11696 public static final int INVALID_DIALOG_ID = -1; 11697 11698 /** 11699 * Extra int indicating the type of dialog to display. 11700 * @hide 11701 */ 11702 public static final String EXTRA_DIALOG_TYPE = "android.net.wifi.extra.DIALOG_TYPE"; 11703 11704 /** 11705 * Extra int indicating the ID of a dialog. The value must not be {@link #INVALID_DIALOG_ID}. 11706 * @hide 11707 */ 11708 public static final String EXTRA_DIALOG_ID = "android.net.wifi.extra.DIALOG_ID"; 11709 11710 /** 11711 * Extra String indicating the title of a simple dialog. 11712 * @hide 11713 */ 11714 public static final String EXTRA_DIALOG_TITLE = "android.net.wifi.extra.DIALOG_TITLE"; 11715 11716 /** 11717 * Extra String indicating the message of a simple dialog. 11718 * @hide 11719 */ 11720 public static final String EXTRA_DIALOG_MESSAGE = "android.net.wifi.extra.DIALOG_MESSAGE"; 11721 11722 /** 11723 * Extra String indicating the message URL of a simple dialog. 11724 * @hide 11725 */ 11726 public static final String EXTRA_DIALOG_MESSAGE_URL = 11727 "android.net.wifi.extra.DIALOG_MESSAGE_URL"; 11728 11729 /** 11730 * Extra String indicating the start index of a message URL span of a simple dialog. 11731 * @hide 11732 */ 11733 public static final String EXTRA_DIALOG_MESSAGE_URL_START = 11734 "android.net.wifi.extra.DIALOG_MESSAGE_URL_START"; 11735 11736 /** 11737 * Extra String indicating the end index of a message URL span of a simple dialog. 11738 * @hide 11739 */ 11740 public static final String EXTRA_DIALOG_MESSAGE_URL_END = 11741 "android.net.wifi.extra.DIALOG_MESSAGE_URL_END"; 11742 11743 /** 11744 * Extra String indicating the positive button text of a simple dialog. 11745 * @hide 11746 */ 11747 public static final String EXTRA_DIALOG_POSITIVE_BUTTON_TEXT = 11748 "android.net.wifi.extra.DIALOG_POSITIVE_BUTTON_TEXT"; 11749 11750 /** 11751 * Extra String indicating the negative button text of a simple dialog. 11752 * @hide 11753 */ 11754 public static final String EXTRA_DIALOG_NEGATIVE_BUTTON_TEXT = 11755 "android.net.wifi.extra.DIALOG_NEGATIVE_BUTTON_TEXT"; 11756 11757 /** 11758 * Extra String indicating the neutral button text of a simple dialog. 11759 * @hide 11760 */ 11761 public static final String EXTRA_DIALOG_NEUTRAL_BUTTON_TEXT = 11762 "android.net.wifi.extra.DIALOG_NEUTRAL_BUTTON_TEXT"; 11763 11764 /** 11765 * Extra long indicating the timeout in milliseconds of a dialog. 11766 * @hide 11767 */ 11768 public static final String EXTRA_DIALOG_TIMEOUT_MS = "android.net.wifi.extra.DIALOG_TIMEOUT_MS"; 11769 11770 /** 11771 * Extra String indicating a P2P device name for a P2P Invitation Sent/Received dialog. 11772 * @hide 11773 */ 11774 public static final String EXTRA_P2P_DEVICE_NAME = "android.net.wifi.extra.P2P_DEVICE_NAME"; 11775 11776 /** 11777 * Extra boolean indicating that a PIN is requested for a P2P Invitation Received dialog. 11778 * @hide 11779 */ 11780 public static final String EXTRA_P2P_PIN_REQUESTED = "android.net.wifi.extra.P2P_PIN_REQUESTED"; 11781 11782 /** 11783 * Extra String indicating the PIN to be displayed for a P2P Invitation Sent/Received dialog. 11784 * @hide 11785 */ 11786 public static final String EXTRA_P2P_DISPLAY_PIN = "android.net.wifi.extra.P2P_DISPLAY_PIN"; 11787 11788 /** 11789 * Extra boolean indicating ACTION_CLOSE_SYSTEM_DIALOGS should not close the Wi-Fi dialogs. 11790 * @hide 11791 */ 11792 public static final String EXTRA_CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI = 11793 "android.net.wifi.extra.CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI"; 11794 11795 /** 11796 * Returns a set of packages that aren't DO or PO but should be able to manage WiFi networks. 11797 * @hide 11798 */ 11799 @SystemApi 11800 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) 11801 @NonNull getOemPrivilegedWifiAdminPackages()11802 public Set<String> getOemPrivilegedWifiAdminPackages() { 11803 try { 11804 return new ArraySet<>(mService.getOemPrivilegedWifiAdminPackages()); 11805 } catch (RemoteException e) { 11806 throw e.rethrowFromSystemServer(); 11807 } 11808 } 11809 11810 /** 11811 * Method for WifiDialog to notify the framework of a reply to a simple dialog. 11812 * @param dialogId id of the replying dialog. 11813 * @param reply reply of the dialog. 11814 * @hide 11815 */ replyToSimpleDialog(int dialogId, @DialogReply int reply)11816 public void replyToSimpleDialog(int dialogId, @DialogReply int reply) { 11817 if (mVerboseLoggingEnabled) { 11818 Log.v(TAG, "replyToWifiEnableRequestDialog: dialogId=" + dialogId 11819 + " reply=" + reply); 11820 } 11821 try { 11822 mService.replyToSimpleDialog(dialogId, reply); 11823 } catch (RemoteException e) { 11824 throw e.rethrowFromSystemServer(); 11825 } 11826 } 11827 11828 /** 11829 * Method for WifiDialog to notify the framework of a reply to a P2P Invitation Received dialog. 11830 * @param dialogId id of the replying dialog. 11831 * @param accepted Whether the invitation was accepted. 11832 * @param optionalPin PIN of the reply, or {@code null} if none was supplied. 11833 * @hide 11834 */ replyToP2pInvitationReceivedDialog( int dialogId, boolean accepted, @Nullable String optionalPin)11835 public void replyToP2pInvitationReceivedDialog( 11836 int dialogId, boolean accepted, @Nullable String optionalPin) { 11837 if (mVerboseLoggingEnabled) { 11838 Log.v(TAG, "replyToP2pInvitationReceivedDialog: " 11839 + "dialogId=" + dialogId 11840 + ", accepted=" + accepted 11841 + ", pin=" + optionalPin); 11842 } 11843 try { 11844 mService.replyToP2pInvitationReceivedDialog(dialogId, accepted, optionalPin); 11845 } catch (RemoteException e) { 11846 throw e.rethrowFromSystemServer(); 11847 } 11848 } 11849 11850 /** 11851 * Specify a list of DHCP options to use for any network whose SSID is specified and which 11852 * transmits vendor-specific information elements (VSIEs) using the specified Organizationally 11853 * Unique Identifier (OUI). If the AP transmits VSIEs for multiple specified OUIs then all 11854 * matching DHCP options will be used. The allowlist for DHCP options in 11855 * {@link android.net.ip.IpClient} gates whether the DHCP options will actually be used. 11856 * When DHCP options are used: if the option value {@link android.net.DhcpOption#getValue()} 11857 * is null, the option type {@link android.net.DhcpOption#getType()} will be put in the 11858 * Parameter Request List in the DHCP packets; otherwise, the option will be included in the 11859 * options section in the DHCP packets. Use {@link #removeCustomDhcpOptions(Object, Object)} 11860 * to remove the specified DHCP options. 11861 * 11862 * @param ssid the network SSID. 11863 * @param oui the 3-byte OUI. 11864 * @param options the list of {@link android.net.DhcpOption}. 11865 * 11866 * @hide 11867 */ 11868 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 11869 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11870 @RequiresPermission(anyOf = { 11871 android.Manifest.permission.NETWORK_SETTINGS, 11872 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 11873 }) addCustomDhcpOptions(@onNull WifiSsid ssid, @NonNull byte[] oui, @NonNull List<DhcpOption> options)11874 public void addCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui, 11875 @NonNull List<DhcpOption> options) { 11876 try { 11877 mService.addCustomDhcpOptions(ssid, oui, new ParceledListSlice<>(options)); 11878 } catch (RemoteException e) { 11879 throw e.rethrowFromSystemServer(); 11880 } 11881 } 11882 11883 /** 11884 * Remove custom DHCP options specified by {@link #addCustomDhcpOptions(Object, Object, List)}. 11885 * 11886 * @param ssid the network SSID. 11887 * @param oui the 3-byte OUI. 11888 * 11889 * @hide 11890 */ 11891 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 11892 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11893 @RequiresPermission(anyOf = { 11894 android.Manifest.permission.NETWORK_SETTINGS, 11895 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 11896 }) removeCustomDhcpOptions(@onNull WifiSsid ssid, @NonNull byte[] oui)11897 public void removeCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui) { 11898 try { 11899 mService.removeCustomDhcpOptions(ssid, oui); 11900 } catch (RemoteException e) { 11901 throw e.rethrowFromSystemServer(); 11902 } 11903 } 11904 11905 /** 11906 * Wi-Fi interface of type STA (station/client Wi-Fi infrastructure device). 11907 */ 11908 public static final int WIFI_INTERFACE_TYPE_STA = 0; 11909 11910 /** 11911 * Wi-Fi interface of type AP (access point Wi-Fi infrastructure device). 11912 */ 11913 public static final int WIFI_INTERFACE_TYPE_AP = 1; 11914 11915 /** 11916 * Wi-Fi interface of type Wi-Fi Aware (aka NAN). 11917 */ 11918 public static final int WIFI_INTERFACE_TYPE_AWARE = 2; 11919 11920 /** 11921 * Wi-Fi interface of type Wi-Fi Direct (aka P2P). 11922 */ 11923 public static final int WIFI_INTERFACE_TYPE_DIRECT = 3; 11924 11925 /** @hide */ 11926 @IntDef(prefix = { "WIFI_INTERFACE_TYPE_" }, value = { 11927 WIFI_INTERFACE_TYPE_STA, 11928 WIFI_INTERFACE_TYPE_AP, 11929 WIFI_INTERFACE_TYPE_AWARE, 11930 WIFI_INTERFACE_TYPE_DIRECT, 11931 }) 11932 @Retention(RetentionPolicy.SOURCE) 11933 public @interface WifiInterfaceType {} 11934 11935 /** 11936 * Class describing an impact of interface creation - returned by 11937 * {@link #reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}. Due to Wi-Fi 11938 * concurrency limitations certain interfaces may have to be torn down. Each of these 11939 * interfaces was requested by a set of applications who could potentially be impacted. 11940 * 11941 * This class contain the information for a single interface: the interface type with 11942 * {@link InterfaceCreationImpact#getInterfaceType()} and the set of impacted packages 11943 * with {@link InterfaceCreationImpact#getPackages()}. 11944 */ 11945 public static class InterfaceCreationImpact { 11946 private final int mInterfaceType; 11947 private final Set<String> mPackages; 11948 InterfaceCreationImpact(@ifiInterfaceType int interfaceType, @NonNull Set<String> packages)11949 public InterfaceCreationImpact(@WifiInterfaceType int interfaceType, 11950 @NonNull Set<String> packages) { 11951 mInterfaceType = interfaceType; 11952 mPackages = packages; 11953 } 11954 11955 /** 11956 * @return The interface type which will be torn down to make room for the interface 11957 * requested in {@link #reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}. 11958 */ getInterfaceType()11959 public @WifiInterfaceType int getInterfaceType() { 11960 return mInterfaceType; 11961 } 11962 11963 /** 11964 * @return The list of potentially impacted packages due to tearing down the interface 11965 * specified in {@link #getInterfaceType()}. 11966 */ getPackages()11967 public @NonNull Set<String> getPackages() { 11968 return mPackages; 11969 } 11970 11971 @Override hashCode()11972 public int hashCode() { 11973 return Objects.hash(mInterfaceType, mPackages); 11974 } 11975 11976 @Override equals(Object that)11977 public boolean equals(Object that) { 11978 if (this == that) return true; 11979 if (!(that instanceof InterfaceCreationImpact)) return false; 11980 InterfaceCreationImpact thatInterfaceCreationImpact = (InterfaceCreationImpact) that; 11981 11982 return this.mInterfaceType == thatInterfaceCreationImpact.mInterfaceType 11983 && Objects.equals(this.mPackages, thatInterfaceCreationImpact.mPackages); 11984 } 11985 } 11986 11987 /** 11988 * Queries the framework to determine whether the specified interface can be created, and if 11989 * so - what other interfaces would be torn down by the framework to allow this creation if 11990 * it were requested. The result is returned via the specified {@link BiConsumer} callback 11991 * which returns two arguments: 11992 * <li>First argument: a {@code boolean} - indicating whether or not the interface can be 11993 * created.</li> 11994 * <li>Second argument: a {@code Set<InterfaceCreationImpact>} - if the interface can be 11995 * created (first argument is {@code true} then this is the set of interface types which 11996 * will be removed and the packages which requested them. Possibly an empty set. If the 11997 * first argument is {@code false}, then an empty set will be returned here.</li> 11998 * <p> 11999 * Interfaces, input and output, are specified using the {@code WIFI_INTERFACE_*} constants: 12000 * {@link #WIFI_INTERFACE_TYPE_STA}, {@link #WIFI_INTERFACE_TYPE_AP}, 12001 * {@link #WIFI_INTERFACE_TYPE_AWARE}, or {@link #WIFI_INTERFACE_TYPE_DIRECT}. 12002 * <p> 12003 * This method does not actually create the interface. That operation is handled by the 12004 * framework when a particular service method is called. E.g. a Wi-Fi Direct interface may be 12005 * created when various methods of {@link android.net.wifi.p2p.WifiP2pManager} are called, 12006 * similarly for Wi-Fi Aware and {@link android.net.wifi.aware.WifiAwareManager}. 12007 * <p> 12008 * Note: the information returned via this method is the current snapshot of the system. It may 12009 * change due to actions of the framework or other apps. 12010 * 12011 * @param interfaceType The interface type whose possible creation is being queried. 12012 * @param requireNewInterface Indicates that the query is for a new interface of the specified 12013 * type - an existing interface won't meet the query. Some 12014 * operations (such as Wi-Fi Direct and Wi-Fi Aware are a shared 12015 * resource and so may not need a new interface). 12016 * @param executor An {@link Executor} on which to return the result. 12017 * @param resultCallback The asynchronous callback which will return two argument: a 12018 * {@code boolean} (whether the interface can be created), and a 12019 * {@code Set<InterfaceCreationImpact>} (a set of {@link InterfaceCreationImpact}: 12020 * interfaces which will be destroyed when the interface is created 12021 * and the packages which requested them and thus may be impacted). 12022 */ 12023 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 12024 @RequiresPermission(allOf = {android.Manifest.permission.MANAGE_WIFI_INTERFACES, 12025 ACCESS_WIFI_STATE}) reportCreateInterfaceImpact(@ifiInterfaceType int interfaceType, boolean requireNewInterface, @NonNull @CallbackExecutor Executor executor, @NonNull BiConsumer<Boolean, Set<InterfaceCreationImpact>> resultCallback)12026 public void reportCreateInterfaceImpact(@WifiInterfaceType int interfaceType, 12027 boolean requireNewInterface, 12028 @NonNull @CallbackExecutor Executor executor, 12029 @NonNull BiConsumer<Boolean, Set<InterfaceCreationImpact>> resultCallback) { 12030 Objects.requireNonNull(executor, "Non-null executor required"); 12031 Objects.requireNonNull(resultCallback, "Non-null resultCallback required"); 12032 try { 12033 mService.reportCreateInterfaceImpact(mContext.getOpPackageName(), interfaceType, 12034 requireNewInterface, new IInterfaceCreationInfoCallback.Stub() { 12035 @Override 12036 public void onResults(boolean canCreate, int[] interfacesToDelete, 12037 String[] packagesForInterfaces) { 12038 Binder.clearCallingIdentity(); 12039 if ((interfacesToDelete == null && packagesForInterfaces != null) 12040 || (interfacesToDelete != null 12041 && packagesForInterfaces == null) || (canCreate && ( 12042 interfacesToDelete == null || interfacesToDelete.length 12043 != packagesForInterfaces.length))) { 12044 Log.e(TAG, 12045 "reportImpactToCreateIfaceRequest: Invalid callback " 12046 + "parameters - canCreate=" 12047 + canCreate + ", interfacesToDelete=" 12048 + Arrays.toString(interfacesToDelete) 12049 + ", worksourcesForInterfaces=" 12050 + Arrays.toString(packagesForInterfaces)); 12051 return; 12052 } 12053 12054 final Set<InterfaceCreationImpact> finalSet = 12055 (canCreate && interfacesToDelete.length > 0) ? new ArraySet<>() 12056 : Collections.emptySet(); 12057 if (canCreate) { 12058 for (int i = 0; i < interfacesToDelete.length; ++i) { 12059 finalSet.add( 12060 new InterfaceCreationImpact(interfacesToDelete[i], 12061 packagesForInterfaces[i] == null 12062 ? Collections.emptySet() 12063 : new ArraySet<>( 12064 packagesForInterfaces[i] 12065 .split(",")))); 12066 } 12067 } 12068 executor.execute(() -> resultCallback.accept(canCreate, finalSet)); 12069 } 12070 }); 12071 } catch (RemoteException e) { 12072 throw e.rethrowFromSystemServer(); 12073 } 12074 } 12075 12076 /** 12077 * Returns the max number of channels that is allowed to be set on a 12078 * {@link WifiNetworkSpecifier}. 12079 * @see WifiNetworkSpecifier.Builder#setPreferredChannelsFrequenciesMhz(int[]) 12080 * 12081 * @return The max number of channels can be set on a request. 12082 */ 12083 getMaxNumberOfChannelsPerNetworkSpecifierRequest()12084 public int getMaxNumberOfChannelsPerNetworkSpecifierRequest() { 12085 try { 12086 return mService.getMaxNumberOfChannelsPerRequest(); 12087 } catch (RemoteException e) { 12088 throw e.rethrowFromSystemServer(); 12089 } 12090 } 12091 12092 /** 12093 * Add a list of new application-initiated QoS policies. 12094 * 12095 * Note: Policies are managed using a policy ID, which can be retrieved using 12096 * {@link QosPolicyParams#getPolicyId()}. This ID can be used when removing a policy via 12097 * {@link #removeQosPolicies(int[])}. The caller is in charge of assigning and managing 12098 * the policy IDs for any requested policies. 12099 * 12100 * Note: Policies with duplicate IDs are not allowed. To update an existing policy, first 12101 * remove it using {@link #removeQosPolicies(int[])}, and then re-add it using this API. 12102 * 12103 * Note: All policies in a single request must have the same {@link QosPolicyParams.Direction}. 12104 * 12105 * Note: Support for the {@link QosPolicyParams#DIRECTION_UPLINK} direction is added in 12106 * {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}. For earlier releases, 12107 * only the {@link QosPolicyParams#DIRECTION_DOWNLINK} direction is supported. 12108 * 12109 * @param policyParamsList List of {@link QosPolicyParams} objects describing the requested 12110 * policies. Must have a maximum length of 12111 * {@link #getMaxNumberOfPoliciesPerQosRequest()}. 12112 * @param executor The executor on which callback will be invoked. 12113 * @param resultsCallback An asynchronous callback that will return a list of integer status 12114 * codes from {@link QosRequestStatus}. Result list will be the same 12115 * length as the input list, and each status code will correspond to 12116 * the policy at that index in the input list. 12117 * 12118 * @throws SecurityException if caller does not have the required permissions. 12119 * @throws NullPointerException if the caller provided a null input. 12120 * @throws UnsupportedOperationException if the feature is not enabled. 12121 * @throws IllegalArgumentException if the input list is invalid. 12122 * @hide 12123 */ 12124 @SystemApi 12125 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12126 @RequiresPermission(anyOf = { 12127 android.Manifest.permission.NETWORK_SETTINGS, 12128 MANAGE_WIFI_NETWORK_SELECTION 12129 }) addQosPolicies(@onNull List<QosPolicyParams> policyParamsList, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<List<Integer>> resultsCallback)12130 public void addQosPolicies(@NonNull List<QosPolicyParams> policyParamsList, 12131 @NonNull @CallbackExecutor Executor executor, 12132 @NonNull Consumer<List<Integer>> resultsCallback) { 12133 Objects.requireNonNull(policyParamsList, "policyParamsList cannot be null"); 12134 Objects.requireNonNull(executor, "executor cannot be null"); 12135 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12136 try { 12137 mService.addQosPolicies(new ParceledListSlice<>(policyParamsList), 12138 new Binder(), mContext.getOpPackageName(), 12139 new IListListener.Stub() { 12140 @Override 12141 public void onResult(List value) { 12142 Binder.clearCallingIdentity(); 12143 executor.execute(() -> { 12144 resultsCallback.accept(value); 12145 }); 12146 } 12147 }); 12148 } catch (RemoteException e) { 12149 throw e.rethrowFromSystemServer(); 12150 } 12151 } 12152 12153 /** 12154 * Remove a list of existing application-initiated QoS policies, previously added via 12155 * {@link #addQosPolicies(List, Executor, Consumer)}. 12156 * 12157 * Note: Policies are identified by their policy IDs, which are assigned by the caller. The ID 12158 * for a given policy can be retrieved using {@link QosPolicyParams#getPolicyId()}. 12159 * 12160 * @param policyIdList List of policy IDs corresponding to the policies to remove. Must have 12161 * a maximum length of {@link #getMaxNumberOfPoliciesPerQosRequest()}. 12162 * @throws SecurityException if caller does not have the required permissions. 12163 * @throws NullPointerException if the caller provided a null input. 12164 * @throws IllegalArgumentException if the input list is invalid. 12165 * @hide 12166 */ 12167 @SystemApi 12168 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12169 @RequiresPermission(anyOf = { 12170 android.Manifest.permission.NETWORK_SETTINGS, 12171 MANAGE_WIFI_NETWORK_SELECTION 12172 }) removeQosPolicies(@onNull int[] policyIdList)12173 public void removeQosPolicies(@NonNull int[] policyIdList) { 12174 Objects.requireNonNull(policyIdList, "policyIdList cannot be null"); 12175 try { 12176 mService.removeQosPolicies(policyIdList, mContext.getOpPackageName()); 12177 } catch (RemoteException e) { 12178 throw e.rethrowFromSystemServer(); 12179 } 12180 } 12181 12182 /** 12183 * Remove all application-initiated QoS policies requested by this caller, 12184 * previously added via {@link #addQosPolicies(List, Executor, Consumer)}. 12185 * 12186 * @throws SecurityException if caller does not have the required permissions. 12187 * @hide 12188 */ 12189 @SystemApi 12190 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12191 @RequiresPermission(anyOf = { 12192 android.Manifest.permission.NETWORK_SETTINGS, 12193 MANAGE_WIFI_NETWORK_SELECTION 12194 }) removeAllQosPolicies()12195 public void removeAllQosPolicies() { 12196 try { 12197 mService.removeAllQosPolicies(mContext.getOpPackageName()); 12198 } catch (RemoteException e) { 12199 throw e.rethrowFromSystemServer(); 12200 } 12201 } 12202 12203 /** 12204 * Set the link layer stats polling interval, in milliseconds. 12205 * 12206 * @param intervalMs a non-negative integer, for the link layer stats polling interval 12207 * in milliseconds. 12208 * To set a fixed interval, use a positive value. 12209 * For automatic handling of the interval, use value 0 12210 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 12211 * @throws SecurityException if the caller does not have permission. 12212 * @throws IllegalArgumentException if input is invalid. 12213 * @hide 12214 */ 12215 @SystemApi 12216 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 12217 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) setLinkLayerStatsPollingInterval(@ntRange from = 0) int intervalMs)12218 public void setLinkLayerStatsPollingInterval(@IntRange (from = 0) int intervalMs) { 12219 try { 12220 mService.setLinkLayerStatsPollingInterval(intervalMs); 12221 } catch (RemoteException e) { 12222 throw e.rethrowFromSystemServer(); 12223 } 12224 } 12225 12226 /** 12227 * Get the link layer stats polling interval, in milliseconds. 12228 * 12229 * @param executor The executor on which callback will be invoked. 12230 * @param resultsCallback An asynchronous callback that will return current 12231 * link layer stats polling interval in milliseconds. 12232 * 12233 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 12234 * @throws SecurityException if the caller does not have permission. 12235 * @throws NullPointerException if the caller provided invalid inputs. 12236 * @hide 12237 */ 12238 @SystemApi 12239 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 12240 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) getLinkLayerStatsPollingInterval(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)12241 public void getLinkLayerStatsPollingInterval(@NonNull @CallbackExecutor Executor executor, 12242 @NonNull Consumer<Integer> resultsCallback) { 12243 Objects.requireNonNull(executor, "executor cannot be null"); 12244 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12245 try { 12246 mService.getLinkLayerStatsPollingInterval( 12247 new IIntegerListener.Stub() { 12248 @Override 12249 public void onResult(int value) { 12250 Binder.clearCallingIdentity(); 12251 executor.execute(() -> { 12252 resultsCallback.accept(value); 12253 }); 12254 } 12255 }); 12256 } catch (RemoteException e) { 12257 throw e.rethrowFromSystemServer(); 12258 } 12259 } 12260 12261 /** 12262 * This API allows a privileged application to set Multi-Link Operation mode. 12263 * 12264 * Multi-link operation (MLO) will allow Wi-Fi devices to operate on multiple links at the same 12265 * time through a single connection, aiming to support applications that require lower latency, 12266 * and higher capacity. Chip vendors have algorithms that run on the chip to use available links 12267 * based on incoming traffic and various inputs. This API allows system application to give a 12268 * suggestion to such algorithms on its preference using {@link MloMode}. 12269 * 12270 * 12271 * @param mode Refer {@link MloMode} for supported modes. 12272 * @param executor The executor on which callback will be invoked. 12273 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 12274 * whether the MLO mode is successfully set or not. 12275 * @throws IllegalArgumentException if mode value is not in {@link MloMode}. 12276 * @throws NullPointerException if the caller provided a null input. 12277 * @throws SecurityException if caller does not have the required permissions. 12278 * @throws UnsupportedOperationException if the set operation is not supported on this SDK. 12279 * @hide 12280 */ 12281 @SystemApi 12282 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12283 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) setMloMode(@loMode int mode, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)12284 public void setMloMode(@MloMode int mode, @NonNull @CallbackExecutor Executor executor, 12285 @NonNull Consumer<Boolean> resultsCallback) { 12286 12287 if (mode < MLO_MODE_DEFAULT || mode > MLO_MODE_LOW_POWER) { 12288 throw new IllegalArgumentException("invalid mode: " + mode); 12289 } 12290 Objects.requireNonNull(executor, "executor cannot be null"); 12291 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12292 try { 12293 mService.setMloMode(mode, new IBooleanListener.Stub() { 12294 @Override 12295 public void onResult(boolean value) { 12296 Binder.clearCallingIdentity(); 12297 executor.execute(() -> { 12298 resultsCallback.accept(value); 12299 }); 12300 } 12301 }); 12302 } catch (RemoteException e) { 12303 throw e.rethrowFromSystemServer(); 12304 } 12305 } 12306 12307 /** 12308 * This API allows a privileged application to get Multi-Link Operation mode. Refer 12309 * {@link WifiManager#setMloMode(int, Executor, Consumer)} for more details. 12310 * 12311 * @param executor The executor on which callback will be invoked. 12312 * @param resultsCallback An asynchronous callback that will return current MLO mode. Returns 12313 * {@link MloMode#MLO_MODE_DEFAULT} if information is not available, 12314 * e.g. if the driver/firmware doesn't provide this information. 12315 * @throws NullPointerException if the caller provided a null input. 12316 * @throws SecurityException if caller does not have the required permissions. 12317 * @throws UnsupportedOperationException if the get operation is not supported on this SDK. 12318 * @hide 12319 */ 12320 @SystemApi 12321 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12322 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getMloMode(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)12323 public void getMloMode(@NonNull @CallbackExecutor Executor executor, 12324 @NonNull Consumer<Integer> resultsCallback) { 12325 Objects.requireNonNull(executor, "executor cannot be null"); 12326 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12327 try { 12328 mService.getMloMode(new IIntegerListener.Stub() { 12329 @Override 12330 public void onResult(int value) { 12331 Binder.clearCallingIdentity(); 12332 executor.execute(() -> { 12333 resultsCallback.accept(value); 12334 }); 12335 } 12336 }); 12337 } catch (RemoteException e) { 12338 throw e.rethrowFromSystemServer(); 12339 } 12340 } 12341 12342 /** 12343 * Get the maximum number of links supported by the chip for MLO association. e.g. if the Wi-Fi 12344 * chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous Transmit and 12345 * Receive) with following capabilities, 12346 * - Max MLO assoc link count = 3. 12347 * - Max MLO STR link count = 2. See 12348 * {@link WifiManager#getMaxMloStrLinkCount(Executor, Consumer)} 12349 * One of the possible configuration is - STR (2.4 GHz , eMLSR(5 GHz, 6 GHz)), provided the 12350 * radio combination of the chip supports it. 12351 * 12352 * @param executor The executor on which callback will be invoked. 12353 * @param resultsCallback An asynchronous callback that will return maximum MLO association link 12354 * count supported by the chip or -1 if error or not available. 12355 * @throws NullPointerException if the caller provided a null input. 12356 * @throws SecurityException if caller does not have the required permissions. 12357 * @throws UnsupportedOperationException if the get operation is not supported on this SDK. 12358 * @hide 12359 */ 12360 @SystemApi 12361 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12362 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12363 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getMaxMloAssociationLinkCount(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)12364 public void getMaxMloAssociationLinkCount(@NonNull @CallbackExecutor Executor executor, 12365 @NonNull Consumer<Integer> resultsCallback) { 12366 Objects.requireNonNull(executor, "executor cannot be null"); 12367 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12368 try { 12369 Bundle extras = new Bundle(); 12370 if (SdkLevel.isAtLeastS()) { 12371 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12372 mContext.getAttributionSource()); 12373 } 12374 mService.getMaxMloAssociationLinkCount(new IIntegerListener.Stub() { 12375 @Override 12376 public void onResult(int value) { 12377 Binder.clearCallingIdentity(); 12378 executor.execute(() -> { 12379 resultsCallback.accept(value); 12380 }); 12381 } 12382 }, extras); 12383 } catch (RemoteException e) { 12384 throw e.rethrowFromSystemServer(); 12385 } 12386 } 12387 12388 /** 12389 * Get the maximum number of STR links used in Multi-Link Operation. The maximum number of STR 12390 * links used for MLO can be different from the number of radios supported by the chip. e.g. if 12391 * the Wi-Fi chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous 12392 * Transmit and Receive) with following capabilities, 12393 * - Max MLO assoc link count = 3. See 12394 * {@link WifiManager#getMaxMloAssociationLinkCount(Executor, Consumer)}. 12395 * - Max MLO STR link count = 2. 12396 * One of the possible configuration is - STR (2.4 GHz, eMLSR(5 GHz, 6 GHz)), provided the radio 12397 * combination of the chip supports it. 12398 * 12399 * @param executor The executor on which callback will be invoked. 12400 * @param resultsCallback An asynchronous callback that will return maximum STR link count 12401 * supported by the chip in MLO mode or -1 if error or not available. 12402 * @throws NullPointerException if the caller provided a null input. 12403 * @throws SecurityException if caller does not have the required permissions. 12404 * @throws UnsupportedOperationException if the get operation is not supported on this SDK 12405 * @hide 12406 */ 12407 @SystemApi 12408 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12409 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12410 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getMaxMloStrLinkCount(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)12411 public void getMaxMloStrLinkCount(@NonNull @CallbackExecutor Executor executor, 12412 @NonNull Consumer<Integer> resultsCallback) { 12413 Objects.requireNonNull(executor, "executor cannot be null"); 12414 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12415 try { 12416 Bundle extras = new Bundle(); 12417 if (SdkLevel.isAtLeastS()) { 12418 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12419 mContext.getAttributionSource()); 12420 } 12421 mService.getMaxMloStrLinkCount(new IIntegerListener.Stub() { 12422 @Override 12423 public void onResult(int value) { 12424 Binder.clearCallingIdentity(); 12425 executor.execute(() -> { 12426 resultsCallback.accept(value); 12427 }); 12428 } 12429 }, extras); 12430 } catch (RemoteException e) { 12431 throw e.rethrowFromSystemServer(); 12432 } 12433 } 12434 12435 /** 12436 * Get the set of band combinations supported simultaneously by the Wi-Fi Chip. 12437 * 12438 * Note: This method returns simultaneous band operation combination and not multichannel 12439 * concurrent operation (MCC) combination. 12440 * 12441 * @param executor The executor on which callback will be invoked. 12442 * @param resultsCallback An asynchronous callback that will return a list of possible 12443 * simultaneous band combinations supported by the chip or empty list if 12444 * not available. Band value is defined in {@link WifiScanner.WifiBand}. 12445 * @throws NullPointerException if the caller provided a null input. 12446 * @throws SecurityException if caller does not have the required permissions. 12447 * @throws UnsupportedOperationException if the get operation is not supported on this SDK. 12448 * @hide 12449 */ 12450 @SystemApi 12451 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12452 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 12453 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getSupportedSimultaneousBandCombinations( @onNull @allbackExecutor Executor executor, @NonNull Consumer<List<int[]>> resultsCallback)12454 public void getSupportedSimultaneousBandCombinations( 12455 @NonNull @CallbackExecutor Executor executor, 12456 @NonNull Consumer<List<int[]>> resultsCallback) { 12457 Objects.requireNonNull(executor, "executor cannot be null"); 12458 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12459 try { 12460 Bundle extras = new Bundle(); 12461 if (SdkLevel.isAtLeastS()) { 12462 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12463 mContext.getAttributionSource()); 12464 } 12465 mService.getSupportedSimultaneousBandCombinations(new IWifiBandsListener.Stub() { 12466 @Override 12467 public void onResult(WifiBands[] supportedBands) { 12468 Binder.clearCallingIdentity(); 12469 List<int[]> bandCombinations = new ArrayList<>(); 12470 for (WifiBands wifiBands : supportedBands) { 12471 bandCombinations.add(wifiBands.bands); 12472 } 12473 executor.execute(() -> { 12474 resultsCallback.accept(bandCombinations); 12475 }); 12476 } 12477 }, extras); 12478 } catch (RemoteException e) { 12479 throw e.rethrowFromSystemServer(); 12480 } 12481 } 12482 12483 /** 12484 * This API allows a privileged application to set whether or not this device allows 12485 * connections to Wi-Fi WEP networks. 12486 * 12487 * Note: The WEP connections may not work even if caller invokes this method with {@code true} 12488 * because device may NOT support connections to Wi-Fi WEP networks. 12489 * See: {@link #isWepSupported()}. 12490 * 12491 * @param isAllowed whether or not the user allow connections to Wi-Fi WEP networks. 12492 * @throws SecurityException if the caller does not have permission. 12493 * @hide 12494 */ 12495 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12496 @SystemApi 12497 @RequiresPermission(anyOf = { 12498 android.Manifest.permission.NETWORK_SETTINGS, 12499 android.Manifest.permission.NETWORK_SETUP_WIZARD 12500 }) setWepAllowed(boolean isAllowed)12501 public void setWepAllowed(boolean isAllowed) { 12502 try { 12503 mService.setWepAllowed(isAllowed); 12504 } catch (RemoteException e) { 12505 throw e.rethrowFromSystemServer(); 12506 } 12507 } 12508 12509 /** 12510 * Query whether or not this device is configured to allow connections to Wi-Fi WEP networks. 12511 * @see #setWepAllowed(boolean) 12512 * 12513 * Note: The WEP connections may not work even if this method returns {@code true} in the 12514 * result callback because device may NOT support connections to Wi-Fi WEP networks. 12515 * See: {@link #isWepSupported()}. 12516 * 12517 * @param executor The executor on which callback will be invoked. 12518 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 12519 * whether wep network support is enabled/disabled. 12520 * 12521 * @throws SecurityException if the caller does not have permission. 12522 * @hide 12523 */ 12524 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12525 @SystemApi 12526 @RequiresPermission(anyOf = { 12527 android.Manifest.permission.NETWORK_SETTINGS, 12528 android.Manifest.permission.NETWORK_SETUP_WIZARD 12529 }) queryWepAllowed(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)12530 public void queryWepAllowed(@NonNull @CallbackExecutor Executor executor, 12531 @NonNull Consumer<Boolean> resultsCallback) { 12532 Objects.requireNonNull(executor, "executor cannot be null"); 12533 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12534 try { 12535 mService.queryWepAllowed( 12536 new IBooleanListener.Stub() { 12537 @Override 12538 public void onResult(boolean value) { 12539 Binder.clearCallingIdentity(); 12540 executor.execute(() -> { 12541 resultsCallback.accept(value); 12542 }); 12543 } 12544 }); 12545 } catch (RemoteException e) { 12546 throw e.rethrowFromSystemServer(); 12547 } 12548 } 12549 12550 /** 12551 * Enable Mirrored Stream Classification Service (MSCS) and configure using 12552 * the provided configuration values. 12553 * 12554 * If MSCS has already been enabled/configured, this will override the 12555 * existing configuration. 12556 * 12557 * Refer to Section 11.25.3 of the IEEE 802.11-2020 standard for more information. 12558 * 12559 * @param mscsParams {@link MscsParams} object containing the configuration parameters. 12560 * @hide 12561 */ 12562 @SystemApi 12563 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12564 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12565 @RequiresPermission(anyOf = {MANAGE_WIFI_NETWORK_SELECTION}) enableMscs(@onNull MscsParams mscsParams)12566 public void enableMscs(@NonNull MscsParams mscsParams) { 12567 Objects.requireNonNull(mscsParams); 12568 try { 12569 mService.enableMscs(mscsParams); 12570 } catch (RemoteException e) { 12571 throw e.rethrowFromSystemServer(); 12572 } 12573 } 12574 12575 /** 12576 * Disable Mirrored Stream Classification Service (MSCS). 12577 * 12578 * If MSCS is enabled/configured, this will send a remove request to the AP. 12579 * 12580 * Refer to Section 11.25.3 of the IEEE 802.11-2020 standard for more information. 12581 * @hide 12582 */ 12583 @SystemApi 12584 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12585 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12586 @RequiresPermission(anyOf = {MANAGE_WIFI_NETWORK_SELECTION}) disableMscs()12587 public void disableMscs() { 12588 try { 12589 mService.disableMscs(); 12590 } catch (RemoteException e) { 12591 throw e.rethrowFromSystemServer(); 12592 } 12593 } 12594 12595 /** 12596 * Do not send the DHCP hostname to open networks. 12597 */ 12598 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12599 public static final int FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN = 1 << 0; 12600 12601 /** 12602 * Do not send the DHCP hostname to secure network. 12603 */ 12604 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12605 public static final int FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE = 1 << 1; 12606 12607 /** @hide */ 12608 @IntDef(flag = true, prefix = { "FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_" }, value = { 12609 FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN, 12610 FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE, 12611 }) 12612 @Retention(RetentionPolicy.SOURCE) 12613 public @interface SendDhcpHostnameRestriction {} 12614 12615 /** 12616 * Sets the global restrictions on which networks to send the device hostname to during DHCP. 12617 * 12618 * @param restriction Bitmask of {@link SendDhcpHostnameRestriction}, or none to indicate no 12619 * restriction. 12620 * @throws IllegalArgumentException if input is invalid 12621 * @throws SecurityException if the calling app is not a Device Owner (DO), or a privileged app 12622 * that has one of the permissions required by this API. 12623 */ 12624 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12625 @RequiresPermission(anyOf = { 12626 android.Manifest.permission.NETWORK_SETTINGS, 12627 android.Manifest.permission.NETWORK_SETUP_WIZARD 12628 }) setSendDhcpHostnameRestriction(@endDhcpHostnameRestriction int restriction)12629 public void setSendDhcpHostnameRestriction(@SendDhcpHostnameRestriction int restriction) { 12630 try { 12631 mService.setSendDhcpHostnameRestriction(mContext.getOpPackageName(), restriction); 12632 } catch (RemoteException e) { 12633 throw e.rethrowFromSystemServer(); 12634 } 12635 } 12636 12637 /** 12638 * Query the global restriction on which networks to send the device hostname to during DHCP. 12639 * @see #setSendDhcpHostnameRestriction(int) 12640 * 12641 * @param executor The executor on which callback will be invoked. 12642 * @param resultsCallback An asynchronous callback that will return a bitmask of 12643 * {@link SendDhcpHostnameRestriction}. 12644 * 12645 * @throws SecurityException if the calling app is not a Device Owner (DO), or a privileged app 12646 * that has one of the permissions required by this API. 12647 */ 12648 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12649 @RequiresPermission(anyOf = { 12650 android.Manifest.permission.NETWORK_SETTINGS, 12651 android.Manifest.permission.NETWORK_SETUP_WIZARD 12652 }) querySendDhcpHostnameRestriction(@onNull @allbackExecutor Executor executor, @NonNull IntConsumer resultsCallback)12653 public void querySendDhcpHostnameRestriction(@NonNull @CallbackExecutor Executor executor, 12654 @NonNull IntConsumer resultsCallback) { 12655 Objects.requireNonNull(executor, "executor cannot be null"); 12656 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12657 try { 12658 mService.querySendDhcpHostnameRestriction(mContext.getOpPackageName(), 12659 new IIntegerListener.Stub() { 12660 @Override 12661 public void onResult(int value) { 12662 Binder.clearCallingIdentity(); 12663 executor.execute(() -> { 12664 resultsCallback.accept(value); 12665 }); 12666 } 12667 }); 12668 } catch (RemoteException e) { 12669 throw e.rethrowFromSystemServer(); 12670 } 12671 } 12672 12673 /** 12674 * @return true if this device supports Aggressive roaming mode 12675 * {@link #setPerSsidRoamingMode(WifiSsid, int)} 12676 */ 12677 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) isAggressiveRoamingModeSupported()12678 public boolean isAggressiveRoamingModeSupported() { 12679 return isFeatureSupported(WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); 12680 } 12681 12682 /** 12683 * This API allows a privileged application to set roaming mode per SSID. 12684 * 12685 * Available for Device Owner (DO) and profile owner of an organization owned device. 12686 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 12687 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 12688 * 12689 * @param ssid SSID to be mapped to apply roaming policy 12690 * @param roamingMode One of the {@code ROAMING_MODE_} values. 12691 * @throws IllegalArgumentException if input is invalid. 12692 * @throws NullPointerException if the caller provided a null input. 12693 * @throws SecurityException if caller does not have the required permission. 12694 * @throws UnsupportedOperationException if the API is not supported on this SDK version or 12695 * {@link #isAggressiveRoamingModeSupported()} returns 12696 * false, but input roaming mode is 12697 * {@code ROAMING_MODE_AGGRESSIVE}. 12698 */ 12699 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12700 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12701 @SuppressLint("RequiresPermission") setPerSsidRoamingMode(@onNull WifiSsid ssid, @RoamingMode int roamingMode)12702 public void setPerSsidRoamingMode(@NonNull WifiSsid ssid, @RoamingMode int roamingMode) { 12703 if (roamingMode < ROAMING_MODE_NONE || roamingMode > ROAMING_MODE_AGGRESSIVE) { 12704 throw new IllegalArgumentException("invalid roaming mode: " + roamingMode); 12705 } 12706 Objects.requireNonNull(ssid, "ssid cannot be null"); 12707 try { 12708 mService.setPerSsidRoamingMode(ssid, roamingMode, mContext.getOpPackageName()); 12709 } catch (RemoteException e) { 12710 throw e.rethrowFromSystemServer(); 12711 } 12712 } 12713 12714 /** 12715 * This API allows a privileged application to remove roaming mode policy 12716 * configured using the {@link #setPerSsidRoamingMode(WifiSsid, int)}. 12717 * 12718 * Available for Device Owner (DO) and profile owner of an organization owned device. 12719 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 12720 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 12721 * 12722 * @param ssid SSID to be removed from the roaming mode policy. 12723 * @throws NullPointerException if the caller provided a null input. 12724 * @throws SecurityException if caller does not have the required permission. 12725 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 12726 */ 12727 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12728 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12729 @SuppressLint("RequiresPermission") removePerSsidRoamingMode(@onNull WifiSsid ssid)12730 public void removePerSsidRoamingMode(@NonNull WifiSsid ssid) { 12731 Objects.requireNonNull(ssid, "ssid cannot be null"); 12732 try { 12733 mService.removePerSsidRoamingMode(ssid, mContext.getOpPackageName()); 12734 } catch (RemoteException e) { 12735 throw e.rethrowFromSystemServer(); 12736 } 12737 } 12738 12739 /** 12740 * This API allows a privileged application to get roaming mode policies 12741 * configured using the {@link #setPerSsidRoamingMode(WifiSsid, int)}. 12742 * 12743 * Available for Device Owner (DO) and profile owner of an organization owned device. 12744 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 12745 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 12746 * 12747 * @param executor The executor on which callback will be invoked. 12748 * @param resultsCallback An asynchronous callback that will return the corresponding 12749 * roaming policies for the API caller. 12750 * @throws SecurityException if caller does not have the required permission. 12751 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 12752 */ 12753 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12754 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12755 @SuppressLint("RequiresPermission") getPerSsidRoamingModes(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Map<String, Integer>> resultsCallback)12756 public void getPerSsidRoamingModes(@NonNull @CallbackExecutor Executor executor, 12757 @NonNull Consumer<Map<String, Integer>> resultsCallback) { 12758 Objects.requireNonNull(executor, "executor cannot be null"); 12759 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 12760 try { 12761 mService.getPerSsidRoamingModes(mContext.getOpPackageName(), new IMapListener.Stub() { 12762 @Override 12763 public void onResult(Map roamingPolicies) { 12764 Binder.clearCallingIdentity(); 12765 executor.execute(() -> { 12766 resultsCallback.accept(roamingPolicies); 12767 }); 12768 } 12769 }); 12770 } catch (RemoteException e) { 12771 throw e.rethrowFromSystemServer(); 12772 } 12773 } 12774 12775 /** 12776 * Bundle key to check target wake time requester mode supported or not 12777 * @hide 12778 */ 12779 @SystemApi 12780 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12781 public static final String TWT_CAPABILITIES_KEY_BOOLEAN_TWT_REQUESTER = 12782 "key_requester"; 12783 12784 /** 12785 * Bundle key to get minimum wake duration supported in microseconds 12786 * @hide 12787 */ 12788 @SystemApi 12789 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12790 public static final String TWT_CAPABILITIES_KEY_INT_MIN_WAKE_DURATION_MICROS = 12791 "key_min_wake_duration"; 12792 /** 12793 * Bundle key to get maximum wake duration supported in microseconds 12794 * @hide 12795 */ 12796 @SystemApi 12797 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12798 public static final String TWT_CAPABILITIES_KEY_INT_MAX_WAKE_DURATION_MICROS = 12799 "key_max_wake_duration"; 12800 /** 12801 * Bundle key to get minimum wake interval supported in microseconds 12802 * @hide 12803 */ 12804 @SystemApi 12805 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12806 public static final String TWT_CAPABILITIES_KEY_LONG_MIN_WAKE_INTERVAL_MICROS = 12807 "key_min_wake_interval"; 12808 /** 12809 * Bundle key to get maximum wake interval supported in microseconds 12810 * @hide 12811 */ 12812 @SystemApi 12813 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 12814 public static final String TWT_CAPABILITIES_KEY_LONG_MAX_WAKE_INTERVAL_MICROS = 12815 "key_max_wake_interval"; 12816 12817 /** @hide */ 12818 @StringDef(prefix = { "TWT_CAPABILITIES_KEY_"}, value = { 12819 TWT_CAPABILITIES_KEY_BOOLEAN_TWT_REQUESTER, 12820 TWT_CAPABILITIES_KEY_INT_MIN_WAKE_DURATION_MICROS, 12821 TWT_CAPABILITIES_KEY_INT_MAX_WAKE_DURATION_MICROS, 12822 TWT_CAPABILITIES_KEY_LONG_MIN_WAKE_INTERVAL_MICROS, 12823 TWT_CAPABILITIES_KEY_LONG_MAX_WAKE_INTERVAL_MICROS, 12824 }) 12825 @Retention(RetentionPolicy.SOURCE) 12826 public @interface TwtCapabilities {} 12827 12828 /** 12829 * Get target wake time (TWT) capabilities of the primary station interface. 12830 * 12831 * Note: Target wake time feature is only supported for primary station. If Wi-Fi is off or the 12832 * capability is not available the asynchronous callback will be called with the bundle 12833 * with values { false, -1, -1, -1, -1 }. 12834 * 12835 * @param executor Executor to execute listener callback 12836 * @param resultCallback An asynchronous callback that will return a bundle for target wake time 12837 * capabilities. See {@link TwtCapabilities} for the string keys for 12838 * the bundle. 12839 * @throws SecurityException if the caller does not have permission. 12840 * @throws NullPointerException if the caller provided null inputs. 12841 * @throws UnsupportedOperationException if the API is not supported. 12842 * @hide 12843 */ 12844 @SystemApi 12845 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12846 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) 12847 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) getTwtCapabilities(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Bundle> resultCallback)12848 public void getTwtCapabilities(@NonNull @CallbackExecutor Executor executor, 12849 @NonNull Consumer<Bundle> resultCallback) { 12850 Objects.requireNonNull(executor, "executor cannot be null"); 12851 Objects.requireNonNull(resultCallback, "resultCallback cannot be null"); 12852 if (!SdkLevel.isAtLeastV()) { 12853 throw new UnsupportedOperationException(); 12854 } 12855 try { 12856 Bundle extras = new Bundle(); 12857 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12858 mContext.getAttributionSource()); 12859 mService.getTwtCapabilities( 12860 new ITwtCapabilitiesListener.Stub() { 12861 @Override 12862 public void onResult(Bundle value) { 12863 Binder.clearCallingIdentity(); 12864 executor.execute(() -> { 12865 resultCallback.accept(value); 12866 }); 12867 } 12868 }, extras); 12869 } catch (RemoteException e) { 12870 throw e.rethrowFromSystemServer(); 12871 } 12872 } 12873 12874 private class TwtCallbackProxy extends ITwtCallback.Stub { 12875 private final Executor mExecutor; 12876 private final TwtSessionCallback mCallback; 12877 TwtCallbackProxy(Executor executor, TwtSessionCallback callback)12878 private TwtCallbackProxy(Executor executor, TwtSessionCallback callback) { 12879 mExecutor = executor; 12880 mCallback = callback; 12881 } 12882 12883 @Override onFailure(@wtSessionCallback.TwtErrorCode int errorCode)12884 public void onFailure(@TwtSessionCallback.TwtErrorCode int errorCode) 12885 throws RemoteException { 12886 if (mVerboseLoggingEnabled) { 12887 Log.v(TAG, "TwtCallbackProxy: onFailure(errorCode = " + errorCode + " )"); 12888 } 12889 Binder.clearCallingIdentity(); 12890 mExecutor.execute(() -> mCallback.onFailure(errorCode)); 12891 } 12892 12893 @Override onTeardown(@wtSessionCallback.TwtReasonCode int reasonCode)12894 public void onTeardown(@TwtSessionCallback.TwtReasonCode int reasonCode) 12895 throws RemoteException { 12896 if (mVerboseLoggingEnabled) { 12897 Log.v(TAG, "TwtCallbackProxy: onTeardown(errorCode = " + reasonCode + " )"); 12898 } 12899 Binder.clearCallingIdentity(); 12900 mExecutor.execute(() -> mCallback.onTeardown(reasonCode)); 12901 } 12902 12903 @Override onCreate(int wakeDuration, long wakeInterval, int mloLinkId, int owner, int sessionId)12904 public void onCreate(int wakeDuration, long wakeInterval, int mloLinkId, int owner, 12905 int sessionId) throws RemoteException { 12906 if (mVerboseLoggingEnabled) { 12907 Log.v(TAG, "TwtCallbackProxy: onCreate " + sessionId); 12908 } 12909 12910 WifiTwtSession wifiTwtSession = new WifiTwtSession(WifiManager.this, wakeDuration, 12911 wakeInterval, mloLinkId, owner, sessionId); 12912 Binder.clearCallingIdentity(); 12913 mExecutor.execute(() -> mCallback.onCreate(wifiTwtSession)); 12914 } 12915 } 12916 12917 /** 12918 * Set up a TWT session with a TWT responder capable AP. Only supported for primary connected 12919 * station which is a TWT requester. See {@link #getTwtCapabilities(Executor, Consumer)} and 12920 * {@link ScanResult#isTwtResponder()} to check station and AP support. 12921 * 12922 * Following callbacks are invoked, 12923 * - {@link TwtSessionCallback#onFailure(int)} upon error with error code. 12924 * - {@link TwtSessionCallback#onCreate(TwtSession)} upon TWT session creation. 12925 * - {@link TwtSessionCallback#onTeardown(int)} upon TWT session teardown. 12926 * 12927 * Note: {@link #getTwtCapabilities(Executor, Consumer)} gives {@link TwtCapabilities} which can 12928 * be used to fill in the valid TWT wake interval and duration ranges for {@link TwtRequest}. 12929 * 12930 * @param twtRequest TWT request 12931 * @param executor Executor to execute listener callback on 12932 * @param callback Callback to register 12933 * @throws SecurityException if the caller does not have permission. 12934 * @throws NullPointerException if the caller provided null inputs. 12935 * @throws UnsupportedOperationException if the API is not supported. 12936 * @hide 12937 */ 12938 @SystemApi 12939 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 12940 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) 12941 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) setupTwtSession(@onNull TwtRequest twtRequest, @NonNull @CallbackExecutor Executor executor, @NonNull TwtSessionCallback callback)12942 public void setupTwtSession(@NonNull TwtRequest twtRequest, 12943 @NonNull @CallbackExecutor Executor executor, @NonNull TwtSessionCallback callback) { 12944 Objects.requireNonNull(executor, "executor cannot be null"); 12945 Objects.requireNonNull(callback, "callback cannot be null"); 12946 Objects.requireNonNull(twtRequest, "twtRequest cannot be null"); 12947 if (!SdkLevel.isAtLeastV()) { 12948 throw new UnsupportedOperationException(); 12949 } 12950 try { 12951 ITwtCallback.Stub binderCallback = new TwtCallbackProxy(executor, callback); 12952 Bundle extras = new Bundle(); 12953 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12954 mContext.getAttributionSource()); 12955 mService.setupTwtSession(twtRequest, binderCallback, extras); 12956 } catch (RemoteException e) { 12957 throw e.rethrowFromSystemServer(); 12958 } 12959 } 12960 12961 /** 12962 * Get stats of the target wake time session. 12963 * 12964 * Note: For Internal use only. Expected to be called through 12965 * {@link TwtSession#getStats(Executor, Consumer)}. If the command fails, -1 will be returned 12966 * for all stats values. 12967 * 12968 * @param sessionId TWT session id 12969 * @param executor The executor on which callback will be invoked. 12970 * @param resultCallback The asynchronous callback that will return bundle with key string 12971 * {@link TwtSession.TwtStats}. 12972 * 12973 * @throws SecurityException if the caller does not have permission. 12974 * @throws NullPointerException if the caller provided null inputs. 12975 * @throws UnsupportedOperationException if the API is not supported or primary station is 12976 * not connected. 12977 * @hide 12978 */ getStatsTwtSession(@onNull int sessionId, @NonNull Executor executor, @NonNull Consumer<Bundle> resultCallback)12979 public void getStatsTwtSession(@NonNull int sessionId, @NonNull Executor executor, 12980 @NonNull Consumer<Bundle> resultCallback) { 12981 Objects.requireNonNull(executor, "executor cannot be null"); 12982 Objects.requireNonNull(resultCallback, "resultsCallback cannot be null"); 12983 if (!SdkLevel.isAtLeastV()) { 12984 throw new UnsupportedOperationException(); 12985 } 12986 try { 12987 Bundle extras = new Bundle(); 12988 if (SdkLevel.isAtLeastS()) { 12989 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 12990 mContext.getAttributionSource()); 12991 } 12992 mService.getStatsTwtSession(sessionId, 12993 new ITwtStatsListener.Stub() { 12994 @Override 12995 public void onResult(Bundle value) { 12996 Binder.clearCallingIdentity(); 12997 executor.execute(() -> { 12998 resultCallback.accept(value); 12999 }); 13000 } 13001 }, extras); 13002 } catch (RemoteException e) { 13003 throw e.rethrowFromSystemServer(); 13004 } 13005 } 13006 13007 /** 13008 * Teardown the target wake time session. Only owner can teardown the session. 13009 * 13010 * Note: For internal use only. Expected to be called through 13011 * {@link TwtSessionCallback#onTeardown(int)}. 13012 * 13013 * @param sessionId TWT session id 13014 * @throws SecurityException if the caller does not have permission. 13015 * @throws UnsupportedOperationException if the API is not supported or primary station is not 13016 * connected. 13017 * @hide 13018 */ teardownTwtSession(int sessionId)13019 public void teardownTwtSession(int sessionId) { 13020 if (!SdkLevel.isAtLeastV()) { 13021 throw new UnsupportedOperationException(); 13022 } 13023 try { 13024 Bundle extras = new Bundle(); 13025 if (SdkLevel.isAtLeastS()) { 13026 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 13027 mContext.getAttributionSource()); 13028 } 13029 mService.teardownTwtSession(sessionId, extras); 13030 } catch (RemoteException e) { 13031 throw e.rethrowFromSystemServer(); 13032 } 13033 } 13034 13035 /** 13036 * Allows a privileged application to set whether or not this device allows 13037 * device-to-device connections when infra STA is disabled. Callers can use 13038 * {@link #queryD2dAllowedWhenInfraStaDisabled(Executor, Consumer)} to check the currently 13039 * set value. 13040 * 13041 * Note: This functionality is supported only when the device support device-to-device 13042 * when infra STA is disabled. Use {@link #isD2dSupportedWhenInfraStaDisabled()} to 13043 * know if device supported device-to-device when infra STA is disabled. 13044 * 13045 * @param isAllowed whether or not the device allows to device-to-device connectivity when 13046 * infra STA is disabled. 13047 * @throws SecurityException if the caller does not have permission. 13048 * @hide 13049 */ 13050 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 13051 @SystemApi 13052 @RequiresPermission(anyOf = { 13053 android.Manifest.permission.NETWORK_SETTINGS, 13054 android.Manifest.permission.NETWORK_SETUP_WIZARD 13055 }) 13056 @RequiresApi(Build.VERSION_CODES.TIRAMISU) setD2dAllowedWhenInfraStaDisabled(boolean isAllowed)13057 public void setD2dAllowedWhenInfraStaDisabled(boolean isAllowed) { 13058 try { 13059 mService.setD2dAllowedWhenInfraStaDisabled(isAllowed); 13060 } catch (RemoteException e) { 13061 throw e.rethrowFromSystemServer(); 13062 } 13063 } 13064 13065 /** 13066 * Query whether or not this device is configured to allow D2d connection when 13067 * infra STA is disabled. 13068 * see: {@link #setD2dAllowedWhenInfraStaDisabled(boolean)}. 13069 * 13070 * 13071 * @param executor The executor on which callback will be invoked. 13072 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 13073 * whether device-to-device connection is allowed or disallowed 13074 * when infra STA is disabled. 13075 * @hide 13076 */ 13077 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 13078 @SystemApi queryD2dAllowedWhenInfraStaDisabled(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)13079 public void queryD2dAllowedWhenInfraStaDisabled(@NonNull @CallbackExecutor Executor executor, 13080 @NonNull Consumer<Boolean> resultsCallback) { 13081 Objects.requireNonNull(executor, "executor cannot be null"); 13082 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 13083 try { 13084 mService.queryD2dAllowedWhenInfraStaDisabled( 13085 new IBooleanListener.Stub() { 13086 @Override 13087 public void onResult(boolean value) { 13088 Binder.clearCallingIdentity(); 13089 executor.execute(() -> { 13090 resultsCallback.accept(value); 13091 }); 13092 } 13093 }); 13094 } catch (RemoteException e) { 13095 throw e.rethrowFromSystemServer(); 13096 } 13097 } 13098 13099 /** 13100 * Disallow Wi-Fi autojoin on ScanResults matching the selected security types. 13101 * This does not restrict manual connections. 13102 * 13103 * @param restrictions An array of {@code WifiInfo.SECURITY_TYPE_*} values to disallow autojoin. 13104 * An empty array will clear all restrictions. Note, certain combinations of 13105 * restricted security types are not valid. 13106 * 1. restrictions contains WifiInfo.SECURITY_TYPE_OWE, 13107 * but not WifiInfo.SECURITY_TYPE_OPEN. 13108 * 2. restrictions contains WifiInfo.SECURITY_TYPE_SAE, 13109 * but not WifiInfo.SECURITY_TYPE_PSK. 13110 * 3. restrictions contains WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE, 13111 * but not WifiInfo.SECURITY_TYPE_EAP. 13112 * 13113 * Usage example: 13114 * <pre> 13115 * To disallow autojoin to Wi-Fi networks with security type, OPEN, WEP 13116 * or OWE, use following argument. 13117 * 13118 * {@code 13119 * int[] restrictions = { 13120 * WifiInfo.SECURITY_TYPE_OPEN, 13121 * WifiInfo.SECURITY_TYPE_WEP, 13122 * WifiInfo.SECURITY_TYPE_OWE }; 13123 * wifiManager.setAutojoinDisallowedSecurityTypes(restrictions); 13124 * } 13125 * 13126 * To clear autojoin restriction on all security types, use following 13127 * argument. 13128 * 13129 * {@code 13130 * wifiManager.setAutojoinDisallowedSecurityTypes(new int[0]); 13131 * } 13132 * </pre> 13133 * @throws UnsupportedOperationException if the API is not supported. 13134 * @hide 13135 */ 13136 @SystemApi 13137 @FlaggedApi(Flags.FLAG_AUTOJOIN_RESTRICTION_SECURITY_TYPES_API) 13138 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 13139 @RequiresPermission(anyOf = { 13140 android.Manifest.permission.NETWORK_SETTINGS, 13141 MANAGE_WIFI_NETWORK_SELECTION 13142 }) setAutojoinDisallowedSecurityTypes( @onNull @ifiAnnotations.SecurityType int[] restrictions)13143 public void setAutojoinDisallowedSecurityTypes( 13144 @NonNull @WifiAnnotations.SecurityType int[] restrictions) { 13145 if (!SdkLevel.isAtLeastT()) { 13146 throw new UnsupportedOperationException(); 13147 } 13148 Objects.requireNonNull(restrictions, "restrictions cannot be null"); 13149 try { 13150 Bundle extras = new Bundle(); 13151 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 13152 mContext.getAttributionSource()); 13153 int restrictionBitmap = 0; 13154 for (int securityType : restrictions) { 13155 restrictionBitmap |= 0x1 << securityType; 13156 } 13157 mService.setAutojoinDisallowedSecurityTypes(restrictionBitmap, extras); 13158 } catch (RemoteException e) { 13159 throw e.rethrowFromSystemServer(); 13160 } 13161 } 13162 13163 /** 13164 * Retrieves the autojoin disallowed Wi-Fi security types currently set for the device. 13165 * 13166 * @param executor The executor to run the callback on. 13167 * @param resultsCallback The callback to receive the result. It will be called with an array 13168 * of autojoin disallowedse security types from 13169 * {@code WifiInfo.SECURITY_TYPE_*}. 13170 * @throws UnsupportedOperationException if the API is not supported. 13171 * @hide 13172 */ 13173 @SystemApi 13174 @FlaggedApi(Flags.FLAG_AUTOJOIN_RESTRICTION_SECURITY_TYPES_API) 13175 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 13176 @RequiresPermission(anyOf = { 13177 android.Manifest.permission.NETWORK_SETTINGS, 13178 MANAGE_WIFI_NETWORK_SELECTION 13179 }) getAutojoinDisallowedSecurityTypes(@onNull @allbackExecutor Executor executor, @NonNull Consumer<int[]> resultsCallback)13180 public void getAutojoinDisallowedSecurityTypes(@NonNull @CallbackExecutor Executor executor, 13181 @NonNull Consumer<int[]> resultsCallback) { 13182 if (!SdkLevel.isAtLeastT()) { 13183 throw new UnsupportedOperationException(); 13184 } 13185 Objects.requireNonNull(executor, "executor cannot be null"); 13186 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 13187 try { 13188 Bundle extras = new Bundle(); 13189 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 13190 mContext.getAttributionSource()); 13191 mService.getAutojoinDisallowedSecurityTypes(new IIntegerListener.Stub() { 13192 @Override 13193 public void onResult(int value) { 13194 Binder.clearCallingIdentity(); 13195 executor.execute(() -> { 13196 List<Integer> restrictions = new ArrayList<>(); 13197 for (int i = 0; i < Integer.SIZE; i++) { 13198 if (((0x1 << i) & value) != 0) { 13199 restrictions.add(i); 13200 } 13201 } 13202 int[] results = new int[restrictions.size()]; 13203 for (int i = 0; i < restrictions.size(); i++) { 13204 results[i] = restrictions.get(i); 13205 } 13206 resultsCallback.accept(results); 13207 }); 13208 } 13209 }, extras); 13210 } catch (RemoteException e) { 13211 throw e.rethrowFromSystemServer(); 13212 } 13213 } 13214 13215 /** 13216 * Indicates what {@link AdvancedProtectionFeature} are supported over Wi-Fi. 13217 * 13218 * The {@link AdvancedProtectionFeature} is the advanced protection feature 13219 * providing protections which works when Android Advanced Protection Mode (AAPM) 13220 * is enabled. 13221 * 13222 * @return a list of the supported features. 13223 * @hide 13224 */ 13225 @SystemApi 13226 @FlaggedApi(android.security.Flags.FLAG_AAPM_API) 13227 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 13228 @NonNull 13229 @SuppressLint("NewApi") getAvailableAdvancedProtectionFeatures()13230 public List<AdvancedProtectionFeature> getAvailableAdvancedProtectionFeatures() { 13231 if (!Environment.isSdkAtLeastB()) { 13232 throw new UnsupportedOperationException(); 13233 } 13234 List<AdvancedProtectionFeature> features = new ArrayList<>(); 13235 if (Flags.wepDisabledInApm() && android.security.Flags.aapmApi()) { 13236 features.add(new AdvancedProtectionFeature( 13237 AdvancedProtectionManager.FEATURE_ID_DISALLOW_WEP)); 13238 } 13239 return features; 13240 } 13241 13242 /** 13243 * When the device is connected to a network suggested by calling app 13244 * {@link #addNetworkSuggestions(List)}, this API provide a way to avoid the current connection 13245 * without {@link #removeNetworkSuggestions(List)}. The disallowed network will be disconnected 13246 * or roam to other networks. 13247 * App can only use this API to control the current connected network 13248 * which was suggested by this app. 13249 * 13250 * @param blockingOption Option to change for the network blocking {@link BlockingOption} 13251 */ 13252 @FlaggedApi(Flags.FLAG_BSSID_BLOCKLIST_FOR_SUGGESTION) 13253 @RequiresPermission(CHANGE_WIFI_STATE) disallowCurrentSuggestedNetwork(@onNull BlockingOption blockingOption)13254 public void disallowCurrentSuggestedNetwork(@NonNull BlockingOption blockingOption) { 13255 Objects.requireNonNull(blockingOption, "blockingOption cannot be null"); 13256 try { 13257 mService.disallowCurrentSuggestedNetwork(blockingOption, mContext.getOpPackageName()); 13258 } catch (RemoteException e) { 13259 throw e.rethrowFromSystemServer(); 13260 } 13261 } 13262 13263 /** 13264 * Return whether Unsynchronized Service Discovery (USD) subscriber is supported or not. 13265 * @hide 13266 */ 13267 @android.annotation.RequiresApi(Build.VERSION_CODES.BAKLAVA) 13268 @SystemApi 13269 @FlaggedApi(android.net.wifi.flags.Flags.FLAG_USD) 13270 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) isUsdSubscriberSupported()13271 public boolean isUsdSubscriberSupported() { 13272 if (!Environment.isSdkAtLeastB()) { 13273 throw new UnsupportedOperationException(); 13274 } 13275 try { 13276 return mService.isUsdSubscriberSupported(); 13277 } catch (RemoteException e) { 13278 throw e.rethrowFromSystemServer(); 13279 } 13280 } 13281 13282 /** 13283 * Return whether Unsynchronized Service Discovery (USD) publisher is supported or not. 13284 * <p> 13285 * The USD publisher support is controlled by an overlay config_wifiUsdPublisherSupported. 13286 * By default, the feature will be disabled because the publisher operation impacts other 13287 * concurrency operation such as Station. The USD publisher switches channels and dwells a 13288 * longer time (500 milliseconds to 1 second) on non-home channel which disrupts other 13289 * concurrency operation. 13290 * 13291 * @return true if publisher feature is supported, otherwise false. 13292 * @hide 13293 */ 13294 @android.annotation.RequiresApi(Build.VERSION_CODES.BAKLAVA) 13295 @SystemApi 13296 @FlaggedApi(android.net.wifi.flags.Flags.FLAG_USD) 13297 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) isUsdPublisherSupported()13298 public boolean isUsdPublisherSupported() { 13299 if (!Environment.isSdkAtLeastB()) { 13300 throw new UnsupportedOperationException(); 13301 } 13302 try { 13303 return mService.isUsdPublisherSupported(); 13304 } catch (RemoteException e) { 13305 throw e.rethrowFromSystemServer(); 13306 } 13307 } 13308 } 13309