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.READ_WIFI_CREDENTIAL; 25 import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION; 26 27 import android.Manifest; 28 import android.annotation.CallbackExecutor; 29 import android.annotation.IntDef; 30 import android.annotation.IntRange; 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.annotation.RequiresPermission; 34 import android.annotation.SdkConstant; 35 import android.annotation.SdkConstant.SdkConstantType; 36 import android.annotation.SuppressLint; 37 import android.annotation.SystemApi; 38 import android.annotation.SystemService; 39 import android.app.ActivityManager; 40 import android.app.admin.WifiSsidPolicy; 41 import android.compat.annotation.ChangeId; 42 import android.compat.annotation.EnabledAfter; 43 import android.compat.annotation.UnsupportedAppUsage; 44 import android.content.Context; 45 import android.net.ConnectivityManager; 46 import android.net.ConnectivityManager.NetworkCallback; 47 import android.net.DhcpInfo; 48 import android.net.DhcpOption; 49 import android.net.LinkProperties; 50 import android.net.MacAddress; 51 import android.net.Network; 52 import android.net.NetworkCapabilities; 53 import android.net.NetworkRequest; 54 import android.net.NetworkStack; 55 import android.net.Uri; 56 import android.net.wifi.hotspot2.IProvisioningCallback; 57 import android.net.wifi.hotspot2.OsuProvider; 58 import android.net.wifi.hotspot2.PasspointConfiguration; 59 import android.net.wifi.hotspot2.ProvisioningCallback; 60 import android.net.wifi.p2p.WifiP2pConfig; 61 import android.net.wifi.p2p.WifiP2pManager; 62 import android.os.Binder; 63 import android.os.Build; 64 import android.os.Bundle; 65 import android.os.Handler; 66 import android.os.IBinder; 67 import android.os.Looper; 68 import android.os.Parcel; 69 import android.os.Parcelable; 70 import android.os.RemoteException; 71 import android.os.WorkSource; 72 import android.os.connectivity.WifiActivityEnergyInfo; 73 import android.telephony.SubscriptionInfo; 74 import android.telephony.TelephonyManager; 75 import android.text.TextUtils; 76 import android.util.ArraySet; 77 import android.util.CloseGuard; 78 import android.util.Log; 79 import android.util.Pair; 80 import android.util.SparseArray; 81 82 import androidx.annotation.RequiresApi; 83 84 import com.android.internal.annotations.GuardedBy; 85 import com.android.internal.annotations.VisibleForTesting; 86 import com.android.modules.utils.HandlerExecutor; 87 import com.android.modules.utils.ParceledListSlice; 88 import com.android.modules.utils.build.SdkLevel; 89 90 import java.lang.annotation.Retention; 91 import java.lang.annotation.RetentionPolicy; 92 import java.lang.ref.Reference; 93 import java.lang.ref.WeakReference; 94 import java.net.InetAddress; 95 import java.time.Duration; 96 import java.util.ArrayList; 97 import java.util.Arrays; 98 import java.util.Collections; 99 import java.util.HashMap; 100 import java.util.List; 101 import java.util.Map; 102 import java.util.Objects; 103 import java.util.Set; 104 import java.util.StringTokenizer; 105 import java.util.concurrent.Executor; 106 import java.util.function.BiConsumer; 107 import java.util.function.Consumer; 108 109 /** 110 * This class provides the primary API for managing all aspects of Wi-Fi 111 * connectivity. 112 * <p> 113 * On releases before {@link android.os.Build.VERSION_CODES#N}, this object 114 * should only be obtained from an {@linkplain Context#getApplicationContext() 115 * application context}, and not from any other derived context to avoid memory 116 * leaks within the calling process. 117 * <p> 118 * It deals with several categories of items: 119 * </p> 120 * <ul> 121 * <li>The list of configured networks. The list can be viewed and updated, and 122 * attributes of individual entries can be modified.</li> 123 * <li>The currently active Wi-Fi network, if any. Connectivity can be 124 * established or torn down, and dynamic information about the state of the 125 * network can be queried.</li> 126 * <li>Results of access point scans, containing enough information to make 127 * decisions about what access point to connect to.</li> 128 * <li>It defines the names of various Intent actions that are broadcast upon 129 * any sort of change in Wi-Fi state. 130 * </ul> 131 * <p> 132 * This is the API to use when performing Wi-Fi specific operations. To perform 133 * operations that pertain to network connectivity at an abstract level, use 134 * {@link android.net.ConnectivityManager}. 135 * </p> 136 */ 137 @SystemService(Context.WIFI_SERVICE) 138 public class WifiManager { 139 140 private static final String TAG = "WifiManager"; 141 142 /** 143 * Local networks should not be modified by B&R since the user may have 144 * updated it with the latest configurations. 145 * @hide 146 */ 147 @ChangeId 148 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2) 149 public static final long NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE = 234793325L; 150 151 // Supplicant error codes: 152 /** 153 * The error code if there was a problem authenticating. 154 * @deprecated This is no longer supported. 155 */ 156 @Deprecated 157 public static final int ERROR_AUTHENTICATING = 1; 158 159 /** 160 * The reason code if there is no error during authentication. 161 * It could also imply that there no authentication in progress, 162 * this reason code also serves as a reset value. 163 * @deprecated This is no longer supported. 164 * @hide 165 */ 166 @Deprecated 167 public static final int ERROR_AUTH_FAILURE_NONE = 0; 168 169 /** 170 * The reason code if there was a timeout authenticating. 171 * @deprecated This is no longer supported. 172 * @hide 173 */ 174 @Deprecated 175 public static final int ERROR_AUTH_FAILURE_TIMEOUT = 1; 176 177 /** 178 * The reason code if there was a wrong password while 179 * authenticating. 180 * @deprecated This is no longer supported. 181 * @hide 182 */ 183 @Deprecated 184 public static final int ERROR_AUTH_FAILURE_WRONG_PSWD = 2; 185 186 /** 187 * The reason code if there was EAP failure while 188 * authenticating. 189 * @deprecated This is no longer supported. 190 * @hide 191 */ 192 @Deprecated 193 public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3; 194 195 /** @hide */ 196 public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM = 256; 197 198 /** @hide */ 199 public static final int NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM = 1024; 200 201 /** 202 * Reason code if all of the network suggestions were successfully added or removed. 203 */ 204 public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; 205 206 /** 207 * Reason code if there was an internal error in the platform while processing the addition or 208 * removal of suggestions. 209 */ 210 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1; 211 212 /** 213 * Reason code if the user has disallowed "android:change_wifi_state" app-ops from the app. 214 * @see android.app.AppOpsManager#unsafeCheckOp(String, int, String). 215 */ 216 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED = 2; 217 218 /** 219 * Reason code if one or more of the network suggestions added already exists in platform's 220 * database. 221 * Note: this code will not be returned with Android 11 as in-place modification is allowed, 222 * please check {@link #addNetworkSuggestions(List)}. 223 * @see WifiNetworkSuggestion#equals(Object) 224 */ 225 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 3; 226 227 /** 228 * Reason code if the number of network suggestions provided by the app crosses the max 229 * threshold set per app. 230 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} if 231 * the total size exceeds the limit. 232 * @see #getMaxNumberOfNetworkSuggestionsPerApp() 233 */ 234 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 4; 235 236 /** 237 * Reason code if one or more of the network suggestions removed does not exist in platform's 238 * database. 239 * The framework won't remove any suggestions if one or more of suggestions provided 240 * by {@link #removeNetworkSuggestions(List)} does not exist in database. 241 * @see WifiNetworkSuggestion#equals(Object) 242 */ 243 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5; 244 245 /** 246 * Reason code if one or more of the network suggestions added is not allowed. 247 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} 248 * if one or more of them is not allowed. 249 * This error may be caused by suggestion is using SIM-based encryption method, but calling app 250 * is not carrier privileged. 251 */ 252 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED = 6; 253 254 /** 255 * Reason code if one or more of the network suggestions added is invalid. Framework will reject 256 * all the suggestions in the list. 257 * The framework will reject all suggestions provided by {@link #addNetworkSuggestions(List)} 258 * if one or more of them is invalid. 259 * Please use {@link WifiNetworkSuggestion.Builder} to create network suggestions. 260 */ 261 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID = 7; 262 263 /** 264 * Reason code if {@link android.os.UserManager#DISALLOW_ADD_WIFI_CONFIG} user restriction 265 * is set and calling app is restricted by device admin. 266 */ 267 public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN = 8; 268 269 /** @hide */ 270 @IntDef(prefix = { "STATUS_NETWORK_SUGGESTIONS_" }, value = { 271 STATUS_NETWORK_SUGGESTIONS_SUCCESS, 272 STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, 273 STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED, 274 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE, 275 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP, 276 STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, 277 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED, 278 STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID, 279 STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN, 280 }) 281 @Retention(RetentionPolicy.SOURCE) 282 public @interface NetworkSuggestionsStatusCode {} 283 284 /** 285 * Reason code if suggested network connection attempt failed with an unknown failure. 286 */ 287 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN = 0; 288 /** 289 * Reason code if suggested network connection attempt failed with association failure. 290 */ 291 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION = 1; 292 /** 293 * Reason code if suggested network connection attempt failed with an authentication failure. 294 */ 295 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION = 2; 296 /** 297 * Reason code if suggested network connection attempt failed with an IP provision failure. 298 */ 299 public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING = 3; 300 301 /** @hide */ 302 @IntDef(prefix = {"STATUS_SUGGESTION_CONNECTION_FAILURE_"}, 303 value = {STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN, 304 STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION, 305 STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION, 306 STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING 307 }) 308 @Retention(RetentionPolicy.SOURCE) 309 public @interface SuggestionConnectionStatusCode {} 310 311 /** 312 * Reason code if local-only network connection attempt failed with an unknown failure. 313 */ 314 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_UNKNOWN = 0; 315 /** 316 * Reason code if local-only network connection attempt failed with association failure. 317 */ 318 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_ASSOCIATION = 1; 319 /** 320 * Reason code if local-only network connection attempt failed with an authentication failure. 321 */ 322 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION = 2; 323 /** 324 * Reason code if local-only network connection attempt failed with an IP provisioning failure. 325 */ 326 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING = 3; 327 /** 328 * Reason code if local-only network connection attempt failed with AP not in range. 329 */ 330 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND = 4; 331 /** 332 * Reason code if local-only network connection attempt failed with AP not responding 333 */ 334 public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE = 5; 335 336 /** @hide */ 337 @IntDef(prefix = {"STATUS_LOCAL_ONLY_CONNECTION_FAILURE_"}, 338 value = {STATUS_LOCAL_ONLY_CONNECTION_FAILURE_UNKNOWN, 339 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_ASSOCIATION, 340 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION, 341 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING, 342 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND, 343 STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE 344 }) 345 @Retention(RetentionPolicy.SOURCE) 346 public @interface LocalOnlyConnectionStatusCode {} 347 348 /** 349 * Status code if suggestion approval status is unknown, an App which hasn't made any 350 * suggestions will get this code. 351 */ 352 public static final int STATUS_SUGGESTION_APPROVAL_UNKNOWN = 0; 353 354 /** 355 * Status code if the calling app is still pending user approval for suggestions. 356 */ 357 public static final int STATUS_SUGGESTION_APPROVAL_PENDING = 1; 358 359 /** 360 * Status code if the calling app got the user approval for suggestions. 361 */ 362 public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER = 2; 363 364 /** 365 * Status code if the calling app suggestions were rejected by the user. 366 */ 367 public static final int STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER = 3; 368 369 /** 370 * Status code if the calling app was approved by virtue of being a carrier privileged app. 371 * @see TelephonyManager#hasCarrierPrivileges(). 372 */ 373 public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE = 4; 374 375 /** @hide */ 376 @IntDef(prefix = {"STATUS_SUGGESTION_APPROVAL_"}, 377 value = {STATUS_SUGGESTION_APPROVAL_UNKNOWN, 378 STATUS_SUGGESTION_APPROVAL_PENDING, 379 STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER, 380 STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER, 381 STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE 382 }) 383 @Retention(RetentionPolicy.SOURCE) 384 public @interface SuggestionUserApprovalStatus {} 385 386 /** 387 * If one of the removed suggestions is currently connected, that network will be disconnected 388 * after a short delay as opposed to immediately (which will be done by 389 * {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT}). The {@link ConnectivityManager} may call the 390 * {@link NetworkCallback#onLosing(Network, int)} on such networks. 391 */ 392 public static final int ACTION_REMOVE_SUGGESTION_LINGER = 1; 393 394 /** 395 * If one of the removed suggestions is currently connected, trigger an immediate disconnect 396 * after suggestions removal 397 */ 398 public static final int ACTION_REMOVE_SUGGESTION_DISCONNECT = 2; 399 400 /** @hide */ 401 @IntDef(prefix = {"ACTION_REMOVE_SUGGESTION_"}, 402 value = {ACTION_REMOVE_SUGGESTION_LINGER, 403 ACTION_REMOVE_SUGGESTION_DISCONNECT 404 }) 405 @Retention(RetentionPolicy.SOURCE) 406 public @interface ActionAfterRemovingSuggestion {} 407 408 /** 409 * Only available on Android S or later. 410 * @hide 411 **/ 412 public static final String EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE = 413 "EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE"; 414 415 /** 416 * Broadcast intent action indicating whether Wi-Fi scanning is currently available. 417 * Available extras: 418 * - {@link #EXTRA_SCAN_AVAILABLE} 419 */ 420 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 421 public static final String ACTION_WIFI_SCAN_AVAILABILITY_CHANGED = 422 "android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED"; 423 424 /** 425 * A boolean extra indicating whether scanning is currently available. 426 * Sent in the broadcast {@link #ACTION_WIFI_SCAN_AVAILABILITY_CHANGED}. 427 * Its value is true if scanning is currently available, false otherwise. 428 */ 429 public static final String EXTRA_SCAN_AVAILABLE = "android.net.wifi.extra.SCAN_AVAILABLE"; 430 431 /** 432 * Broadcast intent action indicating that the credential of a Wi-Fi network 433 * has been changed. One extra provides the ssid of the network. Another 434 * extra provides the event type, whether the credential is saved or forgot. 435 * @hide 436 */ 437 @SystemApi 438 public static final String WIFI_CREDENTIAL_CHANGED_ACTION = 439 "android.net.wifi.WIFI_CREDENTIAL_CHANGED"; 440 /** @hide */ 441 @SystemApi 442 public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et"; 443 /** @hide */ 444 @SystemApi 445 public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid"; 446 /** @hide */ 447 @SystemApi 448 public static final int WIFI_CREDENTIAL_SAVED = 0; 449 /** @hide */ 450 @SystemApi 451 public static final int WIFI_CREDENTIAL_FORGOT = 1; 452 453 /** @hide */ 454 @SystemApi 455 public static final int PASSPOINT_HOME_NETWORK = 0; 456 457 /** @hide */ 458 @SystemApi 459 public static final int PASSPOINT_ROAMING_NETWORK = 1; 460 461 /** @hide */ 462 @Retention(RetentionPolicy.SOURCE) 463 @IntDef(value = { 464 API_SCANNING_ENABLED, 465 API_WIFI_ENABLED, 466 API_SOFT_AP, 467 API_TETHERED_HOTSPOT, 468 API_AUTOJOIN_GLOBAL, 469 API_SET_SCAN_SCHEDULE, 470 API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY, 471 API_SET_NETWORK_SELECTION_CONFIG, 472 API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG, 473 API_ADD_NETWORK, 474 API_UPDATE_NETWORK, 475 API_ALLOW_AUTOJOIN, 476 API_CONNECT_CONFIG, 477 API_CONNECT_NETWORK_ID, 478 API_DISABLE_NETWORK, 479 API_ENABLE_NETWORK, 480 API_FORGET, 481 API_SAVE, 482 API_START_SCAN, 483 API_START_LOCAL_ONLY_HOTSPOT, 484 API_P2P_DISCOVER_PEERS, 485 API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS, 486 API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY, 487 API_P2P_STOP_PEER_DISCOVERY, 488 API_P2P_CONNECT, 489 API_P2P_CANCEL_CONNECT, 490 API_P2P_CREATE_GROUP, 491 API_P2P_CREATE_GROUP_P2P_CONFIG, 492 API_P2P_REMOVE_GROUP, 493 API_P2P_START_LISTENING, 494 API_P2P_STOP_LISTENING, 495 API_P2P_SET_CHANNELS, 496 API_WIFI_SCANNER_START_SCAN, 497 API_SET_TDLS_ENABLED, 498 API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS 499 }) 500 public @interface ApiType {} 501 502 /** 503 * A constant used in 504 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 505 * Tracks usage of {@link WifiScanner#setScanningEnabled(boolean)} 506 * @hide 507 */ 508 @SystemApi 509 public static final int API_SCANNING_ENABLED = 1; 510 /** 511 * A constant used in 512 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 513 * Tracks usage of {@link WifiManager#setWifiEnabled(boolean)} . 514 * @hide 515 */ 516 @SystemApi 517 public static final int API_WIFI_ENABLED = 2; 518 /** 519 * A constant used in 520 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 521 * Tracks usage of {@link WifiManager#startSoftAp(WifiConfiguration)} and 522 * {@link WifiManager#stopSoftAp()}. 523 * @hide 524 */ 525 @SystemApi 526 public static final int API_SOFT_AP = 3; 527 /** 528 * A constant used in 529 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 530 * Tracks usage of {@link WifiManager#startTetheredHotspot(SoftApConfiguration)}. 531 * @hide 532 */ 533 @SystemApi 534 public static final int API_TETHERED_HOTSPOT = 4; 535 /** 536 * A constant used in 537 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 538 * Tracks usage of {@link WifiManager#allowAutojoinGlobal(boolean)}. 539 * @hide 540 */ 541 @SystemApi 542 public static final int API_AUTOJOIN_GLOBAL = 5; 543 /** 544 * A constant used in 545 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 546 * Tracks usage of {@link WifiManager#setScreenOnScanSchedule(List)}. 547 * @hide 548 */ 549 @SystemApi 550 public static final int API_SET_SCAN_SCHEDULE = 6; 551 552 /** 553 * A constant used in 554 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 555 * Tracks usage of {@link WifiManager#setOneShotScreenOnConnectivityScanDelayMillis(int)}. 556 * @hide 557 */ 558 @SystemApi 559 public static final int API_SET_ONE_SHOT_SCREEN_ON_CONNECTIVITY_SCAN_DELAY = 7; 560 561 /** 562 * A constant used in 563 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 564 * Tracks usage of 565 * {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)} 566 * @hide 567 */ 568 @SystemApi 569 public static final int API_SET_NETWORK_SELECTION_CONFIG = 8; 570 571 /** 572 * A constant used in 573 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 574 * Tracks usage of 575 * {@link WifiManager#setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} 576 * @hide 577 */ 578 @SystemApi 579 public static final int API_SET_THIRD_PARTY_APPS_ENABLING_WIFI_CONFIRMATION_DIALOG = 9; 580 581 /** 582 * A constant used in 583 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 584 * Tracks usage of 585 * {@link WifiManager#addNetwork(WifiConfiguration)} 586 * @hide 587 */ 588 @SystemApi 589 public static final int API_ADD_NETWORK = 10; 590 591 /** 592 * A constant used in 593 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 594 * Tracks usage of 595 * {@link WifiManager#updateNetwork(WifiConfiguration)} 596 * @hide 597 */ 598 @SystemApi 599 public static final int API_UPDATE_NETWORK = 11; 600 601 /** 602 * A constant used in 603 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 604 * Tracks usage of 605 * {@link WifiManager#allowAutojoin(int, boolean)} 606 * @hide 607 */ 608 @SystemApi 609 public static final int API_ALLOW_AUTOJOIN = 12; 610 611 /** 612 * A constant used in 613 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 614 * Tracks usage of 615 * {@link WifiManager#connect(WifiConfiguration, ActionListener)} 616 * @hide 617 */ 618 @SystemApi 619 public static final int API_CONNECT_CONFIG = 13; 620 621 /** 622 * A constant used in 623 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 624 * Tracks usage of 625 * {@link WifiManager#connect(int, ActionListener)} 626 * @hide 627 */ 628 @SystemApi 629 public static final int API_CONNECT_NETWORK_ID = 14; 630 631 /** 632 * A constant used in 633 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 634 * Tracks usage of 635 * {@link WifiManager#disableNetwork(int)} 636 * @hide 637 */ 638 @SystemApi 639 public static final int API_DISABLE_NETWORK = 15; 640 641 /** 642 * A constant used in 643 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 644 * Tracks usage of 645 * {@link WifiManager#enableNetwork(int, boolean)} 646 * @hide 647 */ 648 @SystemApi 649 public static final int API_ENABLE_NETWORK = 16; 650 651 /** 652 * A constant used in 653 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 654 * Tracks usage of 655 * {@link WifiManager#forget(int, ActionListener)} 656 * @hide 657 */ 658 @SystemApi 659 public static final int API_FORGET = 17; 660 661 /** 662 * A constant used in 663 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 664 * Tracks usage of 665 * {@link WifiManager#save(WifiConfiguration, ActionListener)} 666 * @hide 667 */ 668 @SystemApi 669 public static final int API_SAVE = 18; 670 671 /** 672 * A constant used in 673 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 674 * Tracks usage of 675 * {@link WifiManager#startScan()} 676 * @hide 677 */ 678 @SystemApi 679 public static final int API_START_SCAN = 19; 680 681 /** 682 * A constant used in 683 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 684 * Tracks usage of 685 * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} 686 * @hide 687 */ 688 @SystemApi 689 public static final int API_START_LOCAL_ONLY_HOTSPOT = 20; 690 691 /** 692 * A constant used in 693 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 694 * Tracks usage of 695 * {@link WifiP2pManager#discoverPeers(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 696 * @hide 697 */ 698 @SystemApi 699 public static final int API_P2P_DISCOVER_PEERS = 21; 700 701 /** 702 * A constant used in 703 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 704 * Tracks usage of 705 * {@link WifiP2pManager#discoverPeersOnSocialChannels(WifiP2pManager.Channel, 706 * WifiP2pManager.ActionListener)} 707 * @hide 708 */ 709 @SystemApi 710 public static final int API_P2P_DISCOVER_PEERS_ON_SOCIAL_CHANNELS = 22; 711 712 /** 713 * A constant used in 714 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 715 * Tracks usage of 716 * {@link WifiP2pManager#discoverPeersOnSpecificFrequency(WifiP2pManager.Channel, int, 717 * WifiP2pManager.ActionListener)} 718 * @hide 719 */ 720 @SystemApi 721 public static final int API_P2P_DISCOVER_PEERS_ON_SPECIFIC_FREQUENCY = 23; 722 723 /** 724 * A constant used in 725 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 726 * Tracks usage of 727 * {@link WifiP2pManager#stopPeerDiscovery(WifiP2pManager.Channel, 728 * WifiP2pManager.ActionListener)} 729 * @hide 730 */ 731 @SystemApi 732 public static final int API_P2P_STOP_PEER_DISCOVERY = 24; 733 734 /** 735 * A constant used in 736 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 737 * Tracks usage of 738 * {@link WifiP2pManager#connect(WifiP2pManager.Channel, WifiP2pConfig, 739 * WifiP2pManager.ActionListener)} 740 * @hide 741 */ 742 @SystemApi 743 public static final int API_P2P_CONNECT = 25; 744 745 /** 746 * A constant used in 747 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 748 * Tracks usage of 749 * {@link WifiP2pManager#cancelConnect(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 750 * @hide 751 */ 752 @SystemApi 753 public static final int API_P2P_CANCEL_CONNECT = 26; 754 755 /** 756 * A constant used in 757 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 758 * Tracks usage of 759 * {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 760 * @hide 761 */ 762 @SystemApi 763 public static final int API_P2P_CREATE_GROUP = 27; 764 765 /** 766 * A constant used in 767 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 768 * Tracks usage of 769 * {@link WifiP2pManager#createGroup(WifiP2pManager.Channel, WifiP2pConfig, 770 * WifiP2pManager.ActionListener)} 771 * @hide 772 */ 773 @SystemApi 774 public static final int API_P2P_CREATE_GROUP_P2P_CONFIG = 28; 775 776 /** 777 * A constant used in 778 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 779 * Tracks usage of 780 * {@link WifiP2pManager#removeGroup(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 781 * @hide 782 */ 783 @SystemApi 784 public static final int API_P2P_REMOVE_GROUP = 29; 785 786 /** 787 * A constant used in 788 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 789 * Tracks usage of 790 * {@link WifiP2pManager#startListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 791 * @hide 792 */ 793 @SystemApi 794 public static final int API_P2P_START_LISTENING = 30; 795 796 /** 797 * A constant used in 798 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 799 * Tracks usage of 800 * {@link WifiP2pManager#stopListening(WifiP2pManager.Channel, WifiP2pManager.ActionListener)} 801 * @hide 802 */ 803 @SystemApi 804 public static final int API_P2P_STOP_LISTENING = 31; 805 806 /** 807 * A constant used in 808 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 809 * Tracks usage of 810 * {@link WifiP2pManager#setWifiP2pChannels(WifiP2pManager.Channel, int, int, 811 * WifiP2pManager.ActionListener)} 812 * @hide 813 */ 814 @SystemApi 815 public static final int API_P2P_SET_CHANNELS = 32; 816 817 /** 818 * A constant used in 819 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 820 * Tracks usage of 821 * {@link WifiScanner#startScan(WifiScanner.ScanSettings, WifiScanner.ScanListener)} 822 * @hide 823 */ 824 @SystemApi 825 public static final int API_WIFI_SCANNER_START_SCAN = 33; 826 827 /** 828 * A constant used in 829 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 830 * Tracks usage of 831 * {@link WifiManager#setTdlsEnabled(InetAddress, boolean)} and 832 * {@link WifiManager#setTdlsEnabled(InetAddress, boolean, Executor, Consumer)} 833 * @hide 834 */ 835 @SystemApi 836 public static final int API_SET_TDLS_ENABLED = 34; 837 838 /** 839 * A constant used in 840 * {@link WifiManager#getLastCallerInfoForApi(int, Executor, BiConsumer)} 841 * Tracks usage of 842 * {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean)} and 843 * {@link WifiManager#setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)} 844 * @hide 845 */ 846 @SystemApi 847 public static final int API_SET_TDLS_ENABLED_WITH_MAC_ADDRESS = 35; 848 849 /** 850 * Used internally to keep track of boundary. 851 * @hide 852 */ 853 public static final int API_MAX = 36; 854 855 /** 856 * Broadcast intent action indicating that a Passpoint provider icon has been received. 857 * 858 * Included extras: 859 * {@link #EXTRA_BSSID_LONG} 860 * {@link #EXTRA_FILENAME} 861 * {@link #EXTRA_ICON} 862 * 863 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 864 * 865 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 866 * components will be launched. 867 * 868 * @hide 869 */ 870 public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON"; 871 /** 872 * BSSID of an AP in long representation. The {@link #EXTRA_BSSID} contains BSSID in 873 * String representation. 874 * 875 * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}. 876 * 877 * @hide 878 */ 879 public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG"; 880 /** 881 * Icon data. 882 * 883 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into 884 * {@link android.graphics.drawable.Icon}. 885 * 886 * @hide 887 */ 888 public static final String EXTRA_ICON = "android.net.wifi.extra.ICON"; 889 /** 890 * Name of a file. 891 * 892 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 893 * 894 * @hide 895 */ 896 public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME"; 897 898 /** 899 * Broadcast intent action indicating a Passpoint OSU Providers List element has been received. 900 * 901 * Included extras: 902 * {@link #EXTRA_BSSID_LONG} 903 * {@link #EXTRA_ANQP_ELEMENT_DATA} 904 * 905 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 906 * 907 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 908 * components will be launched. 909 * 910 * @hide 911 */ 912 public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = 913 "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST"; 914 /** 915 * Raw binary data of an ANQP (Access Network Query Protocol) element. 916 * 917 * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}. 918 * 919 * @hide 920 */ 921 public static final String EXTRA_ANQP_ELEMENT_DATA = 922 "android.net.wifi.extra.ANQP_ELEMENT_DATA"; 923 924 /** 925 * Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received. 926 * 927 * Included extras: 928 * {@link #EXTRA_BSSID_LONG} 929 * {@link #EXTRA_ESS} 930 * {@link #EXTRA_DELAY} 931 * {@link #EXTRA_URL} 932 * 933 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 934 * 935 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 936 * components will be launched. 937 * 938 * @hide 939 */ 940 public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT = 941 "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT"; 942 /** 943 * Flag indicating BSS (Basic Service Set) or ESS (Extended Service Set). This will be set to 944 * {@code true} for ESS. 945 * 946 * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}. 947 * 948 * @hide 949 */ 950 public static final String EXTRA_ESS = "android.net.wifi.extra.ESS"; 951 /** 952 * Delay in seconds. 953 * 954 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 955 * 956 * @hide 957 */ 958 public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY"; 959 960 /** 961 * Broadcast intent action indicating a Passpoint subscription remediation frame has been 962 * received. 963 * 964 * Included extras: 965 * {@link #EXTRA_BSSID_LONG} 966 * {@link #EXTRA_SUBSCRIPTION_REMEDIATION_METHOD} 967 * {@link #EXTRA_URL} 968 * 969 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 970 * 971 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 972 * components will be launched. 973 * 974 * @hide 975 */ 976 public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = 977 "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION"; 978 /** 979 * The protocol supported by the subscription remediation server. The possible values are: 980 * 0 - OMA DM 981 * 1 - SOAP XML SPP 982 * 983 * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}. 984 * 985 * @hide 986 */ 987 public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = 988 "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; 989 990 /** 991 * Activity Action: Receiver should launch Passpoint OSU (Online Sign Up) view. 992 * Included extras: 993 * 994 * {@link #EXTRA_OSU_NETWORK}: {@link Network} instance associated with OSU AP. 995 * {@link #EXTRA_URL}: String representation of a server URL used for OSU process. 996 * 997 * @hide 998 */ 999 @SystemApi 1000 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1001 public static final String ACTION_PASSPOINT_LAUNCH_OSU_VIEW = 1002 "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW"; 1003 1004 /** 1005 * The lookup key for a {@link android.net.Network} associated with a Passpoint OSU server. 1006 * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast. 1007 * 1008 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 1009 * 1010 * @hide 1011 */ 1012 @SystemApi 1013 public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK"; 1014 1015 /** 1016 * String representation of an URL for Passpoint OSU. 1017 * Included in the {@link #ACTION_PASSPOINT_LAUNCH_OSU_VIEW} broadcast. 1018 * 1019 * Retrieve with {@link android.content.Intent#getStringExtra(String)}. 1020 * 1021 * @hide 1022 */ 1023 @SystemApi 1024 public static final String EXTRA_URL = "android.net.wifi.extra.URL"; 1025 1026 /** 1027 * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, 1028 * enabling, disabling, or unknown. One extra provides this state as an int. 1029 * Another extra provides the previous state, if available. No network-related 1030 * permissions are required to subscribe to this broadcast. 1031 * 1032 * <p class="note">This broadcast is not delivered to manifest receivers in 1033 * applications that target API version 26 or later. 1034 * 1035 * @see #EXTRA_WIFI_STATE 1036 * @see #EXTRA_PREVIOUS_WIFI_STATE 1037 */ 1038 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1039 public static final String WIFI_STATE_CHANGED_ACTION = 1040 "android.net.wifi.WIFI_STATE_CHANGED"; 1041 /** 1042 * The lookup key for an int that indicates whether Wi-Fi is enabled, 1043 * disabled, enabling, disabling, or unknown. Retrieve it with 1044 * {@link android.content.Intent#getIntExtra(String,int)}. 1045 * 1046 * @see #WIFI_STATE_DISABLED 1047 * @see #WIFI_STATE_DISABLING 1048 * @see #WIFI_STATE_ENABLED 1049 * @see #WIFI_STATE_ENABLING 1050 * @see #WIFI_STATE_UNKNOWN 1051 */ 1052 public static final String EXTRA_WIFI_STATE = "wifi_state"; 1053 /** 1054 * The previous Wi-Fi state. 1055 * 1056 * @see #EXTRA_WIFI_STATE 1057 */ 1058 public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state"; 1059 1060 /** 1061 * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if 1062 * it finishes successfully. 1063 * 1064 * @see #WIFI_STATE_CHANGED_ACTION 1065 * @see #getWifiState() 1066 */ 1067 public static final int WIFI_STATE_DISABLING = 0; 1068 /** 1069 * Wi-Fi is disabled. 1070 * 1071 * @see #WIFI_STATE_CHANGED_ACTION 1072 * @see #getWifiState() 1073 */ 1074 public static final int WIFI_STATE_DISABLED = 1; 1075 /** 1076 * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if 1077 * it finishes successfully. 1078 * 1079 * @see #WIFI_STATE_CHANGED_ACTION 1080 * @see #getWifiState() 1081 */ 1082 public static final int WIFI_STATE_ENABLING = 2; 1083 /** 1084 * Wi-Fi is enabled. 1085 * 1086 * @see #WIFI_STATE_CHANGED_ACTION 1087 * @see #getWifiState() 1088 */ 1089 public static final int WIFI_STATE_ENABLED = 3; 1090 /** 1091 * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling 1092 * or disabling. 1093 * 1094 * @see #WIFI_STATE_CHANGED_ACTION 1095 * @see #getWifiState() 1096 */ 1097 public static final int WIFI_STATE_UNKNOWN = 4; 1098 1099 /** 1100 * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled, 1101 * enabling, disabling, or failed. 1102 * 1103 * @hide 1104 */ 1105 @SystemApi 1106 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 1107 public static final String WIFI_AP_STATE_CHANGED_ACTION = 1108 "android.net.wifi.WIFI_AP_STATE_CHANGED"; 1109 1110 /** 1111 * The lookup key for an int that indicates whether Wi-Fi AP is enabled, 1112 * disabled, enabling, disabling, or failed. Retrieve it with 1113 * {@link android.content.Intent#getIntExtra(String,int)}. 1114 * 1115 * @see #WIFI_AP_STATE_DISABLED 1116 * @see #WIFI_AP_STATE_DISABLING 1117 * @see #WIFI_AP_STATE_ENABLED 1118 * @see #WIFI_AP_STATE_ENABLING 1119 * @see #WIFI_AP_STATE_FAILED 1120 * 1121 * @hide 1122 */ 1123 @SystemApi 1124 public static final String EXTRA_WIFI_AP_STATE = "wifi_state"; 1125 1126 /** 1127 * An extra containing the int error code for Soft AP start failure. 1128 * Can be obtained from the {@link #WIFI_AP_STATE_CHANGED_ACTION} using 1129 * {@link android.content.Intent#getIntExtra}. 1130 * This extra will only be attached if {@link #EXTRA_WIFI_AP_STATE} is 1131 * attached and is equal to {@link #WIFI_AP_STATE_FAILED}. 1132 * 1133 * The error code will be one of: 1134 * {@link #SAP_START_FAILURE_GENERAL}, 1135 * {@link #SAP_START_FAILURE_NO_CHANNEL}, 1136 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION} 1137 * {@link #SAP_START_FAILURE_USER_REJECTED} 1138 * 1139 * @hide 1140 */ 1141 @SystemApi 1142 public static final String EXTRA_WIFI_AP_FAILURE_REASON = 1143 "android.net.wifi.extra.WIFI_AP_FAILURE_REASON"; 1144 /** 1145 * The previous Wi-Fi state. 1146 * 1147 * @see #EXTRA_WIFI_AP_STATE 1148 * 1149 * @hide 1150 */ 1151 @SystemApi 1152 public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state"; 1153 /** 1154 * The lookup key for a String extra that stores the interface name used for the Soft AP. 1155 * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. 1156 * Retrieve its value with {@link android.content.Intent#getStringExtra(String)}. 1157 * 1158 * @hide 1159 */ 1160 @SystemApi 1161 public static final String EXTRA_WIFI_AP_INTERFACE_NAME = 1162 "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME"; 1163 /** 1164 * The lookup key for an int extra that stores the intended IP mode for this Soft AP. 1165 * One of {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}. 1166 * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}. 1167 * Retrieve its value with {@link android.content.Intent#getIntExtra(String, int)}. 1168 * 1169 * @hide 1170 */ 1171 @SystemApi 1172 public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE"; 1173 1174 /** @hide */ 1175 @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = { 1176 WIFI_AP_STATE_DISABLING, 1177 WIFI_AP_STATE_DISABLED, 1178 WIFI_AP_STATE_ENABLING, 1179 WIFI_AP_STATE_ENABLED, 1180 WIFI_AP_STATE_FAILED, 1181 }) 1182 @Retention(RetentionPolicy.SOURCE) 1183 public @interface WifiApState {} 1184 1185 /** 1186 * Wi-Fi AP is currently being disabled. The state will change to 1187 * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully. 1188 * 1189 * @see #WIFI_AP_STATE_CHANGED_ACTION 1190 * @see #getWifiApState() 1191 * 1192 * @hide 1193 */ 1194 @SystemApi 1195 public static final int WIFI_AP_STATE_DISABLING = 10; 1196 /** 1197 * Wi-Fi AP is disabled. 1198 * 1199 * @see #WIFI_AP_STATE_CHANGED_ACTION 1200 * @see #getWifiState() 1201 * 1202 * @hide 1203 */ 1204 @SystemApi 1205 public static final int WIFI_AP_STATE_DISABLED = 11; 1206 /** 1207 * Wi-Fi AP is currently being enabled. The state will change to 1208 * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully. 1209 * 1210 * @see #WIFI_AP_STATE_CHANGED_ACTION 1211 * @see #getWifiApState() 1212 * 1213 * @hide 1214 */ 1215 @SystemApi 1216 public static final int WIFI_AP_STATE_ENABLING = 12; 1217 /** 1218 * Wi-Fi AP is enabled. 1219 * 1220 * @see #WIFI_AP_STATE_CHANGED_ACTION 1221 * @see #getWifiApState() 1222 * 1223 * @hide 1224 */ 1225 @SystemApi 1226 public static final int WIFI_AP_STATE_ENABLED = 13; 1227 /** 1228 * Wi-Fi AP is in a failed state. This state will occur when an error occurs during 1229 * enabling or disabling 1230 * 1231 * @see #WIFI_AP_STATE_CHANGED_ACTION 1232 * @see #getWifiApState() 1233 * 1234 * @hide 1235 */ 1236 @SystemApi 1237 public static final int WIFI_AP_STATE_FAILED = 14; 1238 1239 /** @hide */ 1240 @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = { 1241 SAP_START_FAILURE_GENERAL, 1242 SAP_START_FAILURE_NO_CHANNEL, 1243 SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION, 1244 SAP_START_FAILURE_USER_REJECTED, 1245 }) 1246 @Retention(RetentionPolicy.SOURCE) 1247 public @interface SapStartFailure {} 1248 1249 /** 1250 * All other reasons for AP start failure besides {@link #SAP_START_FAILURE_NO_CHANNEL}, 1251 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}, and 1252 * {@link #SAP_START_FAILURE_USER_REJECTED}. 1253 * 1254 * @hide 1255 */ 1256 @SystemApi 1257 public static final int SAP_START_FAILURE_GENERAL= 0; 1258 1259 /** 1260 * If Wi-Fi AP start failed, this reason code means that no legal channel exists on user 1261 * selected band due to regulatory constraints. 1262 * 1263 * @hide 1264 */ 1265 @SystemApi 1266 public static final int SAP_START_FAILURE_NO_CHANNEL = 1; 1267 1268 /** 1269 * If Wi-Fi AP start failed, this reason code means that the specified configuration 1270 * is not supported by the current HAL version. 1271 * 1272 * @hide 1273 */ 1274 @SystemApi 1275 public static final int SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION = 2; 1276 1277 /** 1278 * If Wi-Fi AP start failed, this reason code means that the user was asked for confirmation to 1279 * create the AP and the user declined. 1280 * 1281 * @hide 1282 */ 1283 @SystemApi 1284 public static final int SAP_START_FAILURE_USER_REJECTED = 3; 1285 1286 /** @hide */ 1287 @IntDef(flag = false, prefix = { "SAP_CLIENT_BLOCKED_REASON_" }, value = { 1288 SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER, 1289 SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS, 1290 }) 1291 @Retention(RetentionPolicy.SOURCE) 1292 public @interface SapClientBlockedReason {} 1293 1294 /** 1295 * If Soft Ap client is blocked, this reason code means that client doesn't exist in the 1296 * specified configuration {@link SoftApConfiguration.Builder#setBlockedClientList(List)} 1297 * and {@link SoftApConfiguration.Builder#setAllowedClientList(List)} 1298 * and the {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)} 1299 * is configured as well. 1300 * @hide 1301 */ 1302 @SystemApi 1303 public static final int SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER = 0; 1304 1305 /** 1306 * If Soft Ap client is blocked, this reason code means that no more clients can be 1307 * associated to this AP since it reached maximum capacity. The maximum capacity is 1308 * the minimum of {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} and 1309 * {@link SoftApCapability#getMaxSupportedClients} which get from 1310 * {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)}. 1311 * 1312 * @hide 1313 */ 1314 @SystemApi 1315 public static final int SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS = 1; 1316 1317 /** 1318 * Client disconnected for unspecified reason. This could for example be because the AP is being 1319 * shut down. 1320 * @hide 1321 */ 1322 public static final int SAP_CLIENT_DISCONNECT_REASON_CODE_UNSPECIFIED = 2; 1323 1324 /** @hide */ 1325 @Retention(RetentionPolicy.SOURCE) 1326 @IntDef(prefix = {"IFACE_IP_MODE_"}, value = { 1327 IFACE_IP_MODE_UNSPECIFIED, 1328 IFACE_IP_MODE_CONFIGURATION_ERROR, 1329 IFACE_IP_MODE_TETHERED, 1330 IFACE_IP_MODE_LOCAL_ONLY}) 1331 public @interface IfaceIpMode {} 1332 1333 /** 1334 * Interface IP mode unspecified. 1335 * 1336 * @see #updateInterfaceIpState(String, int) 1337 * 1338 * @hide 1339 */ 1340 @SystemApi 1341 public static final int IFACE_IP_MODE_UNSPECIFIED = -1; 1342 1343 /** 1344 * Interface IP mode for configuration error. 1345 * 1346 * @see #updateInterfaceIpState(String, int) 1347 * 1348 * @hide 1349 */ 1350 @SystemApi 1351 public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; 1352 1353 /** 1354 * Interface IP mode for tethering. 1355 * 1356 * @see #updateInterfaceIpState(String, int) 1357 * 1358 * @hide 1359 */ 1360 @SystemApi 1361 public static final int IFACE_IP_MODE_TETHERED = 1; 1362 1363 /** 1364 * Interface IP mode for Local Only Hotspot. 1365 * 1366 * @see #updateInterfaceIpState(String, int) 1367 * 1368 * @hide 1369 */ 1370 @SystemApi 1371 public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; 1372 1373 /** 1374 * Broadcast intent action indicating that the wifi network settings 1375 * had been reset. 1376 * 1377 * Note: This intent is sent as a directed broadcast to each manifest registered receiver. 1378 * Intent will not be received by dynamically registered receivers. 1379 * @hide 1380 */ 1381 @SystemApi 1382 @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) 1383 public static final String ACTION_NETWORK_SETTINGS_RESET = 1384 "android.net.wifi.action.NETWORK_SETTINGS_RESET"; 1385 1386 /** 1387 * Broadcast intent action indicating that the wifi network profiles provisioned 1388 * may need refresh. 1389 * 1390 * Note: This intent is sent as a directed broadcast to each manifest registered receiver; 1391 * And restricted to those apps which have the NETWORK_CARRIER_PROVISIONING permission. 1392 * Intent will not be received by dynamically registered receivers. 1393 * @hide 1394 */ 1395 @SystemApi 1396 @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) 1397 public static final String ACTION_REFRESH_USER_PROVISIONING = 1398 "android.net.wifi.action.REFRESH_USER_PROVISIONING"; 1399 1400 /** 1401 * Broadcast intent action indicating that a connection to the supplicant has 1402 * been established (and it is now possible 1403 * to perform Wi-Fi operations) or the connection to the supplicant has been 1404 * lost. One extra provides the connection state as a boolean, where {@code true} 1405 * means CONNECTED. 1406 * @deprecated This is no longer supported. 1407 * @see #EXTRA_SUPPLICANT_CONNECTED 1408 */ 1409 @Deprecated 1410 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1411 public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = 1412 "android.net.wifi.supplicant.CONNECTION_CHANGE"; 1413 /** 1414 * The lookup key for a boolean that indicates whether a connection to 1415 * the supplicant daemon has been gained or lost. {@code true} means 1416 * a connection now exists. 1417 * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. 1418 * @deprecated This is no longer supported. 1419 */ 1420 @Deprecated 1421 public static final String EXTRA_SUPPLICANT_CONNECTED = "connected"; 1422 /** 1423 * Broadcast intent action indicating that the state of Wi-Fi connectivity 1424 * has changed. An extra provides the new state 1425 * in the form of a {@link android.net.NetworkInfo} object. No network-related 1426 * permissions are required to subscribe to this broadcast. 1427 * 1428 * <p class="note">This broadcast is not delivered to manifest receivers in 1429 * applications that target API version 26 or later. 1430 * @see #EXTRA_NETWORK_INFO 1431 */ 1432 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1433 public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE"; 1434 /** 1435 * The lookup key for a {@link android.net.NetworkInfo} object associated with the 1436 * Wi-Fi network. Retrieve with 1437 * {@link android.content.Intent#getParcelableExtra(String)}. 1438 */ 1439 public static final String EXTRA_NETWORK_INFO = "networkInfo"; 1440 /** 1441 * The lookup key for a String giving the BSSID of the access point to which 1442 * we are connected. No longer used. 1443 */ 1444 @Deprecated 1445 public static final String EXTRA_BSSID = "bssid"; 1446 /** 1447 * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the 1448 * information about the access point to which we are connected. 1449 * No longer used. 1450 */ 1451 @Deprecated 1452 public static final String EXTRA_WIFI_INFO = "wifiInfo"; 1453 /** 1454 * Broadcast intent action indicating that the state of establishing a connection to 1455 * an access point has changed.One extra provides the new 1456 * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and 1457 * is not generally the most useful thing to look at if you are just interested in 1458 * the overall state of connectivity. 1459 * @see #EXTRA_NEW_STATE 1460 * @see #EXTRA_SUPPLICANT_ERROR 1461 * @deprecated This is no longer supported. 1462 */ 1463 @Deprecated 1464 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1465 public static final String SUPPLICANT_STATE_CHANGED_ACTION = 1466 "android.net.wifi.supplicant.STATE_CHANGE"; 1467 /** 1468 * The lookup key for a {@link SupplicantState} describing the new state 1469 * Retrieve with 1470 * {@link android.content.Intent#getParcelableExtra(String)}. 1471 * @deprecated This is no longer supported. 1472 */ 1473 @Deprecated 1474 public static final String EXTRA_NEW_STATE = "newState"; 1475 1476 /** 1477 * The lookup key for a {@link SupplicantState} describing the supplicant 1478 * error code if any 1479 * Retrieve with 1480 * {@link android.content.Intent#getIntExtra(String, int)}. 1481 * @see #ERROR_AUTHENTICATING 1482 * @deprecated This is no longer supported. 1483 */ 1484 @Deprecated 1485 public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; 1486 1487 /** 1488 * The lookup key for a {@link SupplicantState} describing the supplicant 1489 * error reason if any 1490 * Retrieve with 1491 * {@link android.content.Intent#getIntExtra(String, int)}. 1492 * @see #ERROR_AUTH_FAILURE_#REASON_CODE 1493 * @deprecated This is no longer supported. 1494 * @hide 1495 */ 1496 @Deprecated 1497 public static final String EXTRA_SUPPLICANT_ERROR_REASON = "supplicantErrorReason"; 1498 1499 /** 1500 * Broadcast intent action indicating that the configured networks changed. 1501 * This can be as a result of adding/updating/deleting a network. 1502 * <br /> 1503 * {@link #EXTRA_CHANGE_REASON} contains whether the configuration was added/changed/removed. 1504 * {@link #EXTRA_WIFI_CONFIGURATION} is never set beginning in 1505 * {@link android.os.Build.VERSION_CODES#R}. 1506 * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set for backwards compatibility reasons, but 1507 * its value is always true beginning in {@link android.os.Build.VERSION_CODES#R}, even if only 1508 * a single network changed. 1509 * <br /> 1510 * The {@link android.Manifest.permission#ACCESS_WIFI_STATE ACCESS_WIFI_STATE} permission is 1511 * required to receive this broadcast. 1512 * 1513 * @hide 1514 */ 1515 @SystemApi 1516 public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = 1517 "android.net.wifi.CONFIGURED_NETWORKS_CHANGE"; 1518 /** 1519 * The lookup key for a {@link android.net.wifi.WifiConfiguration} object representing 1520 * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION} 1521 * broadcast is sent. 1522 * @deprecated This extra is never set beginning in {@link android.os.Build.VERSION_CODES#R}, 1523 * regardless of the target SDK version. Use {@link #getConfiguredNetworks} to get the full list 1524 * of configured networks. 1525 * @hide 1526 */ 1527 @Deprecated 1528 @SystemApi 1529 public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; 1530 /** 1531 * Multiple network configurations have changed. 1532 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 1533 * @deprecated This extra's value is always true beginning in 1534 * {@link android.os.Build.VERSION_CODES#R}, regardless of the target SDK version. 1535 * @hide 1536 */ 1537 @Deprecated 1538 @SystemApi 1539 public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges"; 1540 /** 1541 * The lookup key for an integer indicating the reason a Wi-Fi network configuration 1542 * has changed. One of {@link #CHANGE_REASON_ADDED}, {@link #CHANGE_REASON_REMOVED}, 1543 * {@link #CHANGE_REASON_CONFIG_CHANGE}. 1544 * 1545 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION 1546 * @hide 1547 */ 1548 @SystemApi 1549 public static final String EXTRA_CHANGE_REASON = "changeReason"; 1550 /** 1551 * The configuration is new and was added. 1552 * @hide 1553 */ 1554 @SystemApi 1555 public static final int CHANGE_REASON_ADDED = 0; 1556 /** 1557 * The configuration was removed and is no longer present in the system's list of 1558 * configured networks. 1559 * @hide 1560 */ 1561 @SystemApi 1562 public static final int CHANGE_REASON_REMOVED = 1; 1563 /** 1564 * The configuration has changed as a result of explicit action or because the system 1565 * took an automated action such as disabling a malfunctioning configuration. 1566 * @hide 1567 */ 1568 @SystemApi 1569 public static final int CHANGE_REASON_CONFIG_CHANGE = 2; 1570 /** 1571 * An access point scan has completed, and results are available. 1572 * Call {@link #getScanResults()} to obtain the results. 1573 * The broadcast intent may contain an extra field with the key {@link #EXTRA_RESULTS_UPDATED} 1574 * and a {@code boolean} value indicating if the scan was successful. 1575 */ 1576 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1577 public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS"; 1578 1579 /** 1580 * Lookup key for a {@code boolean} extra in intent {@link #SCAN_RESULTS_AVAILABLE_ACTION} 1581 * representing if the scan was successful or not. 1582 * Scans may fail for multiple reasons, these may include: 1583 * <ol> 1584 * <li>An app requested too many scans in a certain period of time. 1585 * This may lead to additional scan request rejections via "scan throttling" for both 1586 * foreground and background apps. 1587 * Note: Apps holding android.Manifest.permission.NETWORK_SETTINGS permission are 1588 * exempted from scan throttling. 1589 * </li> 1590 * <li>The device is idle and scanning is disabled.</li> 1591 * <li>Wifi hardware reported a scan failure.</li> 1592 * </ol> 1593 * @return true scan was successful, results are updated 1594 * @return false scan was not successful, results haven't been updated since previous scan 1595 */ 1596 public static final String EXTRA_RESULTS_UPDATED = "resultsUpdated"; 1597 1598 /** 1599 * A batch of access point scans has been completed and the results areavailable. 1600 * Call {@link #getBatchedScanResults()} to obtain the results. 1601 * @deprecated This API is nolonger supported. 1602 * Use {@link WifiScanner} API 1603 * @hide 1604 */ 1605 @Deprecated 1606 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1607 public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION = 1608 "android.net.wifi.BATCHED_RESULTS"; 1609 1610 /** 1611 * The RSSI (signal strength) has changed. 1612 * 1613 * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE 1614 * @see #EXTRA_NEW_RSSI 1615 */ 1616 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1617 public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; 1618 /** 1619 * The lookup key for an {@code int} giving the new RSSI in dBm. 1620 */ 1621 public static final String EXTRA_NEW_RSSI = "newRssi"; 1622 1623 /** 1624 * @see #ACTION_LINK_CONFIGURATION_CHANGED 1625 * @hide 1626 */ 1627 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1628 public static final String LINK_CONFIGURATION_CHANGED_ACTION = 1629 "android.net.wifi.LINK_CONFIGURATION_CHANGED"; 1630 1631 /** 1632 * Broadcast intent action indicating that the link configuration changed on wifi. 1633 * <br /> No permissions are required to listen to this broadcast. 1634 * @hide 1635 */ 1636 @SystemApi 1637 public static final String ACTION_LINK_CONFIGURATION_CHANGED = 1638 // should be android.net.wifi.action.LINK_CONFIGURATION_CHANGED, but due to 1639 // @UnsupportedAppUsage leaving it as android.net.wifi.LINK_CONFIGURATION_CHANGED. 1640 LINK_CONFIGURATION_CHANGED_ACTION; 1641 1642 /** 1643 * The lookup key for a {@link android.net.LinkProperties} object associated with the 1644 * Wi-Fi network. 1645 * Included in the {@link #ACTION_LINK_CONFIGURATION_CHANGED} broadcast. 1646 * 1647 * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. 1648 * 1649 * @deprecated this extra is no longer populated. 1650 * 1651 * @hide 1652 */ 1653 @Deprecated 1654 @SystemApi 1655 public static final String EXTRA_LINK_PROPERTIES = "android.net.wifi.extra.LINK_PROPERTIES"; 1656 1657 /** 1658 * The lookup key for a {@link android.net.NetworkCapabilities} object associated with the 1659 * Wi-Fi network. Retrieve with 1660 * {@link android.content.Intent#getParcelableExtra(String)}. 1661 * @hide 1662 */ 1663 public static final String EXTRA_NETWORK_CAPABILITIES = "networkCapabilities"; 1664 1665 /** 1666 * The network IDs of the configured networks could have changed. 1667 */ 1668 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1669 public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; 1670 1671 /** 1672 * Activity Action: Show a system activity that allows the user to enable 1673 * scans to be available even with Wi-Fi turned off. 1674 * 1675 * <p>Notification of the result of this activity is posted using the 1676 * {@link android.app.Activity#onActivityResult} callback. The 1677 * <code>resultCode</code> 1678 * will be {@link android.app.Activity#RESULT_OK} if scan always mode has 1679 * been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user 1680 * has rejected the request or an error has occurred. 1681 */ 1682 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1683 public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = 1684 "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE"; 1685 1686 /** 1687 * Activity Action: Pick a Wi-Fi network to connect to. 1688 * <p>Input: Nothing. 1689 * <p>Output: Nothing. 1690 */ 1691 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1692 public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; 1693 1694 /** 1695 * Activity Action: Receiver should show UI to get user approval to enable WiFi. 1696 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 1697 * the name of the app requesting the action. 1698 * <p>Output: Nothing. 1699 * <p>No permissions are required to send this action. 1700 * @hide 1701 */ 1702 @SystemApi 1703 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1704 public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE"; 1705 1706 /** 1707 * Activity Action: Receiver should show UI to get user approval to disable WiFi. 1708 * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with 1709 * the name of the app requesting the action. 1710 * <p>Output: Nothing. 1711 * <p>No permissions are required to send this action. 1712 * @hide 1713 */ 1714 @SystemApi 1715 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1716 public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; 1717 1718 /** 1719 * Directed broadcast intent action indicating that the device has connected to one of the 1720 * network suggestions provided by the app. This will be sent post connection to a network 1721 * which was created with {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired( 1722 * boolean)} 1723 * flag set. 1724 * <p> 1725 * Note: The broadcast is sent to the app only if it holds 1726 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission. 1727 * 1728 * @see #EXTRA_NETWORK_SUGGESTION 1729 */ 1730 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1731 public static final String ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION = 1732 "android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION"; 1733 /** 1734 * Sent as as a part of {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} that holds 1735 * an instance of {@link WifiNetworkSuggestion} corresponding to the connected network. 1736 */ 1737 public static final String EXTRA_NETWORK_SUGGESTION = 1738 "android.net.wifi.extra.NETWORK_SUGGESTION"; 1739 1740 /** 1741 * Internally used Wi-Fi lock mode representing the case were no locks are held. 1742 * @hide 1743 */ 1744 public static final int WIFI_MODE_NO_LOCKS_HELD = 0; 1745 1746 /** 1747 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 1748 * and will behave normally, i.e., it will attempt to automatically 1749 * establish a connection to a remembered access point that is 1750 * within range, and will do periodic scans if there are remembered 1751 * access points but none are in range. 1752 * 1753 * @deprecated This API is non-functional and will have no impact. 1754 */ 1755 @Deprecated 1756 public static final int WIFI_MODE_FULL = 1; 1757 1758 /** 1759 * In this Wi-Fi lock mode, Wi-Fi will be kept active, 1760 * but the only operation that will be supported is initiation of 1761 * scans, and the subsequent reporting of scan results. No attempts 1762 * will be made to automatically connect to remembered access points, 1763 * nor will periodic scans be automatically performed looking for 1764 * remembered access points. Scans must be explicitly requested by 1765 * an application in this mode. 1766 * 1767 * @deprecated This API is non-functional and will have no impact. 1768 */ 1769 @Deprecated 1770 public static final int WIFI_MODE_SCAN_ONLY = 2; 1771 1772 /** 1773 * In this Wi-Fi lock mode, Wi-Fi will not go to power save. 1774 * This results in operating with low packet latency. 1775 * The lock is only active when the device is connected to an access point. 1776 * The lock is active even when the device screen is off or the acquiring application is 1777 * running in the background. 1778 * This mode will consume more power and hence should be used only 1779 * when there is a need for this tradeoff. 1780 * <p> 1781 * An example use case is when a voice connection needs to be 1782 * kept active even after the device screen goes off. 1783 * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the 1784 * duration of the voice call may improve the call quality. 1785 * <p> 1786 * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_HIGH_PERF} 1787 * lock will have no impact. 1788 * 1789 * @deprecated The {@code WIFI_MODE_FULL_HIGH_PERF} is deprecated and is automatically replaced 1790 * with {@link #WIFI_MODE_FULL_LOW_LATENCY} with all the restrictions documented on that lock. 1791 * I.e. any request to the {@code WIFI_MODE_FULL_HIGH_PERF} will now obtain a 1792 * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock instead. 1793 * Deprecation is due to the impact of {@code WIFI_MODE_FULL_HIGH_PERF} on power dissipation. 1794 * The {@link #WIFI_MODE_FULL_LOW_LATENCY} provides much of the same desired functionality with 1795 * less impact on power dissipation. 1796 */ 1797 @Deprecated 1798 public static final int WIFI_MODE_FULL_HIGH_PERF = 3; 1799 1800 /** 1801 * In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency. 1802 * {@link #WIFI_MODE_FULL_LOW_LATENCY} lock has the following limitations: 1803 * <ol> 1804 * <li>The lock is only active when the device is connected to an access point.</li> 1805 * <li>The lock is only active when the screen is on.</li> 1806 * <li>The lock is only active when the acquiring app is running in the foreground.</li> 1807 * </ol> 1808 * Low latency mode optimizes for reduced packet latency, 1809 * and as a result other performance measures may suffer when there are trade-offs to make: 1810 * <ol> 1811 * <li>Battery life may be reduced.</li> 1812 * <li>Throughput may be reduced.</li> 1813 * <li>Frequency of Wi-Fi scanning may be reduced. This may result in: </li> 1814 * <ul> 1815 * <li>The device may not roam or switch to the AP with highest signal quality.</li> 1816 * <li>Location accuracy may be reduced.</li> 1817 * </ul> 1818 * </ol> 1819 * <p> 1820 * Example use cases are real time gaming or virtual reality applications where 1821 * low latency is a key factor for user experience. 1822 * <p> 1823 * Note: For an app which acquires both {@link #WIFI_MODE_FULL_LOW_LATENCY} and 1824 * {@link #WIFI_MODE_FULL_HIGH_PERF} locks, {@link #WIFI_MODE_FULL_LOW_LATENCY} 1825 * lock will be effective when app is running in foreground and screen is on, 1826 * while the {@link #WIFI_MODE_FULL_HIGH_PERF} lock will take effect otherwise. 1827 */ 1828 public static final int WIFI_MODE_FULL_LOW_LATENCY = 4; 1829 1830 1831 /** Anything worse than or equal to this will show 0 bars. */ 1832 @UnsupportedAppUsage 1833 private static final int MIN_RSSI = -100; 1834 1835 /** Anything better than or equal to this will show the max bars. */ 1836 @UnsupportedAppUsage 1837 private static final int MAX_RSSI = -55; 1838 1839 /** 1840 * Number of RSSI levels used in the framework to initiate {@link #RSSI_CHANGED_ACTION} 1841 * broadcast, where each level corresponds to a range of RSSI values. 1842 * The {@link #RSSI_CHANGED_ACTION} broadcast will only fire if the RSSI 1843 * change is significant enough to change the RSSI signal level. 1844 * @hide 1845 */ 1846 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1847 public static final int RSSI_LEVELS = 5; 1848 1849 //TODO (b/146346676): This needs to be removed, not used in the code. 1850 /** 1851 * Auto settings in the driver. The driver could choose to operate on both 1852 * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band. 1853 * @hide 1854 */ 1855 @UnsupportedAppUsage 1856 public static final int WIFI_FREQUENCY_BAND_AUTO = 0; 1857 1858 /** 1859 * Operation on 5 GHz alone 1860 * @hide 1861 */ 1862 @UnsupportedAppUsage 1863 public static final int WIFI_FREQUENCY_BAND_5GHZ = 1; 1864 1865 /** 1866 * Operation on 2.4 GHz alone 1867 * @hide 1868 */ 1869 @UnsupportedAppUsage 1870 public static final int WIFI_FREQUENCY_BAND_2GHZ = 2; 1871 1872 /** @hide */ 1873 public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false; 1874 1875 /** 1876 * Maximum number of active locks we allow. 1877 * This limit was added to prevent apps from creating a ridiculous number 1878 * of locks and crashing the system by overflowing the global ref table. 1879 */ 1880 private static final int MAX_ACTIVE_LOCKS = 50; 1881 1882 /** Indicates an invalid SSID. */ 1883 public static final String UNKNOWN_SSID = "<unknown ssid>"; 1884 1885 /** @hide */ 1886 public static final MacAddress ALL_ZEROS_MAC_ADDRESS = 1887 MacAddress.fromString("00:00:00:00:00:00"); 1888 1889 /** @hide */ 1890 @IntDef(flag = false, prefix = { "WIFI_MULTI_INTERNET_MODE_" }, value = { 1891 WIFI_MULTI_INTERNET_MODE_DISABLED, 1892 WIFI_MULTI_INTERNET_MODE_DBS_AP, 1893 WIFI_MULTI_INTERNET_MODE_MULTI_AP, 1894 }) 1895 @Retention(RetentionPolicy.SOURCE) 1896 public @interface WifiMultiInternetMode {} 1897 1898 /** 1899 * Wi-Fi simultaneous connection to multiple internet-providing Wi-Fi networks (APs) is 1900 * disabled. 1901 * 1902 * @see #getStaConcurrencyForMultiInternetMode() 1903 * 1904 */ 1905 public static final int WIFI_MULTI_INTERNET_MODE_DISABLED = 0; 1906 /** 1907 * Wi-Fi simultaneous connection to multiple internet-providing Wi-FI networks (APs) is enabled 1908 * and restricted to a single network on different bands (e.g. a DBS AP). 1909 * 1910 * @see #getStaConcurrencyForMultiInternetMode() 1911 * 1912 */ 1913 public static final int WIFI_MULTI_INTERNET_MODE_DBS_AP = 1; 1914 /** 1915 * Wi-Fi simultaneous connection to multiple internet-providing Wi-Fi networks (APs) is enabled. 1916 * The device can connect to any networks/APs - it is just restricted to using different bands 1917 * for individual connections. 1918 * 1919 * @see #getStaConcurrencyForMultiInternetMode() 1920 * 1921 */ 1922 public static final int WIFI_MULTI_INTERNET_MODE_MULTI_AP = 2; 1923 1924 /** 1925 * The bundle key string for the channel frequency in MHz. 1926 * See {@link #getChannelData(Executor, Consumer)} 1927 */ 1928 public static final String CHANNEL_DATA_KEY_FREQUENCY_MHZ = "CHANNEL_DATA_KEY_FREQUENCY_MHZ"; 1929 /** 1930 * The bundle key for the number of APs found on the corresponding channel specified by 1931 * {@link WifiManager#CHANNEL_DATA_KEY_FREQUENCY_MHZ}. 1932 * See {@link #getChannelData(Executor, Consumer)} 1933 */ 1934 public static final String CHANNEL_DATA_KEY_NUM_AP = "CHANNEL_DATA_KEY_NUM_AP"; 1935 1936 /** 1937 * This policy is being tracked by the Wifi service. 1938 * Indicates success for {@link #addQosPolicies(List, Executor, Consumer)}. 1939 * @hide 1940 */ 1941 @SystemApi 1942 public static final int QOS_REQUEST_STATUS_TRACKING = 0; 1943 1944 /** 1945 * A policy with the same policy ID is already being tracked. 1946 * @hide 1947 */ 1948 @SystemApi 1949 public static final int QOS_REQUEST_STATUS_ALREADY_ACTIVE = 1; 1950 1951 /** 1952 * There are insufficient resources to handle this request at this time. 1953 * @hide 1954 */ 1955 @SystemApi 1956 public static final int QOS_REQUEST_STATUS_INSUFFICIENT_RESOURCES = 2; 1957 1958 /** 1959 * The parameters in the policy request are invalid. 1960 * @hide 1961 */ 1962 @SystemApi 1963 public static final int QOS_REQUEST_STATUS_INVALID_PARAMETERS = 3; 1964 1965 /** 1966 * An unspecified failure occurred while processing this request. 1967 * @hide 1968 */ 1969 @SystemApi 1970 public static final int QOS_REQUEST_STATUS_FAILURE_UNKNOWN = 4; 1971 1972 /** @hide */ 1973 @Retention(RetentionPolicy.SOURCE) 1974 @IntDef(prefix = {"QOS_REQUEST_STATUS_"}, value = { 1975 QOS_REQUEST_STATUS_TRACKING, 1976 QOS_REQUEST_STATUS_ALREADY_ACTIVE, 1977 QOS_REQUEST_STATUS_INSUFFICIENT_RESOURCES, 1978 QOS_REQUEST_STATUS_INVALID_PARAMETERS, 1979 QOS_REQUEST_STATUS_FAILURE_UNKNOWN}) 1980 public @interface QosRequestStatus {} 1981 1982 /** 1983 * Maximum number of policies that can be included in a QoS add/remove request. 1984 */ 1985 private static final int MAX_POLICIES_PER_QOS_REQUEST = 16; 1986 1987 /** 1988 * Get the maximum number of policies that can be included in a request to 1989 * {@link #addQosPolicies(List, Executor, Consumer)} or {@link #removeQosPolicies(int[])}. 1990 * @hide 1991 */ 1992 @SystemApi getMaxNumberOfPoliciesPerQosRequest()1993 public static int getMaxNumberOfPoliciesPerQosRequest() { 1994 return MAX_POLICIES_PER_QOS_REQUEST; 1995 } 1996 1997 /* Number of currently active WifiLocks and MulticastLocks */ 1998 @UnsupportedAppUsage 1999 private int mActiveLockCount; 2000 2001 private Context mContext; 2002 @UnsupportedAppUsage 2003 IWifiManager mService; 2004 private final int mTargetSdkVersion; 2005 2006 private Looper mLooper; 2007 private boolean mVerboseLoggingEnabled = false; 2008 2009 private final Object mLock = new Object(); // lock guarding access to the following vars 2010 @GuardedBy("mLock") 2011 private LocalOnlyHotspotCallbackProxy mLOHSCallbackProxy; 2012 @GuardedBy("mLock") 2013 private LocalOnlyHotspotObserverProxy mLOHSObserverProxy; 2014 2015 private static final SparseArray<IOnWifiUsabilityStatsListener> 2016 sOnWifiUsabilityStatsListenerMap = new SparseArray(); 2017 private static final SparseArray<ISuggestionConnectionStatusListener> 2018 sSuggestionConnectionStatusListenerMap = new SparseArray(); 2019 private static final SparseArray<ISuggestionUserApprovalStatusListener> 2020 sSuggestionUserApprovalStatusListenerMap = new SparseArray(); 2021 private static final SparseArray<IWifiVerboseLoggingStatusChangedListener> 2022 sWifiVerboseLoggingStatusChangedListenerMap = new SparseArray(); 2023 private static final SparseArray<INetworkRequestMatchCallback> 2024 sNetworkRequestMatchCallbackMap = new SparseArray(); 2025 private static final SparseArray<ITrafficStateCallback> 2026 sTrafficStateCallbackMap = new SparseArray(); 2027 private static final SparseArray<ISoftApCallback> sSoftApCallbackMap = new SparseArray(); 2028 private static final SparseArray<IOnWifiDriverCountryCodeChangedListener> 2029 sActiveCountryCodeChangedCallbackMap = new SparseArray(); 2030 private static final SparseArray<ISoftApCallback> 2031 sLocalOnlyHotspotSoftApCallbackMap = new SparseArray(); 2032 private static final SparseArray<ILocalOnlyConnectionStatusListener> 2033 sLocalOnlyConnectionStatusListenerMap = new SparseArray(); 2034 private static final SparseArray<IWifiNetworkStateChangedListener> 2035 sOnWifiNetworkStateChangedListenerMap = new SparseArray<>(); 2036 private static final SparseArray<IWifiLowLatencyLockListener> 2037 sWifiLowLatencyLockListenerMap = new SparseArray<>(); 2038 2039 /** 2040 * Multi-link operation (MLO) will allow Wi-Fi devices to operate on multiple links at the same 2041 * time through a single connection, aiming to support applications that require lower latency, 2042 * and higher capacity. Chip vendors have algorithms that run on the chip to use available links 2043 * based on incoming traffic and various inputs. Below is a list of Multi-Link Operation modes 2044 * that applications can suggest to be accommodated in the algorithm. 2045 * 2046 * The default MLO mode is for chip vendors to use algorithms to select the optimum links to 2047 * operate on, without any guidance from the calling app. 2048 * 2049 * @hide 2050 */ 2051 @SystemApi 2052 public static final int MLO_MODE_DEFAULT = 0; 2053 2054 /** 2055 * Low latency mode for Multi-link operation. In this mode, the chip vendor's algorithm 2056 * should select MLO links that will achieve low latency. 2057 * 2058 * @hide 2059 */ 2060 @SystemApi 2061 public static final int MLO_MODE_LOW_LATENCY = 1; 2062 2063 /** 2064 * High throughput mode for Multi-link operation. In this mode, the chip vendor's algorithm 2065 * should select MLO links that will achieve higher throughput. 2066 * 2067 * @hide 2068 */ 2069 @SystemApi 2070 public static final int MLO_MODE_HIGH_THROUGHPUT = 2; 2071 2072 /** 2073 * Low power mode for Multi-link operation. In this mode, the chip vendor's algorithm 2074 * should select MLO links that will achieve low power. 2075 * 2076 * @hide 2077 */ 2078 @SystemApi 2079 public static final int MLO_MODE_LOW_POWER = 3; 2080 2081 /** @hide */ 2082 @Retention(RetentionPolicy.SOURCE) 2083 @IntDef(prefix = {"MLO_MODE_"}, value = { 2084 MLO_MODE_DEFAULT, 2085 MLO_MODE_LOW_LATENCY, 2086 MLO_MODE_HIGH_THROUGHPUT, 2087 MLO_MODE_LOW_POWER}) 2088 public @interface MloMode { 2089 } 2090 2091 /** 2092 * Create a new WifiManager instance. 2093 * Applications will almost always want to use 2094 * {@link android.content.Context#getSystemService Context.getSystemService} to retrieve 2095 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}. 2096 * 2097 * @param context the application context 2098 * @param service the Binder interface 2099 * @param looper the Looper used to deliver callbacks 2100 * @hide - hide this because it takes in a parameter of type IWifiManager, which 2101 * is a system private class. 2102 */ WifiManager(@onNull Context context, @NonNull IWifiManager service, @NonNull Looper looper)2103 public WifiManager(@NonNull Context context, @NonNull IWifiManager service, 2104 @NonNull Looper looper) { 2105 mContext = context; 2106 mService = service; 2107 mLooper = looper; 2108 mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; 2109 updateVerboseLoggingEnabledFromService(); 2110 } 2111 2112 /** 2113 * Return a list of all the networks configured for the current foreground 2114 * user. 2115 * 2116 * Not all fields of WifiConfiguration are returned. Only the following 2117 * fields are filled in: 2118 * <ul> 2119 * <li>networkId</li> 2120 * <li>SSID</li> 2121 * <li>BSSID</li> 2122 * <li>priority</li> 2123 * <li>allowedProtocols</li> 2124 * <li>allowedKeyManagement</li> 2125 * <li>allowedAuthAlgorithms</li> 2126 * <li>allowedPairwiseCiphers</li> 2127 * <li>allowedGroupCiphers</li> 2128 * <li>status</li> 2129 * </ul> 2130 * @return a list of network configurations in the form of a list 2131 * of {@link WifiConfiguration} objects. 2132 * 2133 * @deprecated 2134 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2135 * mechanism to trigger connection to a Wi-Fi network. 2136 * b) See {@link #addNetworkSuggestions(List)}, 2137 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2138 * when auto-connecting to wifi. 2139 * <b>Compatibility Note:</b> For applications targeting 2140 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return an 2141 * empty list. 2142 * <p> 2143 * Deprecation Exemptions: 2144 * <ul> 2145 * <li>Device Owner (DO), Profile Owner (PO) and system apps will have access to the full list. 2146 * <li>Callers with Carrier privilege will receive a restricted list only containing 2147 * configurations which they created. 2148 * </ul> 2149 */ 2150 @Deprecated 2151 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) getConfiguredNetworks()2152 public List<WifiConfiguration> getConfiguredNetworks() { 2153 try { 2154 ParceledListSlice<WifiConfiguration> parceledList = 2155 mService.getConfiguredNetworks(mContext.getOpPackageName(), 2156 mContext.getAttributionTag(), false); 2157 if (parceledList == null) { 2158 return Collections.emptyList(); 2159 } 2160 return parceledList.getList(); 2161 } catch (RemoteException e) { 2162 throw e.rethrowFromSystemServer(); 2163 } 2164 } 2165 2166 /** 2167 * Return a list of all the networks previously configured by the calling app. Can 2168 * be called by Device Owner (DO), Profile Owner (PO), Callers with Carrier privilege and 2169 * system apps. 2170 * 2171 * @return a list of network configurations in the form of a list 2172 * of {@link WifiConfiguration} objects. 2173 * @throws SecurityException if the caller is not allowed to call this API 2174 */ 2175 @RequiresPermission(ACCESS_WIFI_STATE) 2176 @NonNull getCallerConfiguredNetworks()2177 public List<WifiConfiguration> getCallerConfiguredNetworks() { 2178 try { 2179 ParceledListSlice<WifiConfiguration> parceledList = 2180 mService.getConfiguredNetworks(mContext.getOpPackageName(), 2181 mContext.getAttributionTag(), true); 2182 if (parceledList == null) { 2183 return Collections.emptyList(); 2184 } 2185 return parceledList.getList(); 2186 } catch (RemoteException e) { 2187 throw e.rethrowFromSystemServer(); 2188 } 2189 } 2190 2191 2192 /** 2193 * Applications targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later need to have 2194 * the following permissions: {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}, 2195 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and 2196 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. 2197 * Applications targeting {@link Build.VERSION_CODES#S} or prior SDK levels need to have the 2198 * following permissions: {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, 2199 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 2200 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. 2201 * <p> See {@link #getPrivilegedConnectedNetwork()} to get the WifiConfiguration for only the 2202 * connected network that's providing internet by default. 2203 * 2204 * @hide 2205 **/ 2206 @SystemApi 2207 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, NEARBY_WIFI_DEVICES, ACCESS_WIFI_STATE, 2208 READ_WIFI_CREDENTIAL}, 2209 conditional = true) getPrivilegedConfiguredNetworks()2210 public List<WifiConfiguration> getPrivilegedConfiguredNetworks() { 2211 try { 2212 Bundle extras = new Bundle(); 2213 if (SdkLevel.isAtLeastS()) { 2214 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 2215 mContext.getAttributionSource()); 2216 } 2217 ParceledListSlice<WifiConfiguration> parceledList = 2218 mService.getPrivilegedConfiguredNetworks(mContext.getOpPackageName(), 2219 mContext.getAttributionTag(), extras); 2220 if (parceledList == null) { 2221 return Collections.emptyList(); 2222 } 2223 return parceledList.getList(); 2224 } catch (RemoteException e) { 2225 throw e.rethrowFromSystemServer(); 2226 } 2227 } 2228 2229 /** 2230 * Gets the {@link WifiConfiguration} with credentials of the connected wifi network 2231 * that's providing internet by default. 2232 * <p> 2233 * On {@link android.os.Build.VERSION_CODES#TIRAMISU} or later SDKs, the caller need to have 2234 * the following permissions: {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with 2235 * android:usesPermissionFlags="neverForLocation", 2236 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and 2237 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. If the app does not have 2238 * android:usesPermissionFlags="neverForLocation", then it must also have 2239 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}. 2240 * <p> 2241 * On {@link Build.VERSION_CODES#S} or prior SDKs, the caller need to have the 2242 * following permissions: {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, 2243 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 2244 * {@link android.Manifest.permission#READ_WIFI_CREDENTIAL}. 2245 * 2246 * @return The WifiConfiguration representation of the connected wifi network providing 2247 * internet, or null if wifi is not connected. 2248 * 2249 * @throws SecurityException if caller does not have the required permissions 2250 * @hide 2251 **/ 2252 @SystemApi 2253 @RequiresPermission(allOf = {NEARBY_WIFI_DEVICES, ACCESS_WIFI_STATE, READ_WIFI_CREDENTIAL}, 2254 conditional = true) 2255 @Nullable getPrivilegedConnectedNetwork()2256 public WifiConfiguration getPrivilegedConnectedNetwork() { 2257 try { 2258 Bundle extras = new Bundle(); 2259 if (SdkLevel.isAtLeastS()) { 2260 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 2261 mContext.getAttributionSource()); 2262 } 2263 return mService.getPrivilegedConnectedNetwork(mContext.getOpPackageName(), 2264 mContext.getAttributionTag(), extras); 2265 } catch (RemoteException e) { 2266 throw e.rethrowFromSystemServer(); 2267 } 2268 } 2269 2270 /** 2271 * Returns a list of all matching WifiConfigurations of PasspointConfiguration for a given list 2272 * of ScanResult. 2273 * 2274 * An empty list will be returned when no PasspointConfiguration are installed or if no 2275 * PasspointConfiguration match the ScanResult. 2276 * 2277 * @param scanResults a list of scanResult that represents the BSSID 2278 * @return List that consists of {@link WifiConfiguration} and corresponding scanResults per 2279 * network type({@link #PASSPOINT_HOME_NETWORK} and {@link #PASSPOINT_ROAMING_NETWORK}). 2280 * @hide 2281 */ 2282 @SystemApi 2283 @RequiresPermission(anyOf = { 2284 android.Manifest.permission.NETWORK_SETTINGS, 2285 android.Manifest.permission.NETWORK_SETUP_WIZARD 2286 }) 2287 @NonNull getAllMatchingWifiConfigs( @onNull List<ScanResult> scanResults)2288 public List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> getAllMatchingWifiConfigs( 2289 @NonNull List<ScanResult> scanResults) { 2290 List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>(); 2291 try { 2292 Map<String, Map<Integer, List<ScanResult>>> results = 2293 mService.getAllMatchingPasspointProfilesForScanResults(scanResults); 2294 if (results.isEmpty()) { 2295 return configs; 2296 } 2297 List<WifiConfiguration> wifiConfigurations = 2298 mService.getWifiConfigsForPasspointProfiles( 2299 new ArrayList<>(results.keySet())); 2300 for (WifiConfiguration configuration : wifiConfigurations) { 2301 Map<Integer, List<ScanResult>> scanResultsPerNetworkType = 2302 results.get(configuration.getProfileKey()); 2303 if (scanResultsPerNetworkType != null) { 2304 configs.add(Pair.create(configuration, scanResultsPerNetworkType)); 2305 } 2306 } 2307 } catch (RemoteException e) { 2308 throw e.rethrowFromSystemServer(); 2309 } 2310 2311 return configs; 2312 } 2313 2314 /** 2315 * To be used with setScreenOnScanSchedule. 2316 * @hide 2317 */ 2318 @SystemApi 2319 public static class ScreenOnScanSchedule { 2320 private final Duration mScanInterval; 2321 private final int mScanType; 2322 2323 /** 2324 * Creates a ScreenOnScanSchedule. 2325 * @param scanInterval Interval between framework-initiated connectivity scans. 2326 * @param scanType One of the {@code WifiScanner.SCAN_TYPE_} values. 2327 */ ScreenOnScanSchedule(@onNull Duration scanInterval, @WifiAnnotations.ScanType int scanType)2328 public ScreenOnScanSchedule(@NonNull Duration scanInterval, 2329 @WifiAnnotations.ScanType int scanType) { 2330 if (scanInterval == null) { 2331 throw new IllegalArgumentException("scanInterval can't be null"); 2332 } 2333 mScanInterval = scanInterval; 2334 mScanType = scanType; 2335 } 2336 2337 /** 2338 * Gets the interval between framework-initiated connectivity scans. 2339 */ getScanInterval()2340 public @NonNull Duration getScanInterval() { 2341 return mScanInterval; 2342 } 2343 2344 /** 2345 * Gets the type of scan to be used. One of the {@code WifiScanner.SCAN_TYPE_} values. 2346 */ getScanType()2347 public @WifiAnnotations.ScanType int getScanType() { 2348 return mScanType; 2349 } 2350 } 2351 2352 /** 2353 * This API allows a privileged app to customize the wifi framework's network selection logic. 2354 * To revert to default behavior, call this API with a {@link WifiNetworkSelectionConfig} 2355 * created from a default {@link WifiNetworkSelectionConfig.Builder}. 2356 * 2357 * Use {@link WifiManager#getNetworkSelectionConfig(Executor, Consumer)} to get the current 2358 * network selection configuration. 2359 * <P> 2360 * @param nsConfig an Object representing the network selection configuration being programmed. 2361 * This should be created with a {@link WifiNetworkSelectionConfig.Builder}. 2362 * 2363 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2364 * @throws IllegalArgumentException if input is invalid. 2365 * @throws SecurityException if the caller does not have permission. 2366 * @hide 2367 */ 2368 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2369 @RequiresPermission(anyOf = { 2370 android.Manifest.permission.NETWORK_SETTINGS, 2371 MANAGE_WIFI_NETWORK_SELECTION 2372 }) 2373 @SystemApi setNetworkSelectionConfig(@onNull WifiNetworkSelectionConfig nsConfig)2374 public void setNetworkSelectionConfig(@NonNull WifiNetworkSelectionConfig nsConfig) { 2375 try { 2376 if (nsConfig == null) { 2377 throw new IllegalArgumentException("nsConfig can not be null"); 2378 } 2379 mService.setNetworkSelectionConfig(nsConfig); 2380 } catch (RemoteException e) { 2381 throw e.rethrowFromSystemServer(); 2382 } 2383 } 2384 2385 /** 2386 * This API allows a privileged app to retrieve the {@link WifiNetworkSelectionConfig} 2387 * currently being used by the network selector. 2388 * 2389 * Use {@link WifiManager#setNetworkSelectionConfig(WifiNetworkSelectionConfig)} to set a 2390 * new network selection configuration. 2391 * <P> 2392 * @param executor The executor on which callback will be invoked. 2393 * @param resultsCallback An asynchronous callback that will return 2394 * {@link WifiNetworkSelectionConfig} 2395 * 2396 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2397 * @throws SecurityException if the caller does not have permission. 2398 * @throws NullPointerException if the caller provided invalid inputs. 2399 * @hide 2400 */ 2401 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2402 @RequiresPermission(anyOf = { 2403 android.Manifest.permission.NETWORK_SETTINGS, 2404 MANAGE_WIFI_NETWORK_SELECTION 2405 }) 2406 @SystemApi getNetworkSelectionConfig(@onNull @allbackExecutor Executor executor, @NonNull Consumer<WifiNetworkSelectionConfig> resultsCallback)2407 public void getNetworkSelectionConfig(@NonNull @CallbackExecutor Executor executor, 2408 @NonNull Consumer<WifiNetworkSelectionConfig> resultsCallback) { 2409 Objects.requireNonNull(executor, "executor cannot be null"); 2410 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 2411 try { 2412 mService.getNetworkSelectionConfig( 2413 new IWifiNetworkSelectionConfigListener.Stub() { 2414 @Override 2415 public void onResult(WifiNetworkSelectionConfig value) { 2416 Binder.clearCallingIdentity(); 2417 executor.execute(() -> { 2418 resultsCallback.accept(value); 2419 }); 2420 } 2421 }); 2422 } catch (RemoteException e) { 2423 throw e.rethrowFromSystemServer(); 2424 } 2425 } 2426 2427 /** 2428 * Allows a privileged app to enable/disable whether a confirmation dialog should be displayed 2429 * when third-party apps attempt to turn on WiFi. 2430 * 2431 * Use {@link #isThirdPartyAppEnablingWifiConfirmationDialogEnabled()} to get the 2432 * currently configured value. 2433 * 2434 * Note: Only affects behavior for apps with targetSDK < Q, since third party apps are not 2435 * allowed to enable wifi on targetSDK >= Q. 2436 * 2437 * This overrides the overlay value |config_showConfirmationDialogForThirdPartyAppsEnablingWifi| 2438 * <P> 2439 * @param enable true to enable the confirmation dialog, false otherwise 2440 * 2441 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2442 * @throws SecurityException if the caller does not have permission. 2443 * @hide 2444 */ 2445 @RequiresPermission(anyOf = { 2446 android.Manifest.permission.NETWORK_SETTINGS, 2447 android.Manifest.permission.NETWORK_SETUP_WIZARD 2448 }) 2449 @SystemApi setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable)2450 public void setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable) { 2451 try { 2452 mService.setThirdPartyAppEnablingWifiConfirmationDialogEnabled(enable); 2453 } catch (RemoteException e) { 2454 throw e.rethrowFromSystemServer(); 2455 } 2456 } 2457 2458 /** 2459 * Check whether the wifi configuration indicates that a confirmation dialog should be displayed 2460 * when third-party apps attempt to turn on WiFi. 2461 * 2462 * Use {@link #setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean)} to set this 2463 * value. 2464 * 2465 * Note: This setting only affects behavior for apps with targetSDK < Q, since third party apps 2466 * are not allowed to enable wifi on targetSDK >= Q. 2467 * 2468 * <P> 2469 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2470 * @throws SecurityException if the caller does not have permission. 2471 * @return true if dialog should be displayed, false otherwise. 2472 * @hide 2473 */ 2474 @RequiresPermission(anyOf = { 2475 android.Manifest.permission.NETWORK_SETTINGS, 2476 android.Manifest.permission.NETWORK_SETUP_WIZARD 2477 }) 2478 @SystemApi isThirdPartyAppEnablingWifiConfirmationDialogEnabled()2479 public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled() { 2480 try { 2481 return mService.isThirdPartyAppEnablingWifiConfirmationDialogEnabled(); 2482 } catch (RemoteException e) { 2483 throw e.rethrowFromSystemServer(); 2484 } 2485 } 2486 2487 /** 2488 * Allows a privileged app to customize the screen-on scan behavior. When a non-null schedule 2489 * is set via this API, it will always get used instead of the scan schedules defined in the 2490 * overlay. When a null schedule is set via this API, the wifi subsystem will go back to using 2491 * the scan schedules defined in the overlay. Also note, the scan schedule will be truncated 2492 * (rounded down) to the nearest whole second. 2493 * <p> 2494 * Example usage: 2495 * The following call specifies that first scheduled scan should be in 20 seconds using 2496 * {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}, and all 2497 * scheduled scans later should happen every 40 seconds using 2498 * {@link WifiScanner#SCAN_TYPE_LOW_POWER}. 2499 * <pre> 2500 * List<ScreenOnScanSchedule> schedule = new ArrayList<>(); 2501 * schedule.add(new ScreenOnScanSchedule(Duration.ofSeconds(20), 2502 * WifiScanner.SCAN_TYPE_HIGH_ACCURACY)); 2503 * schedule.add(new ScreenOnScanSchedule(Duration.ofSeconds(40), 2504 * WifiScanner.SCAN_TYPE_LOW_POWER)); 2505 * wifiManager.setScreenOnScanSchedule(schedule); 2506 * </pre> 2507 * @param screenOnScanSchedule defines the screen-on scan schedule and the corresponding 2508 * scan type. Set to null to clear any previously set value. 2509 * 2510 * @throws IllegalStateException if input is invalid 2511 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2512 * @throws SecurityException if the caller does not have permission. 2513 * @hide 2514 */ 2515 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2516 @RequiresPermission(anyOf = { 2517 android.Manifest.permission.NETWORK_SETTINGS, 2518 MANAGE_WIFI_NETWORK_SELECTION 2519 }) 2520 @SystemApi setScreenOnScanSchedule(@ullable List<ScreenOnScanSchedule> screenOnScanSchedule)2521 public void setScreenOnScanSchedule(@Nullable List<ScreenOnScanSchedule> screenOnScanSchedule) { 2522 try { 2523 if (screenOnScanSchedule == null) { 2524 mService.setScreenOnScanSchedule(null, null); 2525 return; 2526 } 2527 if (screenOnScanSchedule.isEmpty()) { 2528 throw new IllegalArgumentException("The input should either be null or a non-empty" 2529 + " list"); 2530 } 2531 int[] scanSchedule = new int[screenOnScanSchedule.size()]; 2532 int[] scanType = new int[screenOnScanSchedule.size()]; 2533 for (int i = 0; i < screenOnScanSchedule.size(); i++) { 2534 scanSchedule[i] = (int) screenOnScanSchedule.get(i).getScanInterval().toSeconds(); 2535 scanType[i] = screenOnScanSchedule.get(i).getScanType(); 2536 } 2537 mService.setScreenOnScanSchedule(scanSchedule, scanType); 2538 } catch (RemoteException e) { 2539 throw e.rethrowFromSystemServer(); 2540 } 2541 } 2542 2543 /** 2544 * The Wi-Fi framework may trigger connectivity scans in response to the screen turning on for 2545 * network selection purposes. This API allows a privileged app to set a delay to the next 2546 * connectivity scan triggered by the Wi-Fi framework in response to the next screen-on event. 2547 * This gives a window for the privileged app to issue their own custom scans to influence Wi-Fi 2548 * network selection. The expected usage is the privileged app monitor for the screen turning 2549 * off, and then call this API if it believes delaying the next screen-on connectivity scan is 2550 * needed. 2551 * <p> 2552 * Note that this API will only delay screen-on connectivity scans once. This API will need to 2553 * be called again if further screen-on scan delays are needed after it resolves. 2554 * @param delayMs defines the time in milliseconds to delay the next screen-on connectivity 2555 * scan. Setting this to 0 will remove the delay. 2556 * 2557 * @throws IllegalStateException if input is invalid 2558 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 2559 * @throws SecurityException if the caller does not have permission. 2560 * @hide 2561 */ 2562 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2563 @RequiresPermission(anyOf = { 2564 android.Manifest.permission.NETWORK_SETTINGS, 2565 MANAGE_WIFI_NETWORK_SELECTION 2566 }) 2567 @SystemApi setOneShotScreenOnConnectivityScanDelayMillis(@ntRangefrom = 0) int delayMs)2568 public void setOneShotScreenOnConnectivityScanDelayMillis(@IntRange(from = 0) int delayMs) { 2569 try { 2570 mService.setOneShotScreenOnConnectivityScanDelayMillis(delayMs); 2571 } catch (RemoteException e) { 2572 throw e.rethrowFromSystemServer(); 2573 } 2574 } 2575 2576 /** 2577 * Retrieve a list of {@link WifiConfiguration} for available {@link WifiNetworkSuggestion} 2578 * matching the given list of {@link ScanResult}. 2579 * 2580 * An available {@link WifiNetworkSuggestion} must satisfy: 2581 * <ul> 2582 * <li> Matching one of the {@link ScanResult} from the given list. 2583 * <li> and {@link WifiNetworkSuggestion.Builder#setIsUserAllowedToManuallyConnect(boolean)} set 2584 * to true. 2585 * </ul> 2586 * 2587 * @param scanResults a list of scanResult. 2588 * @return a list of @link WifiConfiguration} for available {@link WifiNetworkSuggestion} 2589 * @hide 2590 */ 2591 @SystemApi 2592 @RequiresPermission(anyOf = { 2593 android.Manifest.permission.NETWORK_SETTINGS, 2594 android.Manifest.permission.NETWORK_SETUP_WIZARD 2595 }) 2596 @NonNull getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( @onNull List<ScanResult> scanResults)2597 public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( 2598 @NonNull List<ScanResult> scanResults) { 2599 try { 2600 return mService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults); 2601 } catch (RemoteException e) { 2602 throw e.rethrowAsRuntimeException(); 2603 } 2604 } 2605 2606 /** 2607 * Specify a set of SSIDs that will not get disabled internally by the Wi-Fi subsystem when 2608 * connection issues occur. To clear the list, call this API with an empty Set. 2609 * <p> 2610 * {@link #getSsidsAllowlist()} can be used to check the SSIDs that have been set. 2611 * @param ssids - list of WifiSsid that will not get disabled internally 2612 * @throws SecurityException if the calling app is not a Device Owner (DO), Profile Owner (PO), 2613 * or a privileged app that has one of the permissions required by 2614 * this API. 2615 * @throws IllegalArgumentException if the input is null. 2616 * @hide 2617 */ 2618 @SystemApi 2619 @RequiresPermission(anyOf = { 2620 android.Manifest.permission.NETWORK_SETTINGS, 2621 android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional = true) setSsidsAllowlist(@onNull Set<WifiSsid> ssids)2622 public void setSsidsAllowlist(@NonNull Set<WifiSsid> ssids) { 2623 if (ssids == null) { 2624 throw new IllegalArgumentException(TAG + ": ssids can not be null"); 2625 } 2626 try { 2627 mService.setSsidsAllowlist(mContext.getOpPackageName(), new ArrayList<>(ssids)); 2628 } catch (RemoteException e) { 2629 throw e.rethrowFromSystemServer(); 2630 } 2631 } 2632 2633 /** 2634 * Get the Set of SSIDs that will not get disabled internally by the Wi-Fi subsystem when 2635 * connection issues occur. 2636 * @throws SecurityException if the calling app is not a Device Owner (DO), Profile Owner (PO), 2637 * or a privileged app that has one of the permissions required by 2638 * this API. 2639 * @hide 2640 */ 2641 @SystemApi 2642 @RequiresPermission(anyOf = { 2643 android.Manifest.permission.NETWORK_SETTINGS, 2644 android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}, conditional = true) getSsidsAllowlist()2645 public @NonNull Set<WifiSsid> getSsidsAllowlist() { 2646 try { 2647 return new ArraySet<WifiSsid>( 2648 mService.getSsidsAllowlist(mContext.getOpPackageName())); 2649 } catch (RemoteException e) { 2650 throw e.rethrowFromSystemServer(); 2651 } 2652 } 2653 2654 /** 2655 * Returns a list of unique Hotspot 2.0 OSU (Online Sign-Up) providers associated with a given 2656 * list of ScanResult. 2657 * 2658 * An empty list will be returned if no match is found. 2659 * 2660 * @param scanResults a list of ScanResult 2661 * @return Map that consists {@link OsuProvider} and a list of matching {@link ScanResult} 2662 * @hide 2663 */ 2664 @SystemApi 2665 @RequiresPermission(anyOf = { 2666 android.Manifest.permission.NETWORK_SETTINGS, 2667 android.Manifest.permission.NETWORK_SETUP_WIZARD 2668 }) 2669 @NonNull getMatchingOsuProviders( @ullable List<ScanResult> scanResults)2670 public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( 2671 @Nullable List<ScanResult> scanResults) { 2672 if (scanResults == null) { 2673 return new HashMap<>(); 2674 } 2675 try { 2676 return mService.getMatchingOsuProviders(scanResults); 2677 } catch (RemoteException e) { 2678 throw e.rethrowFromSystemServer(); 2679 } 2680 } 2681 2682 /** 2683 * Returns the matching Passpoint R2 configurations for given OSU (Online Sign-Up) providers. 2684 * 2685 * Given a list of OSU providers, this only returns OSU providers that already have Passpoint R2 2686 * configurations in the device. 2687 * An empty map will be returned when there is no matching Passpoint R2 configuration for the 2688 * given OsuProviders. 2689 * 2690 * @param osuProviders a set of {@link OsuProvider} 2691 * @return Map that consists of {@link OsuProvider} and matching {@link PasspointConfiguration}. 2692 * @hide 2693 */ 2694 @SystemApi 2695 @RequiresPermission(anyOf = { 2696 android.Manifest.permission.NETWORK_SETTINGS, 2697 android.Manifest.permission.NETWORK_SETUP_WIZARD 2698 }) 2699 @NonNull getMatchingPasspointConfigsForOsuProviders( @onNull Set<OsuProvider> osuProviders)2700 public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( 2701 @NonNull Set<OsuProvider> osuProviders) { 2702 try { 2703 return mService.getMatchingPasspointConfigsForOsuProviders( 2704 new ArrayList<>(osuProviders)); 2705 } catch (RemoteException e) { 2706 throw e.rethrowFromSystemServer(); 2707 } 2708 } 2709 2710 /** 2711 * Add a new network description to the set of configured networks. 2712 * The {@code networkId} field of the supplied configuration object 2713 * is ignored. 2714 * <p/> 2715 * The new network will be marked DISABLED by default. To enable it, 2716 * called {@link #enableNetwork}. 2717 * 2718 * @param config the set of variables that describe the configuration, 2719 * contained in a {@link WifiConfiguration} object. 2720 * If the {@link WifiConfiguration} has an Http Proxy set 2721 * the calling app must be System, or be provisioned as the Profile or Device Owner. 2722 * @return the ID of the newly created network description. This is used in 2723 * other operations to specified the network to be acted upon. 2724 * Returns {@code -1} on failure. 2725 * 2726 * @deprecated 2727 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2728 * mechanism to trigger connection to a Wi-Fi network. 2729 * b) See {@link #addNetworkSuggestions(List)}, 2730 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2731 * when auto-connecting to wifi. 2732 * <b>Compatibility Note:</b> For applications targeting 2733 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 2734 * {@code -1}. 2735 * <p> 2736 * Deprecation Exemptions: 2737 * <ul> 2738 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2739 * </ul> 2740 */ 2741 @Deprecated addNetwork(WifiConfiguration config)2742 public int addNetwork(WifiConfiguration config) { 2743 if (config == null) { 2744 return -1; 2745 } 2746 config.networkId = -1; 2747 return addOrUpdateNetwork(config); 2748 } 2749 2750 /** 2751 * This is a new version of {@link #addNetwork(WifiConfiguration)} which returns more detailed 2752 * failure codes. The usage of this API is limited to Device Owner (DO), Profile Owner (PO), 2753 * system app, and privileged apps. 2754 * <p> 2755 * Add a new network description to the set of configured networks. The {@code networkId} 2756 * field of the supplied configuration object is ignored. The new network will be marked 2757 * DISABLED by default. To enable it, call {@link #enableNetwork}. 2758 * <p> 2759 * @param config the set of variables that describe the configuration, 2760 * contained in a {@link WifiConfiguration} object. 2761 * If the {@link WifiConfiguration} has an Http Proxy set 2762 * the calling app must be System, or be provisioned as the Profile or Device Owner. 2763 * @return A {@link AddNetworkResult} Object. 2764 * @throws SecurityException if the calling app is not a Device Owner (DO), 2765 * Profile Owner (PO), system app, or a privileged app that has one of 2766 * the permissions required by this API. 2767 * @throws IllegalArgumentException if the input configuration is null or if the 2768 * security type in input configuration is not supported. 2769 */ 2770 @RequiresPermission(anyOf = { 2771 android.Manifest.permission.NETWORK_SETTINGS, 2772 android.Manifest.permission.NETWORK_STACK, 2773 android.Manifest.permission.NETWORK_SETUP_WIZARD, 2774 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING 2775 }, conditional = true) 2776 @NonNull addNetworkPrivileged(@onNull WifiConfiguration config)2777 public AddNetworkResult addNetworkPrivileged(@NonNull WifiConfiguration config) { 2778 if (config == null) throw new IllegalArgumentException("config cannot be null"); 2779 if (config.isSecurityType(WifiInfo.SECURITY_TYPE_DPP) 2780 && !isFeatureSupported(WIFI_FEATURE_DPP_AKM)) { 2781 throw new IllegalArgumentException("dpp akm is not supported"); 2782 } 2783 config.networkId = -1; 2784 try { 2785 return mService.addOrUpdateNetworkPrivileged(config, mContext.getOpPackageName()); 2786 } catch (RemoteException e) { 2787 throw e.rethrowFromSystemServer(); 2788 } 2789 } 2790 2791 /** 2792 * Provides the results of a call to {@link #addNetworkPrivileged(WifiConfiguration)} 2793 */ 2794 public static final class AddNetworkResult implements Parcelable { 2795 /** 2796 * The operation has completed successfully. 2797 */ 2798 public static final int STATUS_SUCCESS = 0; 2799 /** 2800 * The operation has failed due to an unknown reason. 2801 */ 2802 public static final int STATUS_FAILURE_UNKNOWN = 1; 2803 /** 2804 * The calling app does not have permission to call this API. 2805 */ 2806 public static final int STATUS_NO_PERMISSION = 2; 2807 /** 2808 * Generic failure code for adding a passpoint network. 2809 */ 2810 public static final int STATUS_ADD_PASSPOINT_FAILURE = 3; 2811 /** 2812 * Generic failure code for adding a non-passpoint network. 2813 */ 2814 public static final int STATUS_ADD_WIFI_CONFIG_FAILURE = 4; 2815 /** 2816 * The network configuration is invalid. 2817 */ 2818 public static final int STATUS_INVALID_CONFIGURATION = 5; 2819 /** 2820 * The calling app has no permission to modify the configuration. 2821 */ 2822 public static final int STATUS_NO_PERMISSION_MODIFY_CONFIG = 6; 2823 /** 2824 * The calling app has no permission to modify the proxy setting. 2825 */ 2826 public static final int STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING = 7; 2827 /** 2828 * The calling app has no permission to modify the MAC randomization setting. 2829 */ 2830 public static final int STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION = 8; 2831 /** 2832 * Internal failure in updating network keys.. 2833 */ 2834 public static final int STATUS_FAILURE_UPDATE_NETWORK_KEYS = 9; 2835 /** 2836 * The enterprise network is missing either the root CA or domain name. 2837 */ 2838 public static final int STATUS_INVALID_CONFIGURATION_ENTERPRISE = 10; 2839 2840 /** @hide */ 2841 @IntDef(prefix = { "STATUS_" }, value = { 2842 STATUS_SUCCESS, 2843 STATUS_FAILURE_UNKNOWN, 2844 STATUS_NO_PERMISSION, 2845 STATUS_ADD_PASSPOINT_FAILURE, 2846 STATUS_ADD_WIFI_CONFIG_FAILURE, 2847 STATUS_INVALID_CONFIGURATION, 2848 STATUS_NO_PERMISSION_MODIFY_CONFIG, 2849 STATUS_NO_PERMISSION_MODIFY_PROXY_SETTING, 2850 STATUS_NO_PERMISSION_MODIFY_MAC_RANDOMIZATION, 2851 STATUS_FAILURE_UPDATE_NETWORK_KEYS, 2852 STATUS_INVALID_CONFIGURATION_ENTERPRISE, 2853 }) 2854 @Retention(RetentionPolicy.SOURCE) 2855 public @interface AddNetworkStatusCode {} 2856 2857 @Override describeContents()2858 public int describeContents() { 2859 return 0; 2860 } 2861 2862 @Override writeToParcel(@onNull Parcel dest, int flags)2863 public void writeToParcel(@NonNull Parcel dest, int flags) { 2864 dest.writeInt(statusCode); 2865 dest.writeInt(networkId); 2866 } 2867 2868 /** Implement the Parcelable interface */ 2869 public static final @android.annotation.NonNull Creator<AddNetworkResult> CREATOR = 2870 new Creator<AddNetworkResult>() { 2871 public AddNetworkResult createFromParcel(Parcel in) { 2872 return new AddNetworkResult(in.readInt(), in.readInt()); 2873 } 2874 2875 public AddNetworkResult[] newArray(int size) { 2876 return new AddNetworkResult[size]; 2877 } 2878 }; 2879 2880 /** 2881 * One of the {@code STATUS_} values. If the operation is successful this field 2882 * will be set to {@code STATUS_SUCCESS}. 2883 */ 2884 public final @AddNetworkStatusCode int statusCode; 2885 /** 2886 * The identifier of the added network, which could be used in other operations. This field 2887 * will be set to {@code -1} if the operation failed. 2888 */ 2889 public final int networkId; 2890 AddNetworkResult(@ddNetworkStatusCode int statusCode, int networkId)2891 public AddNetworkResult(@AddNetworkStatusCode int statusCode, int networkId) { 2892 this.statusCode = statusCode; 2893 this.networkId = networkId; 2894 } 2895 } 2896 2897 /** 2898 * Update the network description of an existing configured network. 2899 * 2900 * @param config the set of variables that describe the configuration, 2901 * contained in a {@link WifiConfiguration} object. It may 2902 * be sparse, so that only the items that are being changed 2903 * are non-<code>null</code>. The {@code networkId} field 2904 * must be set to the ID of the existing network being updated. 2905 * If the {@link WifiConfiguration} has an Http Proxy set 2906 * the calling app must be System, or be provisioned as the Profile or Device Owner. 2907 * @return Returns the {@code networkId} of the supplied 2908 * {@code WifiConfiguration} on success. 2909 * <br/> 2910 * Returns {@code -1} on failure, including when the {@code networkId} 2911 * field of the {@code WifiConfiguration} does not refer to an 2912 * existing network. 2913 * 2914 * @deprecated 2915 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 2916 * mechanism to trigger connection to a Wi-Fi network. 2917 * b) See {@link #addNetworkSuggestions(List)}, 2918 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 2919 * when auto-connecting to wifi. 2920 * <b>Compatibility Note:</b> For applications targeting 2921 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 2922 * {@code -1}. 2923 * <p> 2924 * Deprecation Exemptions: 2925 * <ul> 2926 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 2927 * </ul> 2928 */ 2929 @Deprecated updateNetwork(WifiConfiguration config)2930 public int updateNetwork(WifiConfiguration config) { 2931 if (config == null || config.networkId < 0) { 2932 return -1; 2933 } 2934 return addOrUpdateNetwork(config); 2935 } 2936 2937 /** 2938 * Internal method for doing the RPC that creates a new network description 2939 * or updates an existing one. 2940 * 2941 * @param config The possibly sparse object containing the variables that 2942 * are to set or updated in the network description. 2943 * @return the ID of the network on success, {@code -1} on failure. 2944 */ addOrUpdateNetwork(WifiConfiguration config)2945 private int addOrUpdateNetwork(WifiConfiguration config) { 2946 Bundle extras = new Bundle(); 2947 if (SdkLevel.isAtLeastS()) { 2948 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 2949 mContext.getAttributionSource()); 2950 } 2951 2952 try { 2953 return mService.addOrUpdateNetwork(config, mContext.getOpPackageName(), extras); 2954 } catch (RemoteException e) { 2955 throw e.rethrowFromSystemServer(); 2956 } 2957 } 2958 2959 /** 2960 * Interface for indicating user selection from the list of networks presented in the 2961 * {@link NetworkRequestMatchCallback#onMatch(List)}. 2962 * 2963 * The platform will implement this callback and pass it along with the 2964 * {@link NetworkRequestMatchCallback#onUserSelectionCallbackRegistration( 2965 * NetworkRequestUserSelectionCallback)}. The UI component handling 2966 * {@link NetworkRequestMatchCallback} will invoke {@link #select(WifiConfiguration)} or 2967 * {@link #reject()} to return the user's selection back to the platform via this callback. 2968 * @hide 2969 */ 2970 @SystemApi 2971 public interface NetworkRequestUserSelectionCallback { 2972 /** 2973 * User selected this network to connect to. 2974 * @param wifiConfiguration WifiConfiguration object corresponding to the network 2975 * user selected. 2976 */ 2977 @SuppressLint("CallbackMethodName") select(@onNull WifiConfiguration wifiConfiguration)2978 default void select(@NonNull WifiConfiguration wifiConfiguration) {} 2979 2980 /** 2981 * User rejected the app's request. 2982 */ 2983 @SuppressLint("CallbackMethodName") reject()2984 default void reject() {} 2985 } 2986 2987 /** 2988 * Interface for network request callback. Should be implemented by applications and passed when 2989 * calling {@link #registerNetworkRequestMatchCallback(Executor, 2990 * WifiManager.NetworkRequestMatchCallback)}. 2991 * 2992 * This is meant to be implemented by a UI component to present the user with a list of networks 2993 * matching the app's request. The user is allowed to pick one of these networks to connect to 2994 * or reject the request by the app. 2995 * @hide 2996 */ 2997 @SystemApi 2998 public interface NetworkRequestMatchCallback { 2999 /** 3000 * Invoked to register a callback to be invoked to convey user selection. The callback 3001 * object passed in this method is to be invoked by the UI component after the service sends 3002 * a list of matching scan networks using {@link #onMatch(List)} and user picks a network 3003 * from that list. 3004 * 3005 * @param userSelectionCallback Callback object to send back the user selection. 3006 */ onUserSelectionCallbackRegistration( @onNull NetworkRequestUserSelectionCallback userSelectionCallback)3007 default void onUserSelectionCallbackRegistration( 3008 @NonNull NetworkRequestUserSelectionCallback userSelectionCallback) {} 3009 3010 /** 3011 * Invoked when the active network request is aborted, either because 3012 * <li> The app released the request, OR</li> 3013 * <li> Request was overridden by a new request</li> 3014 * This signals the end of processing for the current request and should stop the UI 3015 * component. No subsequent calls from the UI component will be handled by the platform. 3016 */ onAbort()3017 default void onAbort() {} 3018 3019 /** 3020 * Invoked when a network request initiated by an app matches some networks in scan results. 3021 * This may be invoked multiple times for a single network request as the platform finds new 3022 * matching networks in scan results. 3023 * 3024 * @param scanResults List of {@link ScanResult} objects corresponding to the networks 3025 * matching the request. 3026 */ onMatch(@onNull List<ScanResult> scanResults)3027 default void onMatch(@NonNull List<ScanResult> scanResults) {} 3028 3029 /** 3030 * Invoked on a successful connection with the network that the user selected 3031 * via {@link NetworkRequestUserSelectionCallback}. 3032 * 3033 * @param wifiConfiguration WifiConfiguration object corresponding to the network that the 3034 * user selected. 3035 */ onUserSelectionConnectSuccess(@onNull WifiConfiguration wifiConfiguration)3036 default void onUserSelectionConnectSuccess(@NonNull WifiConfiguration wifiConfiguration) {} 3037 3038 /** 3039 * Invoked on failure to establish connection with the network that the user selected 3040 * via {@link NetworkRequestUserSelectionCallback}. 3041 * 3042 * @param wifiConfiguration WifiConfiguration object corresponding to the network 3043 * user selected. 3044 */ onUserSelectionConnectFailure(@onNull WifiConfiguration wifiConfiguration)3045 default void onUserSelectionConnectFailure(@NonNull WifiConfiguration wifiConfiguration) {} 3046 } 3047 3048 /** 3049 * Callback proxy for NetworkRequestUserSelectionCallback objects. 3050 * @hide 3051 */ 3052 private class NetworkRequestUserSelectionCallbackProxy implements 3053 NetworkRequestUserSelectionCallback { 3054 private final INetworkRequestUserSelectionCallback mCallback; 3055 NetworkRequestUserSelectionCallbackProxy( INetworkRequestUserSelectionCallback callback)3056 NetworkRequestUserSelectionCallbackProxy( 3057 INetworkRequestUserSelectionCallback callback) { 3058 mCallback = callback; 3059 } 3060 3061 @Override select(@onNull WifiConfiguration wifiConfiguration)3062 public void select(@NonNull WifiConfiguration wifiConfiguration) { 3063 if (mVerboseLoggingEnabled) { 3064 Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: select " 3065 + "wificonfiguration: " + wifiConfiguration); 3066 } 3067 try { 3068 mCallback.select(wifiConfiguration); 3069 } catch (RemoteException e) { 3070 Log.e(TAG, "Failed to invoke onSelected", e); 3071 throw e.rethrowFromSystemServer(); 3072 } 3073 } 3074 3075 @Override reject()3076 public void reject() { 3077 if (mVerboseLoggingEnabled) { 3078 Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: reject"); 3079 } 3080 try { 3081 mCallback.reject(); 3082 } catch (RemoteException e) { 3083 Log.e(TAG, "Failed to invoke onRejected", e); 3084 throw e.rethrowFromSystemServer(); 3085 } 3086 } 3087 } 3088 3089 /** 3090 * Callback proxy for NetworkRequestMatchCallback objects. 3091 * @hide 3092 */ 3093 private class NetworkRequestMatchCallbackProxy extends INetworkRequestMatchCallback.Stub { 3094 private final Executor mExecutor; 3095 private final NetworkRequestMatchCallback mCallback; 3096 NetworkRequestMatchCallbackProxy(Executor executor, NetworkRequestMatchCallback callback)3097 NetworkRequestMatchCallbackProxy(Executor executor, NetworkRequestMatchCallback callback) { 3098 mExecutor = executor; 3099 mCallback = callback; 3100 } 3101 3102 @Override onUserSelectionCallbackRegistration( INetworkRequestUserSelectionCallback userSelectionCallback)3103 public void onUserSelectionCallbackRegistration( 3104 INetworkRequestUserSelectionCallback userSelectionCallback) { 3105 if (mVerboseLoggingEnabled) { 3106 Log.v(TAG, "NetworkRequestMatchCallbackProxy: " 3107 + "onUserSelectionCallbackRegistration callback: " + userSelectionCallback); 3108 } 3109 Binder.clearCallingIdentity(); 3110 mExecutor.execute(() -> { 3111 mCallback.onUserSelectionCallbackRegistration( 3112 new NetworkRequestUserSelectionCallbackProxy(userSelectionCallback)); 3113 }); 3114 } 3115 3116 @Override onAbort()3117 public void onAbort() { 3118 if (mVerboseLoggingEnabled) { 3119 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onAbort"); 3120 } 3121 Binder.clearCallingIdentity(); 3122 mExecutor.execute(() -> { 3123 mCallback.onAbort(); 3124 }); 3125 } 3126 3127 @Override onMatch(List<ScanResult> scanResults)3128 public void onMatch(List<ScanResult> scanResults) { 3129 if (mVerboseLoggingEnabled) { 3130 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onMatch scanResults: " 3131 + scanResults); 3132 } 3133 Binder.clearCallingIdentity(); 3134 mExecutor.execute(() -> { 3135 mCallback.onMatch(scanResults); 3136 }); 3137 } 3138 3139 @Override onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration)3140 public void onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration) { 3141 if (mVerboseLoggingEnabled) { 3142 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectSuccess " 3143 + " wificonfiguration: " + wifiConfiguration); 3144 } 3145 Binder.clearCallingIdentity(); 3146 mExecutor.execute(() -> { 3147 mCallback.onUserSelectionConnectSuccess(wifiConfiguration); 3148 }); 3149 } 3150 3151 @Override onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration)3152 public void onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration) { 3153 if (mVerboseLoggingEnabled) { 3154 Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectFailure" 3155 + " wificonfiguration: " + wifiConfiguration); 3156 } 3157 Binder.clearCallingIdentity(); 3158 mExecutor.execute(() -> { 3159 mCallback.onUserSelectionConnectFailure(wifiConfiguration); 3160 }); 3161 } 3162 } 3163 3164 /** 3165 * Registers a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. 3166 * Caller can unregister a previously registered callback using 3167 * {@link #unregisterNetworkRequestMatchCallback(NetworkRequestMatchCallback)} 3168 * <p> 3169 * Applications should have the 3170 * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers 3171 * without the permission will trigger a {@link java.lang.SecurityException}. 3172 * <p> 3173 * 3174 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 3175 * object. 3176 * @param callback Callback for network match events to register. 3177 * @hide 3178 */ 3179 @SystemApi 3180 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) registerNetworkRequestMatchCallback(@onNull @allbackExecutor Executor executor, @NonNull NetworkRequestMatchCallback callback)3181 public void registerNetworkRequestMatchCallback(@NonNull @CallbackExecutor Executor executor, 3182 @NonNull NetworkRequestMatchCallback callback) { 3183 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 3184 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 3185 Log.v(TAG, "registerNetworkRequestMatchCallback: callback=" + callback 3186 + ", executor=" + executor); 3187 3188 try { 3189 synchronized (sNetworkRequestMatchCallbackMap) { 3190 INetworkRequestMatchCallback.Stub binderCallback = 3191 new NetworkRequestMatchCallbackProxy(executor, callback); 3192 sNetworkRequestMatchCallbackMap.put(System.identityHashCode(callback), 3193 binderCallback); 3194 mService.registerNetworkRequestMatchCallback(binderCallback); 3195 } 3196 } catch (RemoteException e) { 3197 throw e.rethrowFromSystemServer(); 3198 } 3199 } 3200 3201 /** 3202 * Unregisters a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. 3203 * <p> 3204 * Applications should have the 3205 * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers 3206 * without the permission will trigger a {@link java.lang.SecurityException}. 3207 * <p> 3208 * 3209 * @param callback Callback for network match events to unregister. 3210 * @hide 3211 */ 3212 @SystemApi 3213 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) unregisterNetworkRequestMatchCallback( @onNull NetworkRequestMatchCallback callback)3214 public void unregisterNetworkRequestMatchCallback( 3215 @NonNull NetworkRequestMatchCallback callback) { 3216 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 3217 Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback); 3218 3219 try { 3220 synchronized (sNetworkRequestMatchCallbackMap) { 3221 int callbackIdentifier = System.identityHashCode(callback); 3222 if (!sNetworkRequestMatchCallbackMap.contains(callbackIdentifier)) { 3223 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 3224 return; 3225 } 3226 mService.unregisterNetworkRequestMatchCallback( 3227 sNetworkRequestMatchCallbackMap.get(callbackIdentifier)); 3228 sNetworkRequestMatchCallbackMap.remove(callbackIdentifier); 3229 } 3230 } catch (RemoteException e) { 3231 throw e.rethrowFromSystemServer(); 3232 } 3233 } 3234 3235 /** 3236 * Privileged API to revoke all app state from wifi stack (equivalent to operations that the 3237 * wifi stack performs to clear state for an app that was uninstalled. 3238 * This removes: 3239 * <li> All saved networks or passpoint profiles added by the app </li> 3240 * <li> All previously approved peer to peer connection to access points initiated by the app 3241 * using {@link WifiNetworkSpecifier}</li> 3242 * <li> All network suggestions and approvals provided using {@link WifiNetworkSuggestion}</li> 3243 * <p> 3244 * @param targetAppUid UID of the app. 3245 * @param targetAppPackageName Package name of the app. 3246 * @hide 3247 */ 3248 @SystemApi 3249 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) removeAppState(int targetAppUid, @NonNull String targetAppPackageName)3250 public void removeAppState(int targetAppUid, @NonNull String targetAppPackageName) { 3251 try { 3252 mService.removeAppState(targetAppUid, targetAppPackageName); 3253 } catch (RemoteException e) { 3254 throw e.rethrowAsRuntimeException(); 3255 } 3256 } 3257 3258 /** 3259 * Provide a list of network suggestions to the device. See {@link WifiNetworkSuggestion} 3260 * for a detailed explanation of the parameters. 3261 * When the device decides to connect to one of the provided network suggestions, platform sends 3262 * a directed broadcast {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} to the app if 3263 * the network was created with 3264 * {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired(boolean)} flag set and the 3265 * app holds {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} 3266 * permission. 3267 *<p> 3268 * NOTE: 3269 * <ul> 3270 * <li> These networks are just a suggestion to the platform. The platform will ultimately 3271 * decide on which network the device connects to. </li> 3272 * <li> When an app is uninstalled or disabled, all its suggested networks are discarded. 3273 * If the device is currently connected to a suggested network which is being removed then the 3274 * device will disconnect from that network.</li> 3275 * <li> If user reset network settings, all added suggestions will be discarded. Apps can use 3276 * {@link #getNetworkSuggestions()} to check if their suggestions are in the device.</li> 3277 * <li> In-place modification of existing suggestions are allowed.</li> 3278 * <ul> 3279 * <li> If the provided suggestions include any previously provided suggestions by the app, 3280 * previous suggestions will be updated.</li> 3281 * <li>If one of the provided suggestions marks a previously unmetered suggestion as metered and 3282 * the device is currently connected to that suggested network, then the device will disconnect 3283 * from that network. The system will immediately re-evaluate all the network candidates 3284 * and possibly reconnect back to the same suggestion. This disconnect is to make sure that any 3285 * traffic flowing over unmetered networks isn't accidentally continued over a metered network. 3286 * </li> 3287 * <li> 3288 * On {@link android.os.Build.VERSION_CODES#TIRAMISU} or above If one of the provided 3289 * suggestions marks a previously trusted suggestion as untrusted and the device is currently 3290 * connected to that suggested network, then the device will disconnect from that network. The 3291 * system will immediately re-evaluate all the network candidates. This disconnect is to make 3292 * sure device will not remain connected to an untrusted network without a related 3293 * {@link android.net.NetworkRequest}. 3294 * </li> 3295 * </ul> 3296 * </ul> 3297 * 3298 * @param networkSuggestions List of network suggestions provided by the app. 3299 * @return Status code for the operation. One of the STATUS_NETWORK_SUGGESTIONS_ values. 3300 * @throws SecurityException if the caller is missing required permissions. 3301 * @see WifiNetworkSuggestion#equals(Object) 3302 */ 3303 @RequiresPermission(CHANGE_WIFI_STATE) addNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions)3304 public @NetworkSuggestionsStatusCode int addNetworkSuggestions( 3305 @NonNull List<WifiNetworkSuggestion> networkSuggestions) { 3306 try { 3307 return mService.addNetworkSuggestions( 3308 networkSuggestions, mContext.getOpPackageName(), mContext.getAttributionTag()); 3309 } catch (RemoteException e) { 3310 throw e.rethrowFromSystemServer(); 3311 } 3312 } 3313 3314 /** 3315 * Remove some or all of the network suggestions that were previously provided by the app. 3316 * If one of the suggestions being removed was used to establish connection to the current 3317 * network, then the device will immediately disconnect from that network. This method is same 3318 * as {@link #removeNetworkSuggestions(List, int)} with 3319 * {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT} 3320 * 3321 * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters. 3322 * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used. 3323 * <p></ 3324 * Note: Use {@link #removeNetworkSuggestions(List, int)}. An {@code action} of 3325 * {@link #ACTION_REMOVE_SUGGESTION_DISCONNECT} is equivalent to the current behavior. 3326 * 3327 * @param networkSuggestions List of network suggestions to be removed. Pass an empty list 3328 * to remove all the previous suggestions provided by the app. 3329 * @return Status code for the operation. One of the {@code STATUS_NETWORK_SUGGESTIONS_*} 3330 * values. Any matching suggestions are removed from the device and will not be considered for 3331 * any further connection attempts. 3332 */ 3333 @RequiresPermission(CHANGE_WIFI_STATE) removeNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions)3334 public @NetworkSuggestionsStatusCode int removeNetworkSuggestions( 3335 @NonNull List<WifiNetworkSuggestion> networkSuggestions) { 3336 return removeNetworkSuggestions(networkSuggestions, ACTION_REMOVE_SUGGESTION_DISCONNECT); 3337 } 3338 3339 /** 3340 * Remove some or all of the network suggestions that were previously provided by the app. 3341 * If one of the suggestions being removed was used to establish connection to the current 3342 * network, then the specified action will be executed. 3343 * 3344 * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters. 3345 * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used. 3346 * 3347 * @param networkSuggestions List of network suggestions to be removed. Pass an empty list 3348 * to remove all the previous suggestions provided by the app. 3349 * @param action Desired action to execute after removing the suggestion. One of 3350 * {@code ACTION_REMOVE_SUGGESTION_*} 3351 * @return Status code for the operation. One of the {@code STATUS_NETWORK_SUGGESTIONS_*} 3352 * values. Any matching suggestions are removed from the device and will not be considered for 3353 * further connection attempts. 3354 */ 3355 @RequiresPermission(CHANGE_WIFI_STATE) removeNetworkSuggestions( @onNull List<WifiNetworkSuggestion> networkSuggestions, @ActionAfterRemovingSuggestion int action)3356 public @NetworkSuggestionsStatusCode int removeNetworkSuggestions( 3357 @NonNull List<WifiNetworkSuggestion> networkSuggestions, 3358 @ActionAfterRemovingSuggestion int action) { 3359 try { 3360 return mService.removeNetworkSuggestions(networkSuggestions, 3361 mContext.getOpPackageName(), action); 3362 } catch (RemoteException e) { 3363 throw e.rethrowFromSystemServer(); 3364 } 3365 } 3366 3367 /** 3368 * Get all network suggestions provided by the calling app. 3369 * See {@link #addNetworkSuggestions(List)} 3370 * See {@link #removeNetworkSuggestions(List)} 3371 * @return a list of {@link WifiNetworkSuggestion} 3372 */ 3373 @RequiresPermission(ACCESS_WIFI_STATE) getNetworkSuggestions()3374 public @NonNull List<WifiNetworkSuggestion> getNetworkSuggestions() { 3375 try { 3376 return mService.getNetworkSuggestions(mContext.getOpPackageName()); 3377 } catch (RemoteException e) { 3378 throw e.rethrowAsRuntimeException(); 3379 } 3380 } 3381 3382 /** 3383 * Returns the max number of network suggestions that are allowed per app on the device. 3384 * @see #addNetworkSuggestions(List) 3385 * @see #removeNetworkSuggestions(List) 3386 */ getMaxNumberOfNetworkSuggestionsPerApp()3387 public int getMaxNumberOfNetworkSuggestionsPerApp() { 3388 return getMaxNumberOfNetworkSuggestionsPerApp( 3389 mContext.getSystemService(ActivityManager.class).isLowRamDevice()); 3390 } 3391 3392 /** @hide */ getMaxNumberOfNetworkSuggestionsPerApp(boolean isLowRamDevice)3393 public static int getMaxNumberOfNetworkSuggestionsPerApp(boolean isLowRamDevice) { 3394 return isLowRamDevice 3395 ? NETWORK_SUGGESTIONS_MAX_PER_APP_LOW_RAM 3396 : NETWORK_SUGGESTIONS_MAX_PER_APP_HIGH_RAM; 3397 } 3398 3399 /** 3400 * Add or update a Passpoint configuration. The configuration provides a credential 3401 * for connecting to Passpoint networks that are operated by the Passpoint 3402 * service provider specified in the configuration. 3403 * 3404 * Each configuration is uniquely identified by a unique key which depends on the contents of 3405 * the configuration. This allows the caller to install multiple profiles with the same FQDN 3406 * (Fully qualified domain name). Therefore, in order to update an existing profile, it is 3407 * first required to remove it using {@link WifiManager#removePasspointConfiguration(String)}. 3408 * Otherwise, a new profile will be added with both configuration. 3409 * 3410 * Deprecated for general app usage - except DO/PO apps. 3411 * See {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} to 3412 * create a passpoint suggestion. 3413 * See {@link #addNetworkSuggestions(List)}, {@link #removeNetworkSuggestions(List)} for new 3414 * API to add Wi-Fi networks for consideration when auto-connecting to wifi. 3415 * <b>Compatibility Note:</b> For applications targeting 3416 * {@link android.os.Build.VERSION_CODES#R} or above, this API will always fail and throw 3417 * {@link IllegalArgumentException}. 3418 * <p> 3419 * Deprecation Exemptions: 3420 * <ul> 3421 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3422 * </ul> 3423 * 3424 * @param config The Passpoint configuration to be added 3425 * @throws IllegalArgumentException if configuration is invalid or Passpoint is not enabled on 3426 * the device. 3427 */ addOrUpdatePasspointConfiguration(PasspointConfiguration config)3428 public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) { 3429 try { 3430 if (!mService.addOrUpdatePasspointConfiguration(config, mContext.getOpPackageName())) { 3431 throw new IllegalArgumentException(); 3432 } 3433 } catch (RemoteException e) { 3434 throw e.rethrowFromSystemServer(); 3435 } 3436 } 3437 3438 /** 3439 * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name) added 3440 * by the caller. 3441 * 3442 * @param fqdn The FQDN of the Passpoint configuration added by the caller to be removed 3443 * @throws IllegalArgumentException if no configuration is associated with the given FQDN or 3444 * Passpoint is not enabled on the device. 3445 * @deprecated This will be non-functional in a future release. 3446 * <br> 3447 * Requires {@code android.Manifest.permission.NETWORK_SETTINGS} or 3448 * {@code android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}. 3449 */ 3450 @Deprecated removePasspointConfiguration(String fqdn)3451 public void removePasspointConfiguration(String fqdn) { 3452 try { 3453 if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) { 3454 throw new IllegalArgumentException(); 3455 } 3456 } catch (RemoteException e) { 3457 throw e.rethrowFromSystemServer(); 3458 } 3459 } 3460 3461 /** 3462 * Return the list of installed Passpoint configurations added by the caller. 3463 * 3464 * An empty list will be returned when no configurations are installed. 3465 * 3466 * @return A list of {@link PasspointConfiguration} added by the caller 3467 * @deprecated This will be non-functional in a future release. 3468 * <br> 3469 * Requires {@code android.Manifest.permission.NETWORK_SETTINGS} or 3470 * {@code android.Manifest.permission.NETWORK_SETUP_WIZARD}. 3471 */ 3472 @Deprecated getPasspointConfigurations()3473 public List<PasspointConfiguration> getPasspointConfigurations() { 3474 try { 3475 return mService.getPasspointConfigurations(mContext.getOpPackageName()); 3476 } catch (RemoteException e) { 3477 throw e.rethrowFromSystemServer(); 3478 } 3479 } 3480 3481 /** 3482 * Query for a Hotspot 2.0 release 2 OSU icon file. An {@link #ACTION_PASSPOINT_ICON} intent 3483 * will be broadcasted once the request is completed. The presence of the intent extra 3484 * {@link #EXTRA_ICON} will indicate the result of the request. 3485 * A missing intent extra {@link #EXTRA_ICON} will indicate a failure. 3486 * 3487 * @param bssid The BSSID of the AP 3488 * @param fileName Name of the icon file (remote file) to query from the AP 3489 * 3490 * @throws UnsupportedOperationException if Passpoint is not enabled on the device. 3491 * @hide 3492 */ queryPasspointIcon(long bssid, String fileName)3493 public void queryPasspointIcon(long bssid, String fileName) { 3494 try { 3495 mService.queryPasspointIcon(bssid, fileName); 3496 } catch (RemoteException e) { 3497 throw e.rethrowFromSystemServer(); 3498 } 3499 } 3500 3501 /** 3502 * Match the currently associated network against the SP matching the given FQDN 3503 * @param fqdn FQDN of the SP 3504 * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined] 3505 * @hide 3506 */ matchProviderWithCurrentNetwork(String fqdn)3507 public int matchProviderWithCurrentNetwork(String fqdn) { 3508 try { 3509 return mService.matchProviderWithCurrentNetwork(fqdn); 3510 } catch (RemoteException e) { 3511 throw e.rethrowFromSystemServer(); 3512 } 3513 } 3514 3515 /** 3516 * Remove the specified network from the list of configured networks. 3517 * This may result in the asynchronous delivery of state change 3518 * events. 3519 * 3520 * Applications are not allowed to remove networks created by other 3521 * applications. 3522 * 3523 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 3524 * #getConfiguredNetworks}. 3525 * @return {@code true} if the operation succeeded 3526 * 3527 * @deprecated 3528 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3529 * mechanism to trigger connection to a Wi-Fi network. 3530 * b) See {@link #addNetworkSuggestions(List)}, 3531 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3532 * when auto-connecting to wifi. 3533 * <b>Compatibility Note:</b> For applications targeting 3534 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3535 * {@code false}. 3536 * <p> 3537 * Deprecation Exemptions: 3538 * <ul> 3539 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3540 * </ul> 3541 */ 3542 @Deprecated removeNetwork(int netId)3543 public boolean removeNetwork(int netId) { 3544 try { 3545 return mService.removeNetwork(netId, mContext.getOpPackageName()); 3546 } catch (RemoteException e) { 3547 throw e.rethrowFromSystemServer(); 3548 } 3549 } 3550 3551 /** 3552 * Remove all configured networks that were not created by the calling app. Can only 3553 * be called by a Device Owner (DO) app. 3554 * 3555 * @return {@code true} if at least one network is removed, {@code false} otherwise 3556 * @throws SecurityException if the caller is not a Device Owner app 3557 */ 3558 @RequiresPermission(CHANGE_WIFI_STATE) removeNonCallerConfiguredNetworks()3559 public boolean removeNonCallerConfiguredNetworks() { 3560 try { 3561 return mService.removeNonCallerConfiguredNetworks(mContext.getOpPackageName()); 3562 } catch (RemoteException e) { 3563 throw e.rethrowFromSystemServer(); 3564 } 3565 } 3566 /** 3567 * Allow a previously configured network to be associated with. If 3568 * <code>attemptConnect</code> is true, an attempt to connect to the selected 3569 * network is initiated. This may result in the asynchronous delivery 3570 * of state change events. 3571 * <p> 3572 * <b>Note:</b> Network communication may not use Wi-Fi even if Wi-Fi is connected; 3573 * traffic may instead be sent through another network, such as cellular data, 3574 * Bluetooth tethering, or Ethernet. For example, traffic will never use a 3575 * Wi-Fi network that does not provide Internet access (e.g. a wireless 3576 * printer), if another network that does offer Internet access (e.g. 3577 * cellular data) is available. Applications that need to ensure that their 3578 * network traffic uses Wi-Fi should use APIs such as 3579 * {@link Network#bindSocket(java.net.Socket)}, 3580 * {@link Network#openConnection(java.net.URL)}, or 3581 * {@link ConnectivityManager#bindProcessToNetwork} to do so. 3582 * 3583 * Applications are not allowed to enable networks created by other 3584 * applications. 3585 * 3586 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 3587 * #getConfiguredNetworks}. 3588 * @param attemptConnect The way to select a particular network to connect to is specify 3589 * {@code true} for this parameter. 3590 * @return {@code true} if the operation succeeded 3591 * 3592 * @deprecated 3593 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3594 * mechanism to trigger connection to a Wi-Fi network. 3595 * b) See {@link #addNetworkSuggestions(List)}, 3596 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3597 * when auto-connecting to wifi. 3598 * <b>Compatibility Note:</b> For applications targeting 3599 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3600 * {@code false}. 3601 * Deprecation Exemptions: 3602 * <ul> 3603 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3604 * </ul> 3605 */ 3606 @Deprecated enableNetwork(int netId, boolean attemptConnect)3607 public boolean enableNetwork(int netId, boolean attemptConnect) { 3608 try { 3609 return mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName()); 3610 } catch (RemoteException e) { 3611 throw e.rethrowFromSystemServer(); 3612 } 3613 } 3614 3615 /** 3616 * Disable a configured network. The specified network will not be 3617 * a candidate for associating. This may result in the asynchronous 3618 * delivery of state change events. 3619 * 3620 * Applications are not allowed to disable networks created by other 3621 * applications. 3622 * 3623 * @param netId the ID of the network as returned by {@link #addNetwork} or {@link 3624 * #getConfiguredNetworks}. 3625 * @return {@code true} if the operation succeeded 3626 * 3627 * @deprecated 3628 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3629 * mechanism to trigger connection to a Wi-Fi network. 3630 * b) See {@link #addNetworkSuggestions(List)}, 3631 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3632 * when auto-connecting to wifi. 3633 * <b>Compatibility Note:</b> For applications targeting 3634 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3635 * {@code false}. 3636 * <p> 3637 * Deprecation Exemptions: 3638 * <ul> 3639 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3640 * </ul> 3641 */ 3642 @Deprecated disableNetwork(int netId)3643 public boolean disableNetwork(int netId) { 3644 try { 3645 return mService.disableNetwork(netId, mContext.getOpPackageName()); 3646 } catch (RemoteException e) { 3647 throw e.rethrowFromSystemServer(); 3648 } 3649 } 3650 3651 /** 3652 * Disassociate from the currently active access point. This may result 3653 * in the asynchronous delivery of state change events. 3654 * @return {@code true} if the operation succeeded 3655 * 3656 * @deprecated 3657 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3658 * mechanism to trigger connection to a Wi-Fi network. 3659 * b) See {@link #addNetworkSuggestions(List)}, 3660 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3661 * when auto-connecting to wifi. 3662 * <b>Compatibility Note:</b> For applications targeting 3663 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3664 * {@code false}. 3665 * <p> 3666 * Deprecation Exemptions: 3667 * <ul> 3668 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3669 * </ul> 3670 */ 3671 @Deprecated disconnect()3672 public boolean disconnect() { 3673 try { 3674 return mService.disconnect(mContext.getOpPackageName()); 3675 } catch (RemoteException e) { 3676 throw e.rethrowFromSystemServer(); 3677 } 3678 } 3679 3680 /** 3681 * Reconnect to the currently active access point, if we are currently 3682 * disconnected. This may result in the asynchronous delivery of state 3683 * change events. 3684 * @return {@code true} if the operation succeeded 3685 * 3686 * @deprecated 3687 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3688 * mechanism to trigger connection to a Wi-Fi network. 3689 * b) See {@link #addNetworkSuggestions(List)}, 3690 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3691 * when auto-connecting to wifi. 3692 * <b>Compatibility Note:</b> For applications targeting 3693 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 3694 * {@code false}. 3695 * <p> 3696 * Deprecation Exemptions: 3697 * <ul> 3698 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 3699 * </ul> 3700 */ 3701 @Deprecated reconnect()3702 public boolean reconnect() { 3703 try { 3704 return mService.reconnect(mContext.getOpPackageName()); 3705 } catch (RemoteException e) { 3706 throw e.rethrowFromSystemServer(); 3707 } 3708 } 3709 3710 /** 3711 * Reconnect to the currently active access point, even if we are already 3712 * connected. This may result in the asynchronous delivery of state 3713 * change events. 3714 * @return {@code true} if the operation succeeded 3715 * 3716 * @deprecated 3717 * a) See {@link WifiNetworkSpecifier.Builder#build()} for new 3718 * mechanism to trigger connection to a Wi-Fi network. 3719 * b) See {@link #addNetworkSuggestions(List)}, 3720 * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration 3721 * when auto-connecting to wifi. 3722 * <b>Compatibility Note:</b> For applications targeting 3723 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. 3724 */ 3725 @Deprecated reassociate()3726 public boolean reassociate() { 3727 try { 3728 return mService.reassociate(mContext.getOpPackageName()); 3729 } catch (RemoteException e) { 3730 throw e.rethrowFromSystemServer(); 3731 } 3732 } 3733 3734 /** 3735 * Check that the supplicant daemon is responding to requests. 3736 * @return {@code true} if we were able to communicate with the supplicant and 3737 * it returned the expected response to the PING message. 3738 * @deprecated Will return the output of {@link #isWifiEnabled()} instead. 3739 */ 3740 @Deprecated pingSupplicant()3741 public boolean pingSupplicant() { 3742 return isWifiEnabled(); 3743 } 3744 3745 /** @hide */ 3746 public static final long WIFI_FEATURE_INFRA = 1L << 0; // Basic infrastructure mode 3747 /** @hide */ 3748 public static final long WIFI_FEATURE_PASSPOINT = 1L << 2; // Support for GAS/ANQP 3749 /** @hide */ 3750 public static final long WIFI_FEATURE_P2P = 1L << 3; // Wifi-Direct 3751 /** @hide */ 3752 public static final long WIFI_FEATURE_MOBILE_HOTSPOT = 1L << 4; // Soft AP 3753 /** @hide */ 3754 public static final long WIFI_FEATURE_SCANNER = 1L << 5; // WifiScanner APIs 3755 /** @hide */ 3756 public static final long WIFI_FEATURE_AWARE = 1L << 6; // Wi-Fi Aware networking 3757 /** @hide */ 3758 public static final long WIFI_FEATURE_D2D_RTT = 1L << 7; // Device-to-device RTT 3759 /** @hide */ 3760 public static final long WIFI_FEATURE_D2AP_RTT = 1L << 8; // Device-to-AP RTT 3761 /** @hide */ 3762 public static final long WIFI_FEATURE_PNO = 1L << 10; // Preferred network offload 3763 /** @hide */ 3764 public static final long WIFI_FEATURE_TDLS = 1L << 12; // Tunnel directed link setup 3765 /** @hide */ 3766 public static final long WIFI_FEATURE_TDLS_OFFCHANNEL = 1L << 13; // TDLS off channel 3767 /** @hide */ 3768 public static final long WIFI_FEATURE_AP_STA = 1L << 15; // AP STA Concurrency 3769 /** @hide */ 3770 public static final long WIFI_FEATURE_LINK_LAYER_STATS = 1L << 16; // Link layer stats 3771 /** @hide */ 3772 public static final long WIFI_FEATURE_LOGGER = 1L << 17; // WiFi Logger 3773 /** @hide */ 3774 public static final long WIFI_FEATURE_RSSI_MONITOR = 1L << 19; // RSSI Monitor 3775 /** @hide */ 3776 public static final long WIFI_FEATURE_MKEEP_ALIVE = 1L << 20; // mkeep_alive 3777 /** @hide */ 3778 public static final long WIFI_FEATURE_CONFIG_NDO = 1L << 21; // ND offload 3779 /** @hide */ 3780 public static final long WIFI_FEATURE_CONTROL_ROAMING = 1L << 23; // Control firmware roaming 3781 /** @hide */ 3782 public static final long WIFI_FEATURE_IE_WHITELIST = 1L << 24; // Probe IE white listing 3783 /** @hide */ 3784 public static final long WIFI_FEATURE_SCAN_RAND = 1L << 25; // Random MAC & Probe seq 3785 /** @hide */ 3786 public static final long WIFI_FEATURE_TX_POWER_LIMIT = 1L << 26; // Set Tx power limit 3787 /** @hide */ 3788 public static final long WIFI_FEATURE_WPA3_SAE = 1L << 27; // WPA3-Personal SAE 3789 /** @hide */ 3790 public static final long WIFI_FEATURE_WPA3_SUITE_B = 1L << 28; // WPA3-Enterprise Suite-B 3791 /** @hide */ 3792 public static final long WIFI_FEATURE_OWE = 1L << 29; // Enhanced Open 3793 /** @hide */ 3794 public static final long WIFI_FEATURE_LOW_LATENCY = 1L << 30; // Low Latency modes 3795 /** @hide */ 3796 public static final long WIFI_FEATURE_DPP = 1L << 31; // DPP (Easy-Connect) 3797 /** @hide */ 3798 public static final long WIFI_FEATURE_P2P_RAND_MAC = 1L << 32; // Random P2P MAC 3799 /** @hide */ 3800 public static final long WIFI_FEATURE_CONNECTED_RAND_MAC = 1L << 33; // Random STA MAC 3801 /** @hide */ 3802 public static final long WIFI_FEATURE_AP_RAND_MAC = 1L << 34; // Random AP MAC 3803 /** @hide */ 3804 public static final long WIFI_FEATURE_MBO = 1L << 35; // MBO Support 3805 /** @hide */ 3806 public static final long WIFI_FEATURE_OCE = 1L << 36; // OCE Support 3807 /** @hide */ 3808 public static final long WIFI_FEATURE_WAPI = 1L << 37; // WAPI 3809 3810 /** @hide */ 3811 public static final long WIFI_FEATURE_FILS_SHA256 = 1L << 38; // FILS-SHA256 3812 3813 /** @hide */ 3814 public static final long WIFI_FEATURE_FILS_SHA384 = 1L << 39; // FILS-SHA384 3815 3816 /** @hide */ 3817 public static final long WIFI_FEATURE_SAE_PK = 1L << 40; // SAE-PK 3818 3819 /** @hide */ 3820 public static final long WIFI_FEATURE_STA_BRIDGED_AP = 1L << 41; // STA + Bridged AP 3821 3822 /** @hide */ 3823 public static final long WIFI_FEATURE_BRIDGED_AP = 1L << 42; // Bridged AP 3824 3825 /** @hide */ 3826 public static final long WIFI_FEATURE_INFRA_60G = 1L << 43; // 60 GHz Band Support 3827 3828 /** 3829 * Support for 2 STA's for the local-only (peer to peer) connection + internet connection 3830 * concurrency. 3831 * @hide 3832 */ 3833 public static final long WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 1L << 44; 3834 3835 /** 3836 * Support for 2 STA's for the make before break concurrency. 3837 * @hide 3838 */ 3839 public static final long WIFI_FEATURE_ADDITIONAL_STA_MBB = 1L << 45; 3840 3841 /** 3842 * Support for 2 STA's for the restricted connection + internet connection concurrency. 3843 * @hide 3844 */ 3845 public static final long WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 1L << 46; 3846 3847 /** 3848 * DPP (Easy-Connect) Enrollee Responder mode support 3849 * @hide 3850 */ 3851 public static final long WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 1L << 47; 3852 3853 /** 3854 * Passpoint Terms and Conditions feature support 3855 * @hide 3856 */ 3857 public static final long WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 1L << 48; 3858 3859 /** @hide */ 3860 public static final long WIFI_FEATURE_SAE_H2E = 1L << 49; // Hash-to-Element 3861 3862 /** @hide */ 3863 public static final long WIFI_FEATURE_WFD_R2 = 1L << 50; // Wi-Fi Display R2 3864 3865 /** 3866 * RFC 7542 decorated identity support 3867 * @hide */ 3868 public static final long WIFI_FEATURE_DECORATED_IDENTITY = 1L << 51; 3869 3870 /** 3871 * Trust On First Use support for WPA Enterprise network 3872 * @hide 3873 */ 3874 public static final long WIFI_FEATURE_TRUST_ON_FIRST_USE = 1L << 52; 3875 3876 /** 3877 * Support for 2 STA's multi internet concurrency. 3878 * @hide 3879 */ 3880 public static final long WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 1L << 53; 3881 3882 /** 3883 * Support for DPP (Easy-Connect) AKM. 3884 * @hide 3885 */ 3886 public static final long WIFI_FEATURE_DPP_AKM = 1L << 54; 3887 3888 /** 3889 * Support for setting TLS minimum version. 3890 * @hide 3891 */ 3892 public static final long WIFI_FEATURE_SET_TLS_MINIMUM_VERSION = 1L << 55; 3893 3894 /** 3895 * Support for TLS v.13. 3896 * @hide 3897 */ 3898 public static final long WIFI_FEATURE_TLS_V1_3 = 1L << 56; 3899 3900 /** 3901 * Support for Dual Band Simultaneous (DBS) operation. 3902 * @hide 3903 */ 3904 public static final long WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS = 1L << 57; 3905 /** 3906 * Support for TID-To-Link Mapping negotiation. 3907 * @hide 3908 */ 3909 public static final long WIFI_FEATURE_T2LM_NEGOTIATION = 1L << 58; 3910 getSupportedFeatures()3911 private long getSupportedFeatures() { 3912 try { 3913 return mService.getSupportedFeatures(); 3914 } catch (RemoteException e) { 3915 throw e.rethrowFromSystemServer(); 3916 } 3917 } 3918 isFeatureSupported(long feature)3919 private boolean isFeatureSupported(long feature) { 3920 return (getSupportedFeatures() & feature) == feature; 3921 } 3922 3923 /** 3924 * @return true if this adapter supports Passpoint 3925 * @hide 3926 */ isPasspointSupported()3927 public boolean isPasspointSupported() { 3928 return isFeatureSupported(WIFI_FEATURE_PASSPOINT); 3929 } 3930 3931 /** 3932 * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct) 3933 */ isP2pSupported()3934 public boolean isP2pSupported() { 3935 return isFeatureSupported(WIFI_FEATURE_P2P); 3936 } 3937 3938 /** 3939 * @return true if this adapter supports portable Wi-Fi hotspot 3940 * @hide 3941 */ 3942 @SystemApi isPortableHotspotSupported()3943 public boolean isPortableHotspotSupported() { 3944 return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT); 3945 } 3946 3947 /** 3948 * @return true if this adapter supports WifiScanner APIs 3949 * @hide 3950 */ 3951 @SystemApi isWifiScannerSupported()3952 public boolean isWifiScannerSupported() { 3953 return isFeatureSupported(WIFI_FEATURE_SCANNER); 3954 } 3955 3956 /** 3957 * @return true if this adapter supports Neighbour Awareness Network APIs 3958 * @hide 3959 */ isWifiAwareSupported()3960 public boolean isWifiAwareSupported() { 3961 return isFeatureSupported(WIFI_FEATURE_AWARE); 3962 } 3963 3964 /** 3965 * Query whether or not the device supports Station (STA) + Access point (AP) concurrency. 3966 * 3967 * @return true if this device supports STA + AP concurrency, false otherwise. 3968 */ isStaApConcurrencySupported()3969 public boolean isStaApConcurrencySupported() { 3970 return isFeatureSupported(WIFI_FEATURE_AP_STA); 3971 } 3972 3973 /** 3974 * Query whether or not the device supports concurrent station (STA) connections for local-only 3975 * connections using {@link WifiNetworkSpecifier}. 3976 * 3977 * @return true if this device supports multiple STA concurrency for this use-case, false 3978 * otherwise. 3979 */ isStaConcurrencyForLocalOnlyConnectionsSupported()3980 public boolean isStaConcurrencyForLocalOnlyConnectionsSupported() { 3981 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY); 3982 } 3983 3984 /** 3985 * Query whether or not the device supports concurrent station (STA) connections for 3986 * make-before-break wifi to wifi switching. 3987 * 3988 * Note: This is an internal feature which is not available to apps. 3989 * 3990 * @return true if this device supports multiple STA concurrency for this use-case, false 3991 * otherwise. 3992 */ isMakeBeforeBreakWifiSwitchingSupported()3993 public boolean isMakeBeforeBreakWifiSwitchingSupported() { 3994 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_MBB); 3995 } 3996 3997 /** 3998 * Query whether or not the device supports concurrent station (STA) connections for multi 3999 * internet connections. 4000 * 4001 * @return true if this device supports multiple STA concurrency for this use-case, false 4002 * otherwise. 4003 */ 4004 @RequiresApi(Build.VERSION_CODES.TIRAMISU) isStaConcurrencyForMultiInternetSupported()4005 public boolean isStaConcurrencyForMultiInternetSupported() { 4006 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET); 4007 } 4008 4009 /** 4010 * Query whether or not the device supports concurrent station (STA) connections for restricted 4011 * connections using {@link WifiNetworkSuggestion.Builder#setOemPaid(boolean)} / 4012 * {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)}. 4013 * 4014 * @return true if this device supports multiple STA concurrency for this use-case, false 4015 * otherwise. 4016 * @hide 4017 */ 4018 @SystemApi isStaConcurrencyForRestrictedConnectionsSupported()4019 public boolean isStaConcurrencyForRestrictedConnectionsSupported() { 4020 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED); 4021 } 4022 4023 /** 4024 * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)} 4025 * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT} and 4026 * {@link android.content.pm.PackageManager#FEATURE_WIFI_AWARE}. 4027 * 4028 * @return true if this adapter supports Device-to-device RTT 4029 * @hide 4030 */ 4031 @Deprecated 4032 @SystemApi isDeviceToDeviceRttSupported()4033 public boolean isDeviceToDeviceRttSupported() { 4034 return isFeatureSupported(WIFI_FEATURE_D2D_RTT); 4035 } 4036 4037 /** 4038 * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)} 4039 * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT}. 4040 * 4041 * @return true if this adapter supports Device-to-AP RTT 4042 */ 4043 @Deprecated isDeviceToApRttSupported()4044 public boolean isDeviceToApRttSupported() { 4045 return isFeatureSupported(WIFI_FEATURE_D2AP_RTT); 4046 } 4047 4048 /** 4049 * @return true if this adapter supports offloaded connectivity scan 4050 */ isPreferredNetworkOffloadSupported()4051 public boolean isPreferredNetworkOffloadSupported() { 4052 return isFeatureSupported(WIFI_FEATURE_PNO); 4053 } 4054 4055 /** 4056 * @return true if this adapter supports Tunnel Directed Link Setup 4057 */ isTdlsSupported()4058 public boolean isTdlsSupported() { 4059 return isFeatureSupported(WIFI_FEATURE_TDLS); 4060 } 4061 4062 /** 4063 * @return true if this adapter supports Off Channel Tunnel Directed Link Setup 4064 * @hide 4065 */ isOffChannelTdlsSupported()4066 public boolean isOffChannelTdlsSupported() { 4067 return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL); 4068 } 4069 4070 /** 4071 * @return true if this adapter supports advanced power/performance counters 4072 */ isEnhancedPowerReportingSupported()4073 public boolean isEnhancedPowerReportingSupported() { 4074 return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS); 4075 } 4076 4077 /** 4078 * @return true if this device supports connected MAC randomization. 4079 * @hide 4080 */ 4081 @SystemApi isConnectedMacRandomizationSupported()4082 public boolean isConnectedMacRandomizationSupported() { 4083 return isFeatureSupported(WIFI_FEATURE_CONNECTED_RAND_MAC); 4084 } 4085 4086 /** 4087 * @return true if this device supports AP MAC randomization. 4088 * @hide 4089 */ 4090 @SystemApi isApMacRandomizationSupported()4091 public boolean isApMacRandomizationSupported() { 4092 return isFeatureSupported(WIFI_FEATURE_AP_RAND_MAC); 4093 } 4094 4095 /** 4096 * Check if the chipset supports 2.4GHz band. 4097 * @return {@code true} if supported, {@code false} otherwise. 4098 */ is24GHzBandSupported()4099 public boolean is24GHzBandSupported() { 4100 try { 4101 return mService.is24GHzBandSupported(); 4102 } catch (RemoteException e) { 4103 throw e.rethrowFromSystemServer(); 4104 } 4105 } 4106 4107 /** 4108 * Check if the chipset supports 5GHz band. 4109 * @return {@code true} if supported, {@code false} otherwise. 4110 */ is5GHzBandSupported()4111 public boolean is5GHzBandSupported() { 4112 try { 4113 return mService.is5GHzBandSupported(); 4114 } catch (RemoteException e) { 4115 throw e.rethrowFromSystemServer(); 4116 } 4117 } 4118 4119 /** 4120 * Check if the chipset supports the 60GHz frequency band. 4121 * 4122 * @return {@code true} if supported, {@code false} otherwise. 4123 */ 4124 @RequiresApi(Build.VERSION_CODES.S) is60GHzBandSupported()4125 public boolean is60GHzBandSupported() { 4126 try { 4127 return mService.is60GHzBandSupported(); 4128 } catch (RemoteException e) { 4129 throw e.rethrowFromSystemServer(); 4130 } 4131 } 4132 4133 /** 4134 * Check if the chipset supports 6GHz band. 4135 * @return {@code true} if supported, {@code false} otherwise. 4136 */ is6GHzBandSupported()4137 public boolean is6GHzBandSupported() { 4138 try { 4139 return mService.is6GHzBandSupported(); 4140 } catch (RemoteException e) { 4141 throw e.rethrowFromSystemServer(); 4142 } 4143 } 4144 4145 /** 4146 * Check if the chipset supports a certain Wi-Fi standard. 4147 * @param standard the IEEE 802.11 standard to check on. 4148 * valid values from {@link ScanResult}'s {@code WIFI_STANDARD_} 4149 * @return {@code true} if supported, {@code false} otherwise. 4150 */ isWifiStandardSupported(@ifiAnnotations.WifiStandard int standard)4151 public boolean isWifiStandardSupported(@WifiAnnotations.WifiStandard int standard) { 4152 try { 4153 return mService.isWifiStandardSupported(standard); 4154 } catch (RemoteException e) { 4155 throw e.rethrowFromSystemServer(); 4156 } 4157 } 4158 4159 /** 4160 * Query whether or not the device supports concurrency of Station (STA) + multiple access 4161 * points (AP) (where the APs bridged together). 4162 * 4163 * See {@link SoftApConfiguration.Builder#setBands(int[])} 4164 * or {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)} to configure 4165 * bridged AP when the bridged AP supported. 4166 * 4167 * @return true if this device supports concurrency of STA + multiple APs which are bridged 4168 * together, false otherwise. 4169 */ isStaBridgedApConcurrencySupported()4170 public boolean isStaBridgedApConcurrencySupported() { 4171 return isFeatureSupported(WIFI_FEATURE_STA_BRIDGED_AP); 4172 } 4173 4174 /** 4175 * Query whether or not the device supports multiple Access point (AP) which are bridged 4176 * together. 4177 * 4178 * See {@link SoftApConfiguration.Builder#setBands(int[])} 4179 * or {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)} to configure 4180 * bridged AP when the bridged AP supported. 4181 * 4182 * @return true if this device supports concurrency of multiple AP which bridged together, 4183 * false otherwise. 4184 */ isBridgedApConcurrencySupported()4185 public boolean isBridgedApConcurrencySupported() { 4186 return isFeatureSupported(WIFI_FEATURE_BRIDGED_AP); 4187 } 4188 4189 /** 4190 * Interface for Wi-Fi activity energy info listener. Should be implemented by applications and 4191 * set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}. 4192 * 4193 * @hide 4194 */ 4195 @SystemApi 4196 public interface OnWifiActivityEnergyInfoListener { 4197 /** 4198 * Called when Wi-Fi activity energy info is available. 4199 * Note: this listener is triggered at most once for each call to 4200 * {@link #getWifiActivityEnergyInfoAsync}. 4201 * 4202 * @param info the latest {@link WifiActivityEnergyInfo}, or null if unavailable. 4203 */ onWifiActivityEnergyInfo(@ullable WifiActivityEnergyInfo info)4204 void onWifiActivityEnergyInfo(@Nullable WifiActivityEnergyInfo info); 4205 } 4206 4207 private static class OnWifiActivityEnergyInfoProxy 4208 extends IOnWifiActivityEnergyInfoListener.Stub { 4209 private final Object mLock = new Object(); 4210 @Nullable @GuardedBy("mLock") private Executor mExecutor; 4211 @Nullable @GuardedBy("mLock") private OnWifiActivityEnergyInfoListener mListener; 4212 OnWifiActivityEnergyInfoProxy(Executor executor, OnWifiActivityEnergyInfoListener listener)4213 OnWifiActivityEnergyInfoProxy(Executor executor, 4214 OnWifiActivityEnergyInfoListener listener) { 4215 mExecutor = executor; 4216 mListener = listener; 4217 } 4218 4219 @Override onWifiActivityEnergyInfo(WifiActivityEnergyInfo info)4220 public void onWifiActivityEnergyInfo(WifiActivityEnergyInfo info) { 4221 Executor executor; 4222 OnWifiActivityEnergyInfoListener listener; 4223 synchronized (mLock) { 4224 if (mExecutor == null || mListener == null) { 4225 return; 4226 } 4227 executor = mExecutor; 4228 listener = mListener; 4229 // null out to allow garbage collection, prevent triggering listener more than once 4230 mExecutor = null; 4231 mListener = null; 4232 } 4233 Binder.clearCallingIdentity(); 4234 executor.execute(() -> listener.onWifiActivityEnergyInfo(info)); 4235 } 4236 } 4237 4238 /** 4239 * Request to get the current {@link WifiActivityEnergyInfo} asynchronously. 4240 * Note: This method will return null if {@link #isEnhancedPowerReportingSupported()} returns 4241 * false. 4242 * 4243 * @param executor the executor that the listener will be invoked on 4244 * @param listener the listener that will receive the {@link WifiActivityEnergyInfo} object 4245 * when it becomes available. The listener will be triggered at most once for 4246 * each call to this method. 4247 * 4248 * @hide 4249 */ 4250 @SystemApi 4251 @RequiresPermission(ACCESS_WIFI_STATE) getWifiActivityEnergyInfoAsync( @onNull @allbackExecutor Executor executor, @NonNull OnWifiActivityEnergyInfoListener listener)4252 public void getWifiActivityEnergyInfoAsync( 4253 @NonNull @CallbackExecutor Executor executor, 4254 @NonNull OnWifiActivityEnergyInfoListener listener) { 4255 Objects.requireNonNull(executor, "executor cannot be null"); 4256 Objects.requireNonNull(listener, "listener cannot be null"); 4257 try { 4258 mService.getWifiActivityEnergyInfoAsync( 4259 new OnWifiActivityEnergyInfoProxy(executor, listener)); 4260 } catch (RemoteException e) { 4261 throw e.rethrowFromSystemServer(); 4262 } 4263 } 4264 4265 /** 4266 * Request a scan for access points. Returns immediately. The availability 4267 * of the results is made known later by means of an asynchronous event sent 4268 * on completion of the scan. 4269 * <p> 4270 * To initiate a Wi-Fi scan, declare the 4271 * {@link android.Manifest.permission#CHANGE_WIFI_STATE} 4272 * permission in the manifest, and perform these steps: 4273 * </p> 4274 * <ol style="1"> 4275 * <li>Invoke the following method: 4276 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).startScan()}</li> 4277 * <li> 4278 * Register a BroadcastReceiver to listen to 4279 * {@code SCAN_RESULTS_AVAILABLE_ACTION}.</li> 4280 * <li>When a broadcast is received, call: 4281 * {@code ((WifiManager) getSystemService(WIFI_SERVICE)).getScanResults()}</li> 4282 * </ol> 4283 * @return {@code true} if the operation succeeded, i.e., the scan was initiated. 4284 * @deprecated The ability for apps to trigger scan requests will be removed in a future 4285 * release. 4286 */ 4287 @Deprecated startScan()4288 public boolean startScan() { 4289 return startScan(null); 4290 } 4291 4292 /** @hide */ 4293 @SystemApi 4294 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) startScan(WorkSource workSource)4295 public boolean startScan(WorkSource workSource) { 4296 try { 4297 String packageName = mContext.getOpPackageName(); 4298 String attributionTag = mContext.getAttributionTag(); 4299 return mService.startScan(packageName, attributionTag); 4300 } catch (RemoteException e) { 4301 throw e.rethrowFromSystemServer(); 4302 } 4303 } 4304 4305 /** 4306 * WPS has been deprecated from Client mode operation. 4307 * 4308 * @return null 4309 * @hide 4310 * @deprecated This API is deprecated 4311 */ getCurrentNetworkWpsNfcConfigurationToken()4312 public String getCurrentNetworkWpsNfcConfigurationToken() { 4313 return null; 4314 } 4315 4316 /** 4317 * Return dynamic information about the current Wi-Fi connection, if any is active. 4318 * <p> 4319 * 4320 * @return the Wi-Fi information, contained in {@link WifiInfo}. 4321 * 4322 * @deprecated Starting with {@link Build.VERSION_CODES#S}, WifiInfo retrieval is moved to 4323 * {@link ConnectivityManager} API surface. WifiInfo is attached in 4324 * {@link NetworkCapabilities#getTransportInfo()} which is available via callback in 4325 * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} or on-demand from 4326 * {@link ConnectivityManager#getNetworkCapabilities(Network)}. 4327 * 4328 *</p> 4329 * Usage example: 4330 * <pre> 4331 * final NetworkRequest request = 4332 * new NetworkRequest.Builder() 4333 * .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 4334 * .build(); 4335 * final ConnectivityManager connectivityManager = 4336 * context.getSystemService(ConnectivityManager.class); 4337 * final NetworkCallback networkCallback = new NetworkCallback() { 4338 * ... 4339 * @Override 4340 * void onAvailable(Network network) {} 4341 * 4342 * @Override 4343 * void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { 4344 * WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo(); 4345 * } 4346 * // etc. 4347 * }; 4348 * connectivityManager.requestNetwork(request, networkCallback); // For request 4349 * connectivityManager.registerNetworkCallback(request, networkCallback); // For listen 4350 * </pre> 4351 * <p> 4352 * <b>Compatibility Notes:</b> 4353 * <li>Apps can continue using this API, however newer features 4354 * such as ability to mask out location sensitive data in WifiInfo will not be supported 4355 * via this API. </li> 4356 * <li>On devices supporting concurrent connections (indicated via 4357 * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc) this API will return 4358 * the details of the internet providing connection (if any) to all apps, except for the apps 4359 * that triggered the creation of the concurrent connection. For such apps, this API will return 4360 * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will 4361 * trigger a concurrent connection on supported devices and hence this API will provide 4362 * details of their peer to peer connection (not the internet providing connection). This 4363 * is to maintain backwards compatibility with behavior on single STA devices.</li> 4364 * </p> 4365 */ 4366 @Deprecated 4367 @RequiresPermission(allOf = {ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION}, conditional = true) getConnectionInfo()4368 public WifiInfo getConnectionInfo() { 4369 try { 4370 return mService.getConnectionInfo(mContext.getOpPackageName(), 4371 mContext.getAttributionTag()); 4372 } catch (RemoteException e) { 4373 throw e.rethrowFromSystemServer(); 4374 } 4375 } 4376 4377 /** 4378 * Return the results of the latest access point scan. 4379 * @return the list of access points found in the most recent scan. An app must hold 4380 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission 4381 * and {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission 4382 * in order to get valid results. 4383 */ 4384 @RequiresPermission(allOf = {ACCESS_WIFI_STATE, ACCESS_FINE_LOCATION}) getScanResults()4385 public List<ScanResult> getScanResults() { 4386 try { 4387 return mService.getScanResults(mContext.getOpPackageName(), 4388 mContext.getAttributionTag()); 4389 } catch (RemoteException e) { 4390 throw e.rethrowFromSystemServer(); 4391 } 4392 } 4393 4394 /** 4395 * Get the filtered ScanResults which match the network configurations specified by the 4396 * {@code networkSuggestionsToMatch}. Suggestions which use {@link WifiConfiguration} use 4397 * SSID and the security type to match. Suggestions which use {@link PasspointConfigration} 4398 * use the matching rules of Hotspot 2.0. 4399 * @param networkSuggestionsToMatch The list of {@link WifiNetworkSuggestion} to match against. 4400 * These may or may not be suggestions which are installed on the device. 4401 * @param scanResults The scan results to be filtered. Optional - if not provided(empty list), 4402 * the Wi-Fi service will use the most recent scan results which the system has. 4403 * @return The map of {@link WifiNetworkSuggestion} to the list of {@link ScanResult} 4404 * corresponding to networks which match them. 4405 * @hide 4406 */ 4407 @SystemApi 4408 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) 4409 @NonNull getMatchingScanResults( @onNull List<WifiNetworkSuggestion> networkSuggestionsToMatch, @Nullable List<ScanResult> scanResults)4410 public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( 4411 @NonNull List<WifiNetworkSuggestion> networkSuggestionsToMatch, 4412 @Nullable List<ScanResult> scanResults) { 4413 if (networkSuggestionsToMatch == null) { 4414 throw new IllegalArgumentException("networkSuggestions must not be null."); 4415 } 4416 try { 4417 return mService.getMatchingScanResults( 4418 networkSuggestionsToMatch, scanResults, 4419 mContext.getOpPackageName(), mContext.getAttributionTag()); 4420 } catch (RemoteException e) { 4421 throw e.rethrowFromSystemServer(); 4422 } 4423 } 4424 4425 /** 4426 * Set if scanning is always available. 4427 * 4428 * If set to {@code true}, apps can issue {@link #startScan} and fetch scan results 4429 * even when Wi-Fi is turned off. 4430 * 4431 * @param isAvailable true to enable, false to disable. 4432 * @hide 4433 * @see #isScanAlwaysAvailable() 4434 */ 4435 @SystemApi 4436 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setScanAlwaysAvailable(boolean isAvailable)4437 public void setScanAlwaysAvailable(boolean isAvailable) { 4438 try { 4439 mService.setScanAlwaysAvailable(isAvailable, mContext.getOpPackageName()); 4440 } catch (RemoteException e) { 4441 throw e.rethrowFromSystemServer(); 4442 } 4443 } 4444 4445 /** 4446 * Check if scanning is always available. 4447 * 4448 * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results 4449 * even when Wi-Fi is turned off. 4450 * 4451 * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}. 4452 * @deprecated The ability for apps to trigger scan requests will be removed in a future 4453 * release. 4454 */ 4455 @Deprecated isScanAlwaysAvailable()4456 public boolean isScanAlwaysAvailable() { 4457 try { 4458 return mService.isScanAlwaysAvailable(); 4459 } catch (RemoteException e) { 4460 throw e.rethrowFromSystemServer(); 4461 } 4462 } 4463 4464 /** 4465 * Get channel data such as the number of APs found on each channel from the most recent scan. 4466 * App requires {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} 4467 * 4468 * @param executor The executor on which callback will be invoked. 4469 * @param resultsCallback A callback that will return {@code List<Bundle>} containing channel 4470 * data such as the number of APs found on each channel. 4471 * {@link WifiManager#CHANNEL_DATA_KEY_FREQUENCY_MHZ} and 4472 * {@link WifiManager#CHANNEL_DATA_KEY_NUM_AP} are used to get 4473 * the frequency (Mhz) and number of APs. 4474 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 4475 * @throws SecurityException if the caller does not have permission. 4476 * @throws NullPointerException if the caller provided invalid inputs. 4477 */ 4478 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 4479 @RequiresPermission(NEARBY_WIFI_DEVICES) getChannelData(@onNull @allbackExecutor Executor executor, @NonNull Consumer<List<Bundle>> resultsCallback)4480 public void getChannelData(@NonNull @CallbackExecutor Executor executor, 4481 @NonNull Consumer<List<Bundle>> resultsCallback) { 4482 Objects.requireNonNull(executor, "executor cannot be null"); 4483 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 4484 try { 4485 Bundle extras = new Bundle(); 4486 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 4487 mContext.getAttributionSource()); 4488 mService.getChannelData(new IListListener.Stub() { 4489 @Override 4490 public void onResult(List value) { 4491 Binder.clearCallingIdentity(); 4492 executor.execute(() -> { 4493 resultsCallback.accept(value); 4494 }); 4495 } 4496 }, mContext.getOpPackageName(), extras); 4497 } catch (RemoteException e) { 4498 throw e.rethrowFromSystemServer(); 4499 } 4500 } 4501 4502 /** 4503 * Tell the device to persist the current list of configured networks. 4504 * <p> 4505 * Note: It is possible for this method to change the network IDs of 4506 * existing networks. You should assume the network IDs can be different 4507 * after calling this method. 4508 * 4509 * @return {@code false}. 4510 * @deprecated There is no need to call this method - 4511 * {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)} 4512 * and {@link #removeNetwork(int)} already persist the configurations automatically. 4513 */ 4514 @Deprecated saveConfiguration()4515 public boolean saveConfiguration() { 4516 return false; 4517 } 4518 4519 /** 4520 * Helper class to support driver country code changed listener. 4521 */ 4522 private static class OnDriverCountryCodeChangedProxy 4523 extends IOnWifiDriverCountryCodeChangedListener.Stub { 4524 4525 @NonNull private Executor mExecutor; 4526 @NonNull private ActiveCountryCodeChangedCallback mCallback; 4527 OnDriverCountryCodeChangedProxy(@onNull Executor executor, @NonNull ActiveCountryCodeChangedCallback callback)4528 OnDriverCountryCodeChangedProxy(@NonNull Executor executor, 4529 @NonNull ActiveCountryCodeChangedCallback callback) { 4530 Objects.requireNonNull(executor); 4531 Objects.requireNonNull(callback); 4532 mExecutor = executor; 4533 mCallback = callback; 4534 } 4535 4536 @Override onDriverCountryCodeChanged(String countryCode)4537 public void onDriverCountryCodeChanged(String countryCode) { 4538 Log.i(TAG, "OnDriverCountryCodeChangedProxy: receive onDriverCountryCodeChanged: " 4539 + countryCode); 4540 Binder.clearCallingIdentity(); 4541 if (countryCode != null) { 4542 mExecutor.execute(() -> mCallback.onActiveCountryCodeChanged(countryCode)); 4543 } else { 4544 mExecutor.execute(() -> mCallback.onCountryCodeInactive()); 4545 } 4546 } 4547 } 4548 4549 /** 4550 * Interface used to listen the active country code changed event. 4551 * @hide 4552 */ 4553 @SystemApi 4554 public interface ActiveCountryCodeChangedCallback { 4555 /** 4556 * Called when the country code used by the Wi-Fi subsystem has changed. 4557 * 4558 * @param countryCode An ISO-3166-alpha2 country code which is 2-Character alphanumeric. 4559 */ onActiveCountryCodeChanged(@onNull String countryCode)4560 void onActiveCountryCodeChanged(@NonNull String countryCode); 4561 4562 /** 4563 * Called when the Wi-Fi subsystem does not have an active country code. 4564 * This can happen when Wi-Fi is disabled. 4565 */ onCountryCodeInactive()4566 void onCountryCodeInactive(); 4567 } 4568 4569 /** 4570 * Add the provided callback for the active country code changed event. 4571 * Caller will receive either 4572 * {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)} 4573 * or {@link WifiManager.ActiveCountryCodeChangedCallback#onCountryCodeInactive()} 4574 * on registration. 4575 * 4576 * Note: When the global location setting is off or the caller does not have runtime location 4577 * permission, caller will not receive the callback even if caller register callback succeeded. 4578 * 4579 * 4580 * Caller can remove a previously registered callback using 4581 * {@link WifiManager#unregisterActiveCountryCodeChangedCallback( 4582 * ActiveCountryCodeChangedCallback)}. 4583 * 4584 * <p> 4585 * Note: 4586 * The value provided by 4587 * {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)} 4588 * may be different from the returned value from {@link WifiManager#getCountryCode()} even if 4589 * the Wi-Fi subsystem is active. See: {@link WifiManager#getCountryCode()} for details. 4590 * </p> 4591 * 4592 * @param executor The Executor on which to execute the callbacks. 4593 * @param callback callback for the driver country code changed events. 4594 * @hide 4595 */ 4596 @SystemApi 4597 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 4598 @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) registerActiveCountryCodeChangedCallback( @onNull @allbackExecutor Executor executor, @NonNull ActiveCountryCodeChangedCallback callback)4599 public void registerActiveCountryCodeChangedCallback( 4600 @NonNull @CallbackExecutor Executor executor, 4601 @NonNull ActiveCountryCodeChangedCallback callback) { 4602 if (!SdkLevel.isAtLeastT()) { 4603 throw new UnsupportedOperationException(); 4604 } 4605 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 4606 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 4607 if (mVerboseLoggingEnabled) { 4608 Log.d(TAG, "registerActiveCountryCodeChangedCallback: callback=" + callback 4609 + ", executor=" + executor); 4610 } 4611 final int callbackIdentifier = System.identityHashCode(callback); 4612 synchronized (sActiveCountryCodeChangedCallbackMap) { 4613 try { 4614 IOnWifiDriverCountryCodeChangedListener.Stub binderListener = 4615 new OnDriverCountryCodeChangedProxy(executor, callback); 4616 sActiveCountryCodeChangedCallbackMap.put(callbackIdentifier, 4617 binderListener); 4618 mService.registerDriverCountryCodeChangedListener(binderListener, 4619 mContext.getOpPackageName(), mContext.getAttributionTag()); 4620 } catch (RemoteException e) { 4621 sActiveCountryCodeChangedCallbackMap.remove(callbackIdentifier); 4622 throw e.rethrowFromSystemServer(); 4623 } 4624 } 4625 } 4626 4627 /** 4628 * Allow callers to remove a previously registered listener. After calling this method, 4629 * applications will no longer receive the active country code changed events through that 4630 * callback. 4631 * 4632 * @param callback Callback to remove the active country code changed events. 4633 * 4634 * @hide 4635 */ 4636 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 4637 @SystemApi unregisterActiveCountryCodeChangedCallback( @onNull ActiveCountryCodeChangedCallback callback)4638 public void unregisterActiveCountryCodeChangedCallback( 4639 @NonNull ActiveCountryCodeChangedCallback callback) { 4640 if (!SdkLevel.isAtLeastT()) { 4641 throw new UnsupportedOperationException(); 4642 } 4643 if (callback == null) throw new IllegalArgumentException("Callback cannot be null"); 4644 if (mVerboseLoggingEnabled) { 4645 Log.d(TAG, "unregisterActiveCountryCodeChangedCallback: callback=" + callback); 4646 } 4647 final int callbackIdentifier = System.identityHashCode(callback); 4648 synchronized (sActiveCountryCodeChangedCallbackMap) { 4649 try { 4650 if (!sActiveCountryCodeChangedCallbackMap.contains(callbackIdentifier)) { 4651 Log.w(TAG, "Unknown external listener " + callbackIdentifier); 4652 return; 4653 } 4654 mService.unregisterDriverCountryCodeChangedListener( 4655 sActiveCountryCodeChangedCallbackMap.get(callbackIdentifier)); 4656 } catch (RemoteException e) { 4657 throw e.rethrowFromSystemServer(); 4658 } finally { 4659 sActiveCountryCodeChangedCallbackMap.remove(callbackIdentifier); 4660 } 4661 } 4662 } 4663 4664 /** 4665 * Interface used to listen to changes in current network state. 4666 * @hide 4667 */ 4668 @SystemApi 4669 public interface WifiNetworkStateChangedListener { 4670 /** @hide */ 4671 @Retention(RetentionPolicy.SOURCE) 4672 @IntDef(prefix = {"WIFI_ROLE_CLIENT_"}, value = { 4673 WIFI_ROLE_CLIENT_PRIMARY, 4674 WIFI_ROLE_CLIENT_SECONDARY_INTERNET, 4675 WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY 4676 }) 4677 @interface WifiClientModeRole {} 4678 4679 /** 4680 * A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}. 4681 * Represents the primary Client Mode Manager which is mostly used for internet, but could 4682 * also be used for other use-cases such as local only connections. 4683 **/ 4684 int WIFI_ROLE_CLIENT_PRIMARY = 1; 4685 /** 4686 * A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}. 4687 * Represents a Client Mode Manager dedicated for the secondary internet use-case. 4688 **/ 4689 int WIFI_ROLE_CLIENT_SECONDARY_INTERNET = 2; 4690 /** 4691 * A client mode role returned by {@link #onWifiNetworkStateChanged(int, int)}. 4692 * Represents a Client Mode Manager dedicated for the local only connection use-case. 4693 **/ 4694 int WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY = 3; 4695 4696 /** @hide */ 4697 @Retention(RetentionPolicy.SOURCE) 4698 @IntDef(prefix = {"WIFI_NETWORK_STATUS_"}, value = { 4699 WIFI_NETWORK_STATUS_IDLE, 4700 WIFI_NETWORK_STATUS_SCANNING, 4701 WIFI_NETWORK_STATUS_CONNECTING, 4702 WIFI_NETWORK_STATUS_AUTHENTICATING, 4703 WIFI_NETWORK_STATUS_OBTAINING_IPADDR, 4704 WIFI_NETWORK_STATUS_CONNECTED, 4705 WIFI_NETWORK_STATUS_DISCONNECTED, 4706 WIFI_NETWORK_STATUS_FAILED 4707 }) 4708 @interface WifiNetworkState {} 4709 4710 /** 4711 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4712 * Supplicant is in uninitialized state. 4713 **/ 4714 int WIFI_NETWORK_STATUS_IDLE = 1; 4715 /** 4716 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4717 * Supplicant is scanning. 4718 **/ 4719 int WIFI_NETWORK_STATUS_SCANNING = 2; 4720 /** 4721 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4722 * L2 connection is in progress. 4723 **/ 4724 int WIFI_NETWORK_STATUS_CONNECTING = 3; 4725 /** 4726 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4727 * L2 connection 4 way handshake. 4728 **/ 4729 int WIFI_NETWORK_STATUS_AUTHENTICATING = 4; 4730 /** 4731 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4732 * L2 connection complete. Obtaining IP address. 4733 **/ 4734 int WIFI_NETWORK_STATUS_OBTAINING_IPADDR = 5; 4735 /** 4736 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4737 * L3 connection is complete. 4738 **/ 4739 int WIFI_NETWORK_STATUS_CONNECTED = 6; 4740 /** 4741 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4742 * Network disconnected. 4743 **/ 4744 int WIFI_NETWORK_STATUS_DISCONNECTED = 7; 4745 /** 4746 * A state returned by {@link #onWifiNetworkStateChanged(int, int)}. 4747 * A pseudo-state that should normally never be seen. 4748 **/ 4749 int WIFI_NETWORK_STATUS_FAILED = 8; 4750 4751 4752 /** 4753 * Provides network state changes per client mode role. 4754 * @param cmmRole the role of the wifi client mode manager having the state change. 4755 * One of {@link WifiClientModeRole}. 4756 * @param state the wifi network state specified by one of {@link WifiNetworkState}. 4757 */ onWifiNetworkStateChanged(@ifiClientModeRole int cmmRole, @WifiNetworkState int state)4758 void onWifiNetworkStateChanged(@WifiClientModeRole int cmmRole, 4759 @WifiNetworkState int state); 4760 } 4761 4762 /** 4763 * Helper class to support wifi network state changed listener. 4764 */ 4765 private static class OnWifiNetworkStateChangedProxy 4766 extends IWifiNetworkStateChangedListener.Stub { 4767 4768 @NonNull private Executor mExecutor; 4769 @NonNull private WifiNetworkStateChangedListener mListener; 4770 OnWifiNetworkStateChangedProxy(@onNull Executor executor, @NonNull WifiNetworkStateChangedListener listener)4771 OnWifiNetworkStateChangedProxy(@NonNull Executor executor, 4772 @NonNull WifiNetworkStateChangedListener listener) { 4773 Objects.requireNonNull(executor); 4774 Objects.requireNonNull(listener); 4775 mExecutor = executor; 4776 mListener = listener; 4777 } 4778 4779 @Override onWifiNetworkStateChanged(int cmmRole, int state)4780 public void onWifiNetworkStateChanged(int cmmRole, int state) { 4781 Log.i(TAG, "OnWifiNetworkStateChangedProxy: onWifiNetworkStateChanged: " 4782 + cmmRole + ", " + state); 4783 Binder.clearCallingIdentity(); 4784 mExecutor.execute(() -> mListener.onWifiNetworkStateChanged(cmmRole, state)); 4785 } 4786 } 4787 4788 /** 4789 * Add a listener to listen to Wi-Fi network state changes on available client mode roles 4790 * specified in {@link WifiNetworkStateChangedListener.WifiClientModeRole}. 4791 * When wifi state changes such as connected/disconnect happens, results will be delivered via 4792 * {@link WifiNetworkStateChangedListener#onWifiNetworkStateChanged(int, int)}. 4793 * 4794 * @param executor The Executor on which to execute the callbacks. 4795 * @param listener listener for the network status updates. 4796 * @throws SecurityException if the caller is missing required permissions. 4797 * @throws IllegalArgumentException if incorrect input arguments are provided. 4798 * @hide 4799 */ 4800 @SystemApi 4801 @RequiresPermission(Manifest.permission.NETWORK_SETTINGS) addWifiNetworkStateChangedListener(@onNull @allbackExecutor Executor executor, @NonNull WifiNetworkStateChangedListener listener)4802 public void addWifiNetworkStateChangedListener(@NonNull @CallbackExecutor Executor executor, 4803 @NonNull WifiNetworkStateChangedListener listener) { 4804 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 4805 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 4806 if (mVerboseLoggingEnabled) { 4807 Log.d(TAG, "addWifiNetworkStateChangedListener: listener=" + listener 4808 + ", executor=" + executor); 4809 } 4810 final int listenerIdentifier = System.identityHashCode(listener); 4811 synchronized (sOnWifiNetworkStateChangedListenerMap) { 4812 try { 4813 IWifiNetworkStateChangedListener.Stub listenerProxy = 4814 new OnWifiNetworkStateChangedProxy(executor, listener); 4815 sOnWifiNetworkStateChangedListenerMap.put(listenerIdentifier, 4816 listenerProxy); 4817 mService.addWifiNetworkStateChangedListener(listenerProxy); 4818 } catch (RemoteException e) { 4819 sOnWifiNetworkStateChangedListenerMap.remove(listenerIdentifier); 4820 throw e.rethrowFromSystemServer(); 4821 } 4822 } 4823 } 4824 4825 /** 4826 * Remove a listener added using 4827 * {@link #addWifiNetworkStateChangedListener(Executor, WifiNetworkStateChangedListener)}. 4828 * @param listener the listener to be removed. 4829 * @throws IllegalArgumentException if incorrect input arguments are provided. 4830 * @hide 4831 */ 4832 @SystemApi 4833 @RequiresApi(Build.VERSION_CODES.TIRAMISU) removeWifiNetworkStateChangedListener( @onNull WifiNetworkStateChangedListener listener)4834 public void removeWifiNetworkStateChangedListener( 4835 @NonNull WifiNetworkStateChangedListener listener) { 4836 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 4837 if (mVerboseLoggingEnabled) { 4838 Log.d(TAG, "removeWifiNetworkStateChangedListener: listener=" + listener); 4839 } 4840 final int listenerIdentifier = System.identityHashCode(listener); 4841 synchronized (sOnWifiNetworkStateChangedListenerMap) { 4842 try { 4843 if (!sOnWifiNetworkStateChangedListenerMap.contains(listenerIdentifier)) { 4844 Log.w(TAG, "Unknown external listener " + listenerIdentifier); 4845 return; 4846 } 4847 mService.removeWifiNetworkStateChangedListener( 4848 sOnWifiNetworkStateChangedListenerMap.get(listenerIdentifier)); 4849 } catch (RemoteException e) { 4850 throw e.rethrowFromSystemServer(); 4851 } finally { 4852 sOnWifiNetworkStateChangedListenerMap.remove(listenerIdentifier); 4853 } 4854 } 4855 } 4856 4857 /** 4858 * Get the country code as resolved by the Wi-Fi framework. 4859 * The Wi-Fi framework uses multiple sources to resolve a country code 4860 * - in order of priority (high to low): 4861 * 1. Override country code set by {@link WifiManager#setOverrideCountryCode(String)} 4862 * and cleared by {@link WifiManager#clearOverrideCountryCode()}. Typically only used 4863 * for testing. 4864 * 2. Country code supplied by the telephony module. Typically provided from the 4865 * current network or from emergency cell information. 4866 * 3. Country code supplied by the wifi driver module. (802.11d) 4867 * 4. Default country code set either via {@code ro.boot.wificountrycode} 4868 * or the {@link WifiManager#setDefaultCountryCode(String)}. 4869 * 4870 * <p> 4871 * Note: 4872 * This method returns the Country Code value used by the framework - even if not currently 4873 * used by the Wi-Fi subsystem. I.e. the returned value from this API may be different from the 4874 * value provided by 4875 * {@link WifiManager.ActiveCountryCodeChangedCallback#onActiveCountryCodeChanged(String)}. 4876 * Such a difference may happen when there is an ongoing network connection (STA, AP, Direct, 4877 * or Aware) and the Wi-Fi subsystem does not support dynamic updates - at that point the 4878 * framework may defer setting the Country Code to the Wi-Fi subsystem. 4879 * </p> 4880 * @return the country code in ISO 3166 alpha-2 (2-letter) upper format, 4881 * or null if there is no country code configured. 4882 * 4883 * @hide 4884 */ 4885 @Nullable 4886 @SystemApi 4887 @RequiresPermission(anyOf = { 4888 android.Manifest.permission.NETWORK_SETTINGS, 4889 android.Manifest.permission.ACCESS_COARSE_LOCATION 4890 }) getCountryCode()4891 public String getCountryCode() { 4892 try { 4893 return mService.getCountryCode(mContext.getOpPackageName(), 4894 mContext.getAttributionTag()); 4895 } catch (RemoteException e) { 4896 throw e.rethrowFromSystemServer(); 4897 } 4898 } 4899 4900 /** 4901 * Set the override country code - may be used for testing. See the country code resolution 4902 * order and format in {@link #getCountryCode()}. 4903 * @param country A 2-Character alphanumeric country code. 4904 * @see #getCountryCode(). 4905 * 4906 * @hide 4907 */ 4908 @RequiresApi(Build.VERSION_CODES.S) 4909 @SystemApi 4910 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) setOverrideCountryCode(@onNull String country)4911 public void setOverrideCountryCode(@NonNull String country) { 4912 try { 4913 mService.setOverrideCountryCode(country); 4914 } catch (RemoteException e) { 4915 throw e.rethrowFromSystemServer(); 4916 } 4917 } 4918 4919 /** 4920 * This clears the override country code which was previously set by 4921 * {@link WifiManager#setOverrideCountryCode(String)} method. 4922 * @see #getCountryCode(). 4923 * 4924 * @hide 4925 */ 4926 @RequiresApi(Build.VERSION_CODES.S) 4927 @SystemApi 4928 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) clearOverrideCountryCode()4929 public void clearOverrideCountryCode() { 4930 try { 4931 mService.clearOverrideCountryCode(); 4932 } catch (RemoteException e) { 4933 throw e.rethrowFromSystemServer(); 4934 } 4935 } 4936 /** 4937 * Used to configure the default country code. See {@link #getCountryCode()} for resolution 4938 * method of the country code. 4939 * @param country A 2-character alphanumeric country code. 4940 * @see #getCountryCode(). 4941 * 4942 * @hide 4943 */ 4944 @RequiresApi(Build.VERSION_CODES.S) 4945 @SystemApi 4946 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE) setDefaultCountryCode(@onNull String country)4947 public void setDefaultCountryCode(@NonNull String country) { 4948 try { 4949 mService.setDefaultCountryCode(country); 4950 } catch (RemoteException e) { 4951 throw e.rethrowFromSystemServer(); 4952 } 4953 } 4954 4955 /** 4956 * Return the DHCP-assigned addresses from the last successful DHCP request, 4957 * if any. 4958 * 4959 * @return the DHCP information 4960 * 4961 * @deprecated Use the methods on {@link android.net.LinkProperties} which can be obtained 4962 * either via {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)} or 4963 * {@link ConnectivityManager#getLinkProperties(Network)}. 4964 * 4965 * <p> 4966 * <b>Compatibility Notes:</b> 4967 * <li>On devices supporting concurrent connections (indicated via 4968 * {@link #isStaConcurrencyForLocalOnlyConnectionsSupported()}, etc), this API will return 4969 * the details of the internet providing connection (if any) to all apps, except for the apps 4970 * that triggered the creation of the concurrent connection. For such apps, this API will return 4971 * the details of the connection they created. e.g. apps using {@link WifiNetworkSpecifier} will 4972 * trigger a concurrent connection on supported devices and hence this API will provide 4973 * details of their peer to peer connection (not the internet providing connection). This 4974 * is to maintain backwards compatibility with behavior on single STA devices.</li> 4975 * </p> 4976 */ 4977 @Deprecated getDhcpInfo()4978 public DhcpInfo getDhcpInfo() { 4979 try { 4980 return mService.getDhcpInfo(mContext.getOpPackageName()); 4981 } catch (RemoteException e) { 4982 throw e.rethrowFromSystemServer(); 4983 } 4984 } 4985 4986 /** 4987 * Enable or disable Wi-Fi. 4988 * <p> 4989 * Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE} 4990 * permission to toggle wifi. 4991 * 4992 * @param enabled {@code true} to enable, {@code false} to disable. 4993 * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is 4994 * either already in the requested state, or in progress toward the requested state. 4995 * @throws SecurityException if the caller is missing required permissions. 4996 * 4997 * @deprecated Starting with Build.VERSION_CODES#Q, applications are not allowed to 4998 * enable/disable Wi-Fi. 4999 * <b>Compatibility Note:</b> For applications targeting 5000 * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always fail and return 5001 * {@code false}. If apps are targeting an older SDK ({@link android.os.Build.VERSION_CODES#P} 5002 * or below), they can continue to use this API. 5003 * <p> 5004 * Deprecation Exemptions: 5005 * <ul> 5006 * <li>Device Owner (DO), Profile Owner (PO) and system apps. 5007 * </ul> 5008 * 5009 * Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, DO/COPE may set 5010 * a user restriction (DISALLOW_CHANGE_WIFI_STATE) to only allow DO/PO to use this API. 5011 */ 5012 @Deprecated setWifiEnabled(boolean enabled)5013 public boolean setWifiEnabled(boolean enabled) { 5014 try { 5015 return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); 5016 } catch (RemoteException e) { 5017 throw e.rethrowFromSystemServer(); 5018 } 5019 } 5020 5021 /** 5022 * Abstract callback class for applications to receive updates about the Wi-Fi subsystem 5023 * restarting. The Wi-Fi subsystem can restart due to internal recovery mechanisms or via user 5024 * action. 5025 */ 5026 @RequiresApi(Build.VERSION_CODES.S) 5027 public abstract static class SubsystemRestartTrackingCallback { 5028 private final SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy mProxy; 5029 SubsystemRestartTrackingCallback()5030 public SubsystemRestartTrackingCallback() { 5031 mProxy = new SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy(); 5032 } 5033 5034 /*package*/ @NonNull getProxy()5035 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy getProxy() { 5036 return mProxy; 5037 } 5038 5039 /** 5040 * Indicates that the Wi-Fi subsystem is about to restart. 5041 */ onSubsystemRestarting()5042 public abstract void onSubsystemRestarting(); 5043 5044 /** 5045 * Indicates that the Wi-Fi subsystem has restarted. 5046 */ onSubsystemRestarted()5047 public abstract void onSubsystemRestarted(); 5048 5049 private static class SubsystemRestartCallbackProxy extends ISubsystemRestartCallback.Stub { 5050 private final Object mLock = new Object(); 5051 @Nullable 5052 @GuardedBy("mLock") 5053 private Executor mExecutor; 5054 @Nullable 5055 @GuardedBy("mLock") 5056 private SubsystemRestartTrackingCallback mCallback; 5057 SubsystemRestartCallbackProxy()5058 SubsystemRestartCallbackProxy() { 5059 mExecutor = null; 5060 mCallback = null; 5061 } 5062 initProxy(@onNull Executor executor, @NonNull SubsystemRestartTrackingCallback callback)5063 /*package*/ void initProxy(@NonNull Executor executor, 5064 @NonNull SubsystemRestartTrackingCallback callback) { 5065 synchronized (mLock) { 5066 mExecutor = executor; 5067 mCallback = callback; 5068 } 5069 } 5070 cleanUpProxy()5071 /*package*/ void cleanUpProxy() { 5072 synchronized (mLock) { 5073 mExecutor = null; 5074 mCallback = null; 5075 } 5076 } 5077 5078 @Override onSubsystemRestarting()5079 public void onSubsystemRestarting() { 5080 Executor executor; 5081 SubsystemRestartTrackingCallback callback; 5082 synchronized (mLock) { 5083 executor = mExecutor; 5084 callback = mCallback; 5085 } 5086 if (executor == null || callback == null) { 5087 return; 5088 } 5089 Binder.clearCallingIdentity(); 5090 executor.execute(callback::onSubsystemRestarting); 5091 } 5092 5093 @Override onSubsystemRestarted()5094 public void onSubsystemRestarted() { 5095 Executor executor; 5096 SubsystemRestartTrackingCallback callback; 5097 synchronized (mLock) { 5098 executor = mExecutor; 5099 callback = mCallback; 5100 } 5101 if (executor == null || callback == null) { 5102 return; 5103 } 5104 Binder.clearCallingIdentity(); 5105 executor.execute(callback::onSubsystemRestarted); 5106 } 5107 } 5108 } 5109 5110 /** 5111 * Registers a {@link SubsystemRestartTrackingCallback} to listen to Wi-Fi subsystem restarts. 5112 * The subsystem may restart due to internal recovery mechanisms or via user action. 5113 * 5114 * @see #unregisterSubsystemRestartTrackingCallback(SubsystemRestartTrackingCallback) 5115 * 5116 * @param executor Executor to execute callback on 5117 * @param callback {@link SubsystemRestartTrackingCallback} to register 5118 */ 5119 @RequiresApi(Build.VERSION_CODES.S) 5120 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) registerSubsystemRestartTrackingCallback( @onNull @allbackExecutor Executor executor, @NonNull SubsystemRestartTrackingCallback callback)5121 public void registerSubsystemRestartTrackingCallback( 5122 @NonNull @CallbackExecutor Executor executor, 5123 @NonNull SubsystemRestartTrackingCallback callback) { 5124 if (executor == null) throw new IllegalArgumentException("executor must not be null"); 5125 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5126 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy(); 5127 proxy.initProxy(executor, callback); 5128 try { 5129 mService.registerSubsystemRestartCallback(proxy); 5130 } catch (RemoteException e) { 5131 proxy.cleanUpProxy(); 5132 throw e.rethrowFromSystemServer(); 5133 } 5134 } 5135 5136 /** 5137 * Unregisters a {@link SubsystemRestartTrackingCallback} registered with 5138 * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)} 5139 * 5140 * @param callback {@link SubsystemRestartTrackingCallback} to unregister 5141 */ 5142 @RequiresApi(Build.VERSION_CODES.S) 5143 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) unregisterSubsystemRestartTrackingCallback( @onNull SubsystemRestartTrackingCallback callback)5144 public void unregisterSubsystemRestartTrackingCallback( 5145 @NonNull SubsystemRestartTrackingCallback callback) { 5146 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5147 SubsystemRestartTrackingCallback.SubsystemRestartCallbackProxy proxy = callback.getProxy(); 5148 try { 5149 mService.unregisterSubsystemRestartCallback(proxy); 5150 } catch (RemoteException e) { 5151 throw e.rethrowFromSystemServer(); 5152 } finally { 5153 proxy.cleanUpProxy(); 5154 } 5155 } 5156 5157 /** 5158 * Restart the Wi-Fi subsystem. 5159 * 5160 * Restarts the Wi-Fi subsystem - effectively disabling it and re-enabling it. All existing 5161 * Access Point (AP) associations are torn down, all Soft APs are disabled, Wi-Fi Direct and 5162 * Wi-Fi Aware are disabled. 5163 * 5164 * The state of the system after restart is not guaranteed to match its state before the API is 5165 * called - for instance the device may associate to a different Access Point (AP), and tethered 5166 * hotspots may or may not be restored. 5167 * 5168 * Use the 5169 * {@link #registerSubsystemRestartTrackingCallback(Executor, SubsystemRestartTrackingCallback)} 5170 * to track the operation. 5171 * 5172 * @hide 5173 */ 5174 @RequiresApi(Build.VERSION_CODES.S) 5175 @SystemApi 5176 @RequiresPermission(android.Manifest.permission.RESTART_WIFI_SUBSYSTEM) restartWifiSubsystem()5177 public void restartWifiSubsystem() { 5178 try { 5179 mService.restartWifiSubsystem(); 5180 } catch (RemoteException e) { 5181 throw e.rethrowFromSystemServer(); 5182 } 5183 } 5184 5185 /** 5186 * Gets the Wi-Fi enabled state. 5187 * @return One of {@link #WIFI_STATE_DISABLED}, 5188 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, 5189 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN} 5190 * @see #isWifiEnabled() 5191 */ getWifiState()5192 public int getWifiState() { 5193 try { 5194 return mService.getWifiEnabledState(); 5195 } catch (RemoteException e) { 5196 throw e.rethrowFromSystemServer(); 5197 } 5198 } 5199 5200 /** 5201 * Return whether Wi-Fi is enabled or disabled. 5202 * @return {@code true} if Wi-Fi is enabled 5203 * @see #getWifiState() 5204 */ isWifiEnabled()5205 public boolean isWifiEnabled() { 5206 return getWifiState() == WIFI_STATE_ENABLED; 5207 } 5208 5209 /** 5210 * Calculates the level of the signal. This should be used any time a signal 5211 * is being shown. 5212 * 5213 * @param rssi The power of the signal measured in RSSI. 5214 * @param numLevels The number of levels to consider in the calculated level. 5215 * @return A level of the signal, given in the range of 0 to numLevels-1 (both inclusive). 5216 * @deprecated Callers should use {@link #calculateSignalLevel(int)} instead to get the 5217 * signal level using the system default RSSI thresholds, or otherwise compute the RSSI level 5218 * themselves using their own formula. 5219 */ 5220 @Deprecated calculateSignalLevel(int rssi, int numLevels)5221 public static int calculateSignalLevel(int rssi, int numLevels) { 5222 if (rssi <= MIN_RSSI) { 5223 return 0; 5224 } else if (rssi >= MAX_RSSI) { 5225 return numLevels - 1; 5226 } else { 5227 float inputRange = (MAX_RSSI - MIN_RSSI); 5228 float outputRange = (numLevels - 1); 5229 return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange); 5230 } 5231 } 5232 5233 /** 5234 * Given a raw RSSI, return the RSSI signal quality rating using the system default RSSI 5235 * quality rating thresholds. 5236 * @param rssi a raw RSSI value, in dBm, usually between -55 and -90 5237 * @return the RSSI signal quality rating, in the range 5238 * [0, {@link #getMaxSignalLevel()}], where 0 is the lowest (worst signal) RSSI 5239 * rating and {@link #getMaxSignalLevel()} is the highest (best signal) RSSI rating. 5240 */ 5241 @IntRange(from = 0) calculateSignalLevel(int rssi)5242 public int calculateSignalLevel(int rssi) { 5243 try { 5244 return mService.calculateSignalLevel(rssi); 5245 } catch (RemoteException e) { 5246 throw e.rethrowFromSystemServer(); 5247 } 5248 } 5249 5250 /** 5251 * Get the system default maximum signal level. 5252 * This is the maximum RSSI level returned by {@link #calculateSignalLevel(int)}. 5253 */ 5254 @IntRange(from = 0) getMaxSignalLevel()5255 public int getMaxSignalLevel() { 5256 return calculateSignalLevel(Integer.MAX_VALUE); 5257 } 5258 5259 /** 5260 * Compares two signal strengths. 5261 * 5262 * @param rssiA The power of the first signal measured in RSSI. 5263 * @param rssiB The power of the second signal measured in RSSI. 5264 * @return Returns <0 if the first signal is weaker than the second signal, 5265 * 0 if the two signals have the same strength, and >0 if the first 5266 * signal is stronger than the second signal. 5267 */ compareSignalLevel(int rssiA, int rssiB)5268 public static int compareSignalLevel(int rssiA, int rssiB) { 5269 return rssiA - rssiB; 5270 } 5271 5272 /** 5273 * Call allowing ConnectivityService to update WifiService with interface mode changes. 5274 * 5275 * @param ifaceName String name of the updated interface, or null to represent all interfaces 5276 * @param mode int representing the new mode, one of: 5277 * {@link #IFACE_IP_MODE_TETHERED}, 5278 * {@link #IFACE_IP_MODE_LOCAL_ONLY}, 5279 * {@link #IFACE_IP_MODE_CONFIGURATION_ERROR}, 5280 * {@link #IFACE_IP_MODE_UNSPECIFIED} 5281 * 5282 * @hide 5283 */ 5284 @SystemApi 5285 @RequiresPermission(anyOf = { 5286 android.Manifest.permission.NETWORK_STACK, 5287 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5288 }) updateInterfaceIpState(@ullable String ifaceName, @IfaceIpMode int mode)5289 public void updateInterfaceIpState(@Nullable String ifaceName, @IfaceIpMode int mode) { 5290 try { 5291 mService.updateInterfaceIpState(ifaceName, mode); 5292 } catch (RemoteException e) { 5293 throw e.rethrowFromSystemServer(); 5294 } 5295 } 5296 5297 /* Wi-Fi/Cellular Coex */ 5298 5299 /** 5300 * Mandatory coex restriction flag for Wi-Fi Direct. 5301 * 5302 * @see #setCoexUnsafeChannels(List, int) 5303 * 5304 * @hide 5305 */ 5306 @SystemApi 5307 @RequiresApi(Build.VERSION_CODES.S) 5308 public static final int COEX_RESTRICTION_WIFI_DIRECT = 0x1 << 0; 5309 5310 /** 5311 * Mandatory coex restriction flag for SoftAP 5312 * 5313 * @see #setCoexUnsafeChannels(List, int) 5314 * 5315 * @hide 5316 */ 5317 @SystemApi 5318 @RequiresApi(Build.VERSION_CODES.S) 5319 public static final int COEX_RESTRICTION_SOFTAP = 0x1 << 1; 5320 5321 /** 5322 * Mandatory coex restriction flag for Wi-Fi Aware. 5323 * 5324 * @see #setCoexUnsafeChannels(List, int) 5325 * 5326 * @hide 5327 */ 5328 @SystemApi 5329 @RequiresApi(Build.VERSION_CODES.S) 5330 public static final int COEX_RESTRICTION_WIFI_AWARE = 0x1 << 2; 5331 5332 /** @hide */ 5333 @RequiresApi(Build.VERSION_CODES.S) 5334 @Retention(RetentionPolicy.SOURCE) 5335 @IntDef(flag = true, prefix = {"COEX_RESTRICTION_"}, value = { 5336 COEX_RESTRICTION_WIFI_DIRECT, 5337 COEX_RESTRICTION_SOFTAP, 5338 COEX_RESTRICTION_WIFI_AWARE 5339 }) 5340 public @interface CoexRestriction {} 5341 5342 /** 5343 * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise. 5344 * 5345 * @hide 5346 */ isDefaultCoexAlgorithmEnabled()5347 public boolean isDefaultCoexAlgorithmEnabled() { 5348 try { 5349 return mService.isDefaultCoexAlgorithmEnabled(); 5350 } catch (RemoteException e) { 5351 throw e.rethrowFromSystemServer(); 5352 } 5353 } 5354 5355 /** 5356 * Specify the list of {@link CoexUnsafeChannel} to propagate through the framework for 5357 * Wi-Fi/Cellular coex channel avoidance if the default algorithm is disabled via overlay 5358 * (i.e. config_wifiCoexDefaultAlgorithmEnabled = false). Otherwise do nothing. 5359 * 5360 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 5361 * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode 5362 * restrictions on the specified channels. If any restrictions are set, 5363 * then the supplied CoexUnsafeChannels should be completely avoided for 5364 * the specified modes, rather than be avoided with best effort. 5365 * 5366 * @hide 5367 */ 5368 @SystemApi 5369 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS) 5370 @RequiresApi(Build.VERSION_CODES.S) setCoexUnsafeChannels( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)5371 public void setCoexUnsafeChannels( 5372 @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions) { 5373 if (unsafeChannels == null) { 5374 throw new IllegalArgumentException("unsafeChannels must not be null"); 5375 } 5376 try { 5377 mService.setCoexUnsafeChannels(unsafeChannels, restrictions); 5378 } catch (RemoteException e) { 5379 throw e.rethrowFromSystemServer(); 5380 } 5381 } 5382 5383 /** 5384 * Registers a CoexCallback to listen on the current CoexUnsafeChannels and restrictions being 5385 * used for Wi-Fi/cellular coex channel avoidance. The callback method 5386 * {@link CoexCallback#onCoexUnsafeChannelsChanged(List, int)} will be called immediately after 5387 * registration to return the current values. 5388 * 5389 * @param executor Executor to execute listener callback on 5390 * @param callback CoexCallback to register 5391 * 5392 * @hide 5393 */ 5394 @SystemApi 5395 @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) 5396 @RequiresApi(Build.VERSION_CODES.S) registerCoexCallback( @onNull @allbackExecutor Executor executor, @NonNull CoexCallback callback)5397 public void registerCoexCallback( 5398 @NonNull @CallbackExecutor Executor executor, @NonNull CoexCallback callback) { 5399 if (executor == null) throw new IllegalArgumentException("executor must not be null"); 5400 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5401 CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); 5402 proxy.initProxy(executor, callback); 5403 try { 5404 mService.registerCoexCallback(proxy); 5405 } catch (RemoteException e) { 5406 throw e.rethrowFromSystemServer(); 5407 } 5408 } 5409 5410 /** 5411 * Unregisters a CoexCallback from listening on the current CoexUnsafeChannels and restrictions 5412 * being used for Wi-Fi/cellular coex channel avoidance. 5413 * @param callback CoexCallback to unregister 5414 * 5415 * @hide 5416 */ 5417 @SystemApi 5418 @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) 5419 @RequiresApi(Build.VERSION_CODES.S) unregisterCoexCallback(@onNull CoexCallback callback)5420 public void unregisterCoexCallback(@NonNull CoexCallback callback) { 5421 if (callback == null) throw new IllegalArgumentException("callback must not be null"); 5422 CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); 5423 try { 5424 mService.unregisterCoexCallback(proxy); 5425 } catch (RemoteException e) { 5426 throw e.rethrowFromSystemServer(); 5427 } finally { 5428 proxy.cleanUpProxy(); 5429 } 5430 } 5431 5432 /** 5433 * Abstract callback class for applications to receive updates about current CoexUnsafeChannels 5434 * for Wi-Fi/Cellular coex channel avoidance. 5435 * 5436 * @hide 5437 */ 5438 @SystemApi 5439 @RequiresApi(Build.VERSION_CODES.S) 5440 public abstract static class CoexCallback { 5441 private final CoexCallbackProxy mCoexCallbackProxy; 5442 CoexCallback()5443 public CoexCallback() { 5444 if (!SdkLevel.isAtLeastS()) { 5445 throw new UnsupportedOperationException(); 5446 } 5447 mCoexCallbackProxy = new CoexCallbackProxy(); 5448 } 5449 5450 /*package*/ @NonNull getProxy()5451 CoexCallbackProxy getProxy() { 5452 return mCoexCallbackProxy; 5453 } 5454 5455 /** 5456 * This indicates the current CoexUnsafeChannels and restrictions calculated by the default 5457 * coex algorithm if config_wifiCoexDefaultAlgorithmEnabled is {@code true}. Otherwise, the 5458 * values will match the ones supplied to {@link #setCoexUnsafeChannels(List, int)}. 5459 * 5460 * @param unsafeChannels List of {@link CoexUnsafeChannel} to avoid. 5461 * @param restrictions Bitmap of {@code COEX_RESTRICTION_*} constants specifying the mode 5462 * restrictions on the specified channels. If any restrictions are set, 5463 * then the supplied CoexUnsafeChannels should be completely avoided for 5464 * the specified modes, rather than be avoided with best effort. 5465 */ onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)5466 public abstract void onCoexUnsafeChannelsChanged( 5467 @NonNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions); 5468 5469 /** 5470 * Callback proxy for CoexCallback objects. 5471 */ 5472 private static class CoexCallbackProxy extends ICoexCallback.Stub { 5473 private final Object mLock = new Object(); 5474 @Nullable @GuardedBy("mLock") private Executor mExecutor; 5475 @Nullable @GuardedBy("mLock") private CoexCallback mCallback; 5476 CoexCallbackProxy()5477 CoexCallbackProxy() { 5478 mExecutor = null; 5479 mCallback = null; 5480 } 5481 initProxy(@onNull Executor executor, @NonNull CoexCallback callback)5482 /*package*/ void initProxy(@NonNull Executor executor, 5483 @NonNull CoexCallback callback) { 5484 synchronized (mLock) { 5485 mExecutor = executor; 5486 mCallback = callback; 5487 } 5488 } 5489 cleanUpProxy()5490 /*package*/ void cleanUpProxy() { 5491 synchronized (mLock) { 5492 mExecutor = null; 5493 mCallback = null; 5494 } 5495 } 5496 5497 @Override onCoexUnsafeChannelsChanged( @onNull List<CoexUnsafeChannel> unsafeChannels, @CoexRestriction int restrictions)5498 public void onCoexUnsafeChannelsChanged( 5499 @NonNull List<CoexUnsafeChannel> unsafeChannels, 5500 @CoexRestriction int restrictions) { 5501 Executor executor; 5502 CoexCallback callback; 5503 synchronized (mLock) { 5504 executor = mExecutor; 5505 callback = mCallback; 5506 } 5507 if (executor == null || callback == null) { 5508 return; 5509 } 5510 Binder.clearCallingIdentity(); 5511 executor.execute(() -> 5512 callback.onCoexUnsafeChannelsChanged(unsafeChannels, restrictions)); 5513 } 5514 } 5515 } 5516 5517 /** 5518 * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. 5519 * Note that starting Soft AP mode may disable station mode operation if the device does not 5520 * support concurrency. 5521 * @param wifiConfig SSID, security and channel details as part of WifiConfiguration, or null to 5522 * use the persisted Soft AP configuration that was previously set using 5523 * {@link #setWifiApConfiguration(WifiConfiguration)}. 5524 * @return {@code true} if the operation succeeded, {@code false} otherwise 5525 * 5526 * @hide 5527 */ 5528 @RequiresPermission(anyOf = { 5529 android.Manifest.permission.NETWORK_STACK, 5530 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5531 }) startSoftAp(@ullable WifiConfiguration wifiConfig)5532 public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) { 5533 try { 5534 return mService.startSoftAp(wifiConfig, mContext.getOpPackageName()); 5535 } catch (RemoteException e) { 5536 throw e.rethrowFromSystemServer(); 5537 } 5538 } 5539 5540 /** 5541 * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. 5542 * Note that starting Soft AP mode may disable station mode operation if the device does not 5543 * support concurrency. 5544 * 5545 * Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid 5546 * unexpected error due to invalid configuration. 5547 * 5548 * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP, or 5549 * null to use the persisted Soft AP configuration that was previously set 5550 * using {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)}. 5551 * @return {@code true} if the operation succeeded, {@code false} otherwise 5552 * 5553 * @hide 5554 */ 5555 @SystemApi 5556 @RequiresPermission(anyOf = { 5557 android.Manifest.permission.NETWORK_STACK, 5558 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5559 }) startTetheredHotspot(@ullable SoftApConfiguration softApConfig)5560 public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) { 5561 try { 5562 return mService.startTetheredHotspot(softApConfig, mContext.getOpPackageName()); 5563 } catch (RemoteException e) { 5564 throw e.rethrowFromSystemServer(); 5565 } 5566 } 5567 5568 5569 /** 5570 * Stop SoftAp mode. 5571 * Note that stopping softap mode will restore the previous wifi mode. 5572 * @return {@code true} if the operation succeeds, {@code false} otherwise 5573 * 5574 * @hide 5575 */ 5576 @SystemApi 5577 @RequiresPermission(anyOf = { 5578 android.Manifest.permission.NETWORK_STACK, 5579 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK 5580 }) stopSoftAp()5581 public boolean stopSoftAp() { 5582 try { 5583 return mService.stopSoftAp(); 5584 } catch (RemoteException e) { 5585 throw e.rethrowFromSystemServer(); 5586 } 5587 } 5588 5589 /** 5590 * Check if input configuration is valid. 5591 * 5592 * @param config a configuration would like to be checked. 5593 * @return true if config is valid, otherwise false. 5594 */ validateSoftApConfiguration(@onNull SoftApConfiguration config)5595 public boolean validateSoftApConfiguration(@NonNull SoftApConfiguration config) { 5596 if (config == null) { 5597 throw new IllegalArgumentException(TAG + ": config can not be null"); 5598 } 5599 try { 5600 return mService.validateSoftApConfiguration(config); 5601 } catch (RemoteException e) { 5602 throw e.rethrowFromSystemServer(); 5603 } 5604 } 5605 5606 /** 5607 * Request a local only hotspot that an application can use to communicate between co-located 5608 * devices connected to the created WiFi hotspot. The network created by this method will not 5609 * have Internet access. Each application can make a single request for the hotspot, but 5610 * multiple applications could be requesting the hotspot at the same time. When multiple 5611 * applications have successfully registered concurrently, they will be sharing the underlying 5612 * hotspot. {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} is called 5613 * when the hotspot is ready for use by the application. 5614 * <p> 5615 * Each application can make a single active call to this method. The {@link 5616 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} callback supplies the 5617 * requestor with a {@link LocalOnlyHotspotReservation} that contains a 5618 * {@link SoftApConfiguration} with the SSID, security type and credentials needed to connect 5619 * to the hotspot. Communicating this information is up to the application. 5620 * <p> 5621 * If the LocalOnlyHotspot cannot be created, the {@link LocalOnlyHotspotCallback#onFailed(int)} 5622 * method will be called. Example failures include errors bringing up the network or if 5623 * there is an incompatible operating mode. For example, if the user is currently using Wifi 5624 * Tethering to provide an upstream to another device, LocalOnlyHotspot may not start due to 5625 * an incompatible mode. The possible error codes include: 5626 * {@link LocalOnlyHotspotCallback#ERROR_NO_CHANNEL}, 5627 * {@link LocalOnlyHotspotCallback#ERROR_GENERIC}, 5628 * {@link LocalOnlyHotspotCallback#ERROR_INCOMPATIBLE_MODE} and 5629 * {@link LocalOnlyHotspotCallback#ERROR_TETHERING_DISALLOWED}. 5630 * <p> 5631 * Internally, requests will be tracked to prevent the hotspot from being torn down while apps 5632 * are still using it. The {@link LocalOnlyHotspotReservation} object passed in the {@link 5633 * LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call should be closed when 5634 * the LocalOnlyHotspot is no longer needed using {@link LocalOnlyHotspotReservation#close()}. 5635 * Since the hotspot may be shared among multiple applications, removing the final registered 5636 * application request will trigger the hotspot teardown. This means that applications should 5637 * not listen to broadcasts containing wifi state to determine if the hotspot was stopped after 5638 * they are done using it. Additionally, once {@link LocalOnlyHotspotReservation#close()} is 5639 * called, applications will not receive callbacks of any kind. 5640 * <p> 5641 * Applications should be aware that the user may also stop the LocalOnlyHotspot through the 5642 * Settings UI; it is not guaranteed to stay up as long as there is a requesting application. 5643 * The requestors will be notified of this case via 5644 * {@link LocalOnlyHotspotCallback#onStopped()}. Other cases may arise where the hotspot is 5645 * torn down (Emergency mode, etc). Application developers should be aware that it can stop 5646 * unexpectedly, but they will receive a notification if they have properly registered. 5647 * <p> 5648 * Applications should also be aware that this network will be shared with other applications. 5649 * Applications are responsible for protecting their data on this network (e.g. TLS). 5650 * <p> 5651 * Applications targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later need to have 5652 * the following permissions: {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 5653 * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES}. 5654 * Applications targeting {@link Build.VERSION_CODES#S} or prior SDK levels need to have the 5655 * following permissions: {@link android.Manifest.permission#CHANGE_WIFI_STATE} and 5656 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} 5657 * Callers without 5658 * the permissions will trigger a {@link java.lang.SecurityException}. 5659 * <p> 5660 * @param callback LocalOnlyHotspotCallback for the application to receive updates about 5661 * operating status. 5662 * @param handler Handler to be used for callbacks. If the caller passes a null Handler, the 5663 * main thread will be used. 5664 */ 5665 @RequiresPermission(allOf = {CHANGE_WIFI_STATE, ACCESS_FINE_LOCATION, NEARBY_WIFI_DEVICES}, 5666 conditional = true) startLocalOnlyHotspot(LocalOnlyHotspotCallback callback, @Nullable Handler handler)5667 public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback, 5668 @Nullable Handler handler) { 5669 Executor executor = handler == null ? null : new HandlerExecutor(handler); 5670 startLocalOnlyHotspotInternal(null, executor, callback); 5671 } 5672 5673 /** 5674 * Starts a local-only hotspot with a specific configuration applied. See 5675 * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}. 5676 * 5677 * Applications need either {@link android.Manifest.permission#NETWORK_SETUP_WIZARD}, 5678 * {@link android.Manifest.permission#NETWORK_SETTINGS} or 5679 * {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} to call this method. 5680 * 5681 * Since custom configuration settings may be incompatible with each other, the hotspot started 5682 * through this method cannot coexist with another hotspot created through 5683 * startLocalOnlyHotspot. If this is attempted, the first hotspot request wins and others 5684 * receive {@link LocalOnlyHotspotCallback#ERROR_GENERIC} through 5685 * {@link LocalOnlyHotspotCallback#onFailed}. 5686 * 5687 * @param config Custom configuration for the hotspot. See {@link SoftApConfiguration}. 5688 * @param executor Executor to run callback methods on, or null to use the main thread. 5689 * @param callback Callback object for updates about hotspot status, or null for no updates. 5690 * @hide 5691 */ 5692 @SystemApi 5693 @RequiresPermission(anyOf = { 5694 android.Manifest.permission.NETWORK_SETTINGS, 5695 android.Manifest.permission.NETWORK_SETUP_WIZARD, 5696 NEARBY_WIFI_DEVICES}) startLocalOnlyHotspot(@onNull SoftApConfiguration config, @Nullable @CallbackExecutor Executor executor, @Nullable LocalOnlyHotspotCallback callback)5697 public void startLocalOnlyHotspot(@NonNull SoftApConfiguration config, 5698 @Nullable @CallbackExecutor Executor executor, 5699 @Nullable LocalOnlyHotspotCallback callback) { 5700 Objects.requireNonNull(config); 5701 startLocalOnlyHotspotInternal(config, executor, callback); 5702 } 5703 5704 /** 5705 * Common implementation of both configurable and non-configurable LOHS. 5706 * 5707 * @param config App-specified configuration, or null. When present, additional privileges are 5708 * required, and the hotspot cannot be shared with other clients. 5709 * @param executor Executor to run callback methods on, or null to use the main thread. 5710 * @param callback Callback object for updates about hotspot status, or null for no updates. 5711 */ startLocalOnlyHotspotInternal( @ullable SoftApConfiguration config, @Nullable @CallbackExecutor Executor executor, @Nullable LocalOnlyHotspotCallback callback)5712 private void startLocalOnlyHotspotInternal( 5713 @Nullable SoftApConfiguration config, 5714 @Nullable @CallbackExecutor Executor executor, 5715 @Nullable LocalOnlyHotspotCallback callback) { 5716 if (executor == null) { 5717 executor = mContext.getMainExecutor(); 5718 } 5719 synchronized (mLock) { 5720 LocalOnlyHotspotCallbackProxy proxy = 5721 new LocalOnlyHotspotCallbackProxy(this, executor, callback); 5722 try { 5723 String packageName = mContext.getOpPackageName(); 5724 String featureId = mContext.getAttributionTag(); 5725 Bundle extras = new Bundle(); 5726 if (SdkLevel.isAtLeastS()) { 5727 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 5728 mContext.getAttributionSource()); 5729 } 5730 int returnCode = mService.startLocalOnlyHotspot(proxy, packageName, featureId, 5731 config, extras); 5732 if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) { 5733 // Send message to the proxy to make sure we call back on the correct thread 5734 proxy.onHotspotFailed(returnCode); 5735 return; 5736 } 5737 mLOHSCallbackProxy = proxy; 5738 } catch (RemoteException e) { 5739 throw e.rethrowFromSystemServer(); 5740 } 5741 } 5742 } 5743 5744 /** 5745 * Cancels a pending local only hotspot request. This can be used by the calling application to 5746 * cancel the existing request if the provided callback has not been triggered. Calling this 5747 * method will be equivalent to closing the returned LocalOnlyHotspotReservation, but it is not 5748 * explicitly required. 5749 * <p> 5750 * When cancelling this request, application developers should be aware that there may still be 5751 * outstanding local only hotspot requests and the hotspot may still start, or continue running. 5752 * Additionally, if a callback was registered, it will no longer be triggered after calling 5753 * cancel. 5754 * 5755 * @hide 5756 */ 5757 @UnsupportedAppUsage cancelLocalOnlyHotspotRequest()5758 public void cancelLocalOnlyHotspotRequest() { 5759 synchronized (mLock) { 5760 stopLocalOnlyHotspot(); 5761 } 5762 } 5763 5764 /** 5765 * Method used to inform WifiService that the LocalOnlyHotspot is no longer needed. This 5766 * method is used by WifiManager to release LocalOnlyHotspotReservations held by calling 5767 * applications and removes the internal tracking for the hotspot request. When all requesting 5768 * applications are finished using the hotspot, it will be stopped and WiFi will return to the 5769 * previous operational mode. 5770 * 5771 * This method should not be called by applications. Instead, they should call the close() 5772 * method on their LocalOnlyHotspotReservation. 5773 */ stopLocalOnlyHotspot()5774 private void stopLocalOnlyHotspot() { 5775 synchronized (mLock) { 5776 if (mLOHSCallbackProxy == null) { 5777 // nothing to do, the callback was already cleaned up. 5778 return; 5779 } 5780 mLOHSCallbackProxy = null; 5781 try { 5782 mService.stopLocalOnlyHotspot(); 5783 } catch (RemoteException e) { 5784 throw e.rethrowFromSystemServer(); 5785 } 5786 } 5787 } 5788 5789 /** 5790 * Registers a callback for local only hotspot. See {@link SoftApCallback}. Caller will receive 5791 * the following callbacks on registration: 5792 * <ul> 5793 * <li> {@link SoftApCallback#onStateChanged(int, int)}</li> 5794 * <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li> 5795 * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li> 5796 * <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li> 5797 * </ul> 5798 * 5799 * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know 5800 * if there are any clients connected to a specific bridged instance of this AP 5801 * (if bridged AP is enabled). 5802 * 5803 * Note: Caller will receive the callback 5804 * {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} 5805 * on registration when there are clients connected to AP. 5806 * 5807 * These will be dispatched on registration to provide the caller with the current state 5808 * (and are not an indication of any current change). Note that receiving an immediate 5809 * WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start 5810 * soft AP has failed. Caller can unregister a previously registered callback using 5811 * {@link #unregisterLocalOnlyHotspotSoftApCallback} 5812 * <p> 5813 * 5814 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 5815 * object. 5816 * @param callback Callback for local only hotspot events 5817 * @hide 5818 */ 5819 @SystemApi 5820 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 5821 @RequiresPermission(NEARBY_WIFI_DEVICES) registerLocalOnlyHotspotSoftApCallback(@onNull @allbackExecutor Executor executor, @NonNull SoftApCallback callback)5822 public void registerLocalOnlyHotspotSoftApCallback(@NonNull @CallbackExecutor Executor executor, 5823 @NonNull SoftApCallback callback) { 5824 if (!SdkLevel.isAtLeastT()) { 5825 throw new UnsupportedOperationException(); 5826 } 5827 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 5828 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 5829 Log.v(TAG, "registerLocalOnlyHotspotSoftApCallback: callback=" + callback + ", executor=" 5830 + executor); 5831 try { 5832 synchronized (sLocalOnlyHotspotSoftApCallbackMap) { 5833 ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback, 5834 IFACE_IP_MODE_LOCAL_ONLY); 5835 sLocalOnlyHotspotSoftApCallbackMap.put(System.identityHashCode(callback), 5836 binderCallback); 5837 Bundle extras = new Bundle(); 5838 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 5839 mContext.getAttributionSource()); 5840 mService.registerLocalOnlyHotspotSoftApCallback(binderCallback, extras); 5841 } 5842 } catch (RemoteException e) { 5843 throw e.rethrowFromSystemServer(); 5844 } 5845 } 5846 5847 /** 5848 * Allow callers to unregister a previously registered callback. After calling this method, 5849 * applications will no longer receive local only hotspot events. 5850 * 5851 * <p> 5852 * 5853 * @param callback Callback to unregister for soft AP events 5854 * 5855 * @hide 5856 */ 5857 @SystemApi 5858 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 5859 @RequiresPermission(NEARBY_WIFI_DEVICES) unregisterLocalOnlyHotspotSoftApCallback(@onNull SoftApCallback callback)5860 public void unregisterLocalOnlyHotspotSoftApCallback(@NonNull SoftApCallback callback) { 5861 if (!SdkLevel.isAtLeastT()) { 5862 throw new UnsupportedOperationException(); 5863 } 5864 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 5865 Log.v(TAG, "unregisterLocalOnlyHotspotSoftApCallback: callback=" + callback); 5866 5867 try { 5868 synchronized (sLocalOnlyHotspotSoftApCallbackMap) { 5869 int callbackIdentifier = System.identityHashCode(callback); 5870 if (!sLocalOnlyHotspotSoftApCallbackMap.contains(callbackIdentifier)) { 5871 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 5872 return; 5873 } 5874 Bundle extras = new Bundle(); 5875 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 5876 mContext.getAttributionSource()); 5877 mService.unregisterLocalOnlyHotspotSoftApCallback( 5878 sLocalOnlyHotspotSoftApCallbackMap.get(callbackIdentifier), extras); 5879 sLocalOnlyHotspotSoftApCallbackMap.remove(callbackIdentifier); 5880 } 5881 } catch (RemoteException e) { 5882 throw e.rethrowFromSystemServer(); 5883 } 5884 } 5885 5886 /** 5887 * Allow callers (Settings UI) to watch LocalOnlyHotspot state changes. Callers will 5888 * receive a {@link LocalOnlyHotspotSubscription} object as a parameter of the 5889 * {@link LocalOnlyHotspotObserver#onRegistered(LocalOnlyHotspotSubscription)}. The registered 5890 * callers will receive the {@link LocalOnlyHotspotObserver#onStarted(SoftApConfiguration)} and 5891 * {@link LocalOnlyHotspotObserver#onStopped()} callbacks. 5892 * <p> 5893 * Applications should have the 5894 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} 5895 * permission. Callers without the permission will trigger a 5896 * {@link java.lang.SecurityException}. 5897 * <p> 5898 * @param observer LocalOnlyHotspotObserver callback. 5899 * @param handler Handler to use for callbacks 5900 * 5901 * @hide 5902 */ watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer, @Nullable Handler handler)5903 public void watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer, 5904 @Nullable Handler handler) { 5905 Executor executor = handler == null ? mContext.getMainExecutor() 5906 : new HandlerExecutor(handler); 5907 synchronized (mLock) { 5908 mLOHSObserverProxy = 5909 new LocalOnlyHotspotObserverProxy(this, executor, observer); 5910 try { 5911 mService.startWatchLocalOnlyHotspot(mLOHSObserverProxy); 5912 mLOHSObserverProxy.registered(); 5913 } catch (RemoteException e) { 5914 mLOHSObserverProxy = null; 5915 throw e.rethrowFromSystemServer(); 5916 } 5917 } 5918 } 5919 5920 /** 5921 * Allow callers to stop watching LocalOnlyHotspot state changes. After calling this method, 5922 * applications will no longer receive callbacks. 5923 * 5924 * @hide 5925 */ unregisterLocalOnlyHotspotObserver()5926 public void unregisterLocalOnlyHotspotObserver() { 5927 synchronized (mLock) { 5928 if (mLOHSObserverProxy == null) { 5929 // nothing to do, the callback was already cleaned up 5930 return; 5931 } 5932 mLOHSObserverProxy = null; 5933 try { 5934 mService.stopWatchLocalOnlyHotspot(); 5935 } catch (RemoteException e) { 5936 throw e.rethrowFromSystemServer(); 5937 } 5938 } 5939 } 5940 5941 /** 5942 * Gets the tethered Wi-Fi hotspot enabled state. 5943 * @return One of {@link #WIFI_AP_STATE_DISABLED}, 5944 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 5945 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 5946 * @see #isWifiApEnabled() 5947 * 5948 * @hide 5949 */ 5950 @SystemApi 5951 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) getWifiApState()5952 public int getWifiApState() { 5953 try { 5954 return mService.getWifiApEnabledState(); 5955 } catch (RemoteException e) { 5956 throw e.rethrowFromSystemServer(); 5957 } 5958 } 5959 5960 /** 5961 * Return whether tethered Wi-Fi AP is enabled or disabled. 5962 * @return {@code true} if tethered Wi-Fi AP is enabled 5963 * @see #getWifiApState() 5964 * 5965 * @hide 5966 */ 5967 @SystemApi 5968 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) isWifiApEnabled()5969 public boolean isWifiApEnabled() { 5970 return getWifiApState() == WIFI_AP_STATE_ENABLED; 5971 } 5972 5973 /** 5974 * Gets the tethered Wi-Fi AP Configuration. 5975 * @return AP details in WifiConfiguration 5976 * 5977 * Note that AP detail may contain configuration which is cannot be represented 5978 * by the legacy WifiConfiguration, in such cases a null will be returned. 5979 * 5980 * @deprecated This API is deprecated. Use {@link #getSoftApConfiguration()} instead. 5981 * @hide 5982 */ 5983 @Nullable 5984 @SystemApi 5985 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) 5986 @Deprecated getWifiApConfiguration()5987 public WifiConfiguration getWifiApConfiguration() { 5988 try { 5989 return mService.getWifiApConfiguration(); 5990 } catch (RemoteException e) { 5991 throw e.rethrowFromSystemServer(); 5992 } 5993 } 5994 5995 /** 5996 * Gets the Wi-Fi tethered AP Configuration. 5997 * @return AP details in {@link SoftApConfiguration} 5998 * 5999 * @hide 6000 */ 6001 @NonNull 6002 @SystemApi 6003 @RequiresPermission(anyOf = { 6004 android.Manifest.permission.NETWORK_SETTINGS, 6005 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 6006 }) getSoftApConfiguration()6007 public SoftApConfiguration getSoftApConfiguration() { 6008 try { 6009 return mService.getSoftApConfiguration(); 6010 } catch (RemoteException e) { 6011 throw e.rethrowFromSystemServer(); 6012 } 6013 } 6014 6015 /** 6016 * Gets the last configured Wi-Fi tethered AP passphrase. 6017 * 6018 * Note: It may be null when there is no passphrase changed since 6019 * device boot. 6020 * 6021 * @param executor The executor on which callback will be invoked. 6022 * @param resultCallback An asynchronous callback that will return the last configured 6023 * Wi-Fi tethered AP passphrase. 6024 * 6025 * @throws SecurityException if the caller does not have permission. 6026 * @throws NullPointerException if the caller provided invalid inputs. 6027 * 6028 * @hide 6029 */ 6030 @Nullable 6031 @SystemApi 6032 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) queryLastConfiguredTetheredApPassphraseSinceBoot( @onNull @allbackExecutor Executor executor, @NonNull Consumer<String> resultCallback)6033 public void queryLastConfiguredTetheredApPassphraseSinceBoot( 6034 @NonNull @CallbackExecutor Executor executor, 6035 @NonNull Consumer<String> resultCallback) { 6036 Objects.requireNonNull(executor, "executor cannot be null"); 6037 Objects.requireNonNull(resultCallback, "resultsCallback cannot be null"); 6038 try { 6039 mService.queryLastConfiguredTetheredApPassphraseSinceBoot( 6040 new IStringListener.Stub() { 6041 @Override 6042 public void onResult(String value) { 6043 Binder.clearCallingIdentity(); 6044 executor.execute(() -> { 6045 resultCallback.accept(value); 6046 }); 6047 } 6048 }); 6049 } catch (RemoteException e) { 6050 throw e.rethrowFromSystemServer(); 6051 } 6052 } 6053 6054 /** 6055 * Sets the tethered Wi-Fi AP Configuration. 6056 * @return {@code true} if the operation succeeded, {@code false} otherwise 6057 * 6058 * @deprecated This API is deprecated. Use {@link #setSoftApConfiguration(SoftApConfiguration)} 6059 * instead. 6060 * @hide 6061 */ 6062 @SystemApi 6063 @RequiresPermission(CHANGE_WIFI_STATE) 6064 @Deprecated setWifiApConfiguration(WifiConfiguration wifiConfig)6065 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) { 6066 try { 6067 return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName()); 6068 } catch (RemoteException e) { 6069 throw e.rethrowFromSystemServer(); 6070 } 6071 } 6072 6073 /** 6074 * Sets the tethered Wi-Fi AP Configuration. 6075 * 6076 * If the API is called while the tethered soft AP is enabled, the configuration will apply to 6077 * the current soft AP if the new configuration only includes 6078 * {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} 6079 * or {@link SoftApConfiguration.Builder#setShutdownTimeoutMillis(long)} 6080 * or {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)} 6081 * or {@link SoftApConfiguration.Builder#setBlockedClientList(List)} 6082 * or {@link SoftApConfiguration.Builder#setAllowedClientList(List)} 6083 * or {@link SoftApConfiguration.Builder#setAutoShutdownEnabled(boolean)} 6084 * or {@link SoftApConfiguration.Builder#setBridgedModeOpportunisticShutdownEnabled(boolean)} 6085 * 6086 * Otherwise, the configuration changes will be applied when the Soft AP is next started 6087 * (the framework will not stop/start the AP). 6088 * 6089 * Note: Call {@link WifiManager#validateSoftApConfiguration(SoftApConfiguration)} to avoid 6090 * unexpected error due to invalid configuration. 6091 * 6092 * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP. 6093 * @return {@code true} if the operation succeeded, {@code false} otherwise 6094 * 6095 * @hide 6096 */ 6097 @SystemApi 6098 @RequiresPermission(anyOf = { 6099 android.Manifest.permission.NETWORK_SETTINGS, 6100 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 6101 }) setSoftApConfiguration(@onNull SoftApConfiguration softApConfig)6102 public boolean setSoftApConfiguration(@NonNull SoftApConfiguration softApConfig) { 6103 try { 6104 return mService.setSoftApConfiguration( 6105 softApConfig, mContext.getOpPackageName()); 6106 } catch (RemoteException e) { 6107 throw e.rethrowFromSystemServer(); 6108 } 6109 } 6110 6111 /** 6112 * Enable/Disable TDLS on a specific local route. 6113 * 6114 * <p> 6115 * TDLS enables two wireless endpoints to talk to each other directly 6116 * without going through the access point that is managing the local 6117 * network. It saves bandwidth and improves quality of the link. 6118 * </p> 6119 * <p> 6120 * This API enables/disables the option of using TDLS. If enabled, the 6121 * underlying hardware is free to use TDLS or a hop through the access 6122 * point. If disabled, existing TDLS session is torn down and 6123 * hardware is restricted to use access point for transferring wireless 6124 * packets. Default value for all routes is 'disabled', meaning restricted 6125 * to use access point for transferring packets. 6126 * </p> 6127 * 6128 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 6129 * @param enable true = setup and false = tear down TDLS 6130 */ setTdlsEnabled(InetAddress remoteIPAddress, boolean enable)6131 public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) { 6132 try { 6133 mService.enableTdls(remoteIPAddress.getHostAddress(), enable); 6134 } catch (RemoteException e) { 6135 throw e.rethrowFromSystemServer(); 6136 } 6137 } 6138 6139 /** 6140 * Enable/Disable TDLS on a specific local route. 6141 * 6142 * Similar to {@link #setTdlsEnabled(InetAddress, boolean)}, except 6143 * this version sends the result of the Enable/Disable request. 6144 * 6145 * @param remoteIPAddress IP address of the endpoint to setup TDLS with 6146 * @param enable true = setup and false = tear down TDLS 6147 * @param executor The executor on which callback will be invoked. 6148 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 6149 * whether TDLS was successfully enabled or disabled. 6150 * {@code true} for success, {@code false} for failure. 6151 * 6152 * @throws NullPointerException if the caller provided invalid inputs. 6153 */ setTdlsEnabled(@onNull InetAddress remoteIPAddress, boolean enable, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)6154 public void setTdlsEnabled(@NonNull InetAddress remoteIPAddress, boolean enable, 6155 @NonNull @CallbackExecutor Executor executor, 6156 @NonNull Consumer<Boolean> resultsCallback) { 6157 Objects.requireNonNull(executor, "executor cannot be null"); 6158 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6159 Objects.requireNonNull(remoteIPAddress, "remote IP address cannot be null"); 6160 try { 6161 mService.enableTdlsWithRemoteIpAddress(remoteIPAddress.getHostAddress(), enable, 6162 new IBooleanListener.Stub() { 6163 @Override 6164 public void onResult(boolean value) { 6165 Binder.clearCallingIdentity(); 6166 executor.execute(() -> { 6167 resultsCallback.accept(value); 6168 }); 6169 } 6170 }); 6171 } catch (RemoteException e) { 6172 throw e.rethrowFromSystemServer(); 6173 } 6174 } 6175 6176 /** 6177 * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except 6178 * this version allows you to specify remote endpoint with a MAC address. 6179 * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab 6180 * @param enable true = setup and false = tear down TDLS 6181 */ setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable)6182 public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) { 6183 try { 6184 mService.enableTdlsWithMacAddress(remoteMacAddress, enable); 6185 } catch (RemoteException e) { 6186 throw e.rethrowFromSystemServer(); 6187 } 6188 } 6189 6190 /** 6191 * Enable/Disable TDLS with a specific peer Mac Address. 6192 * 6193 * Similar to {@link #setTdlsEnabledWithMacAddress(String, boolean)}, except 6194 * this version sends the result of the Enable/Disable request. 6195 * 6196 * @param remoteMacAddress Mac address of the endpoint to setup TDLS with 6197 * @param enable true = setup and false = tear down TDLS 6198 * @param executor The executor on which callback will be invoked. 6199 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 6200 * whether TDLS was successfully enabled or disabled. 6201 * {@code true} for success, {@code false} for failure. 6202 * 6203 * @throws NullPointerException if the caller provided invalid inputs. 6204 */ setTdlsEnabledWithMacAddress(@onNull String remoteMacAddress, boolean enable, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)6205 public void setTdlsEnabledWithMacAddress(@NonNull String remoteMacAddress, boolean enable, 6206 @NonNull @CallbackExecutor Executor executor, 6207 @NonNull Consumer<Boolean> resultsCallback) { 6208 Objects.requireNonNull(executor, "executor cannot be null"); 6209 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6210 Objects.requireNonNull(remoteMacAddress, "remote Mac address cannot be null"); 6211 try { 6212 mService.enableTdlsWithRemoteMacAddress(remoteMacAddress, enable, 6213 new IBooleanListener.Stub() { 6214 @Override 6215 public void onResult(boolean value) { 6216 Binder.clearCallingIdentity(); 6217 executor.execute(() -> { 6218 resultsCallback.accept(value); 6219 }); 6220 } 6221 }); 6222 } catch (RemoteException e) { 6223 throw e.rethrowFromSystemServer(); 6224 } 6225 } 6226 6227 /** 6228 * Check if a TDLS session can be established at this time via 6229 * {@link #setTdlsEnabled(InetAddress, boolean)} or 6230 * {@link #setTdlsEnabledWithMacAddress(String, boolean)} or 6231 * {@link #setTdlsEnabled(InetAddress, boolean, Executor, Consumer)} or 6232 * {@link #setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer)} 6233 * 6234 * Internally framework checks the STA connected state, device support for TDLS and 6235 * the number of TDLS sessions available in driver/firmware. 6236 * 6237 * @param executor The executor on which callback will be invoked. 6238 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 6239 * whether a TDLS session can be established at this time. 6240 * {@code true} for available, {@code false} for not available. 6241 * 6242 * @throws NullPointerException if the caller provided invalid inputs. 6243 */ isTdlsOperationCurrentlyAvailable(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)6244 public void isTdlsOperationCurrentlyAvailable(@NonNull @CallbackExecutor Executor executor, 6245 @NonNull Consumer<Boolean> resultsCallback) { 6246 Objects.requireNonNull(executor, "executor cannot be null"); 6247 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6248 try { 6249 mService.isTdlsOperationCurrentlyAvailable( 6250 new IBooleanListener.Stub() { 6251 @Override 6252 public void onResult(boolean value) { 6253 Binder.clearCallingIdentity(); 6254 executor.execute(() -> { 6255 resultsCallback.accept(value); 6256 }); 6257 } 6258 }); 6259 } catch (RemoteException e) { 6260 throw e.rethrowFromSystemServer(); 6261 } 6262 } 6263 6264 /** 6265 * Return the maximum number of concurrent TDLS sessions supported by the device. 6266 * 6267 * @param executor The executor on which callback will be invoked. 6268 * @param resultsCallback An asynchronous callback that will return the maximum number of 6269 * concurrent TDLS sessions supported by the device. Returns 6270 * {@code -1} if information is not available, 6271 * e.g. if the driver/firmware doesn't provide this information. 6272 * 6273 * @throws NullPointerException if the caller provided invalid inputs. 6274 * @throws UnsupportedOperationException if the feature is not available. 6275 */ 6276 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) getMaxSupportedConcurrentTdlsSessions(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)6277 public void getMaxSupportedConcurrentTdlsSessions(@NonNull @CallbackExecutor Executor executor, 6278 @NonNull Consumer<Integer> resultsCallback) { 6279 Objects.requireNonNull(executor, "executor cannot be null"); 6280 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6281 try { 6282 mService.getMaxSupportedConcurrentTdlsSessions( 6283 new IIntegerListener.Stub() { 6284 @Override 6285 public void onResult(int value) { 6286 Binder.clearCallingIdentity(); 6287 executor.execute(() -> { 6288 resultsCallback.accept(value); 6289 }); 6290 } 6291 }); 6292 } catch (RemoteException e) { 6293 throw e.rethrowFromSystemServer(); 6294 } 6295 } 6296 6297 /** 6298 * Return the number of currently enabled TDLS sessions. 6299 * 6300 * Tracks the number of peers enabled for TDLS session via 6301 * {@link #setTdlsEnabled(InetAddress, boolean) }, 6302 * {@link #setTdlsEnabledWithMacAddress(String, boolean) }, 6303 * {@link #setTdlsEnabled(InetAddress, boolean, Executor, Consumer) } and 6304 * {@link #setTdlsEnabledWithMacAddress(String, boolean, Executor, Consumer) } 6305 * 6306 * @param executor The executor on which callback will be invoked. 6307 * @param resultsCallback An asynchronous callback that will return the number of Peer 6308 * Mac addresses configured in the driver for TDLS session. 6309 * 6310 * @throws NullPointerException if the caller provided invalid inputs. 6311 */ getNumberOfEnabledTdlsSessions(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)6312 public void getNumberOfEnabledTdlsSessions(@NonNull @CallbackExecutor Executor executor, 6313 @NonNull Consumer<Integer> resultsCallback) { 6314 Objects.requireNonNull(executor, "executor cannot be null"); 6315 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 6316 try { 6317 mService.getNumberOfEnabledTdlsSessions( 6318 new IIntegerListener.Stub() { 6319 @Override 6320 public void onResult(int value) { 6321 Binder.clearCallingIdentity(); 6322 executor.execute(() -> { 6323 resultsCallback.accept(value); 6324 }); 6325 } 6326 }); 6327 } catch (RemoteException e) { 6328 throw e.rethrowFromSystemServer(); 6329 } 6330 } 6331 6332 /** @hide */ 6333 @Retention(RetentionPolicy.SOURCE) 6334 @IntDef({ActionListener.FAILURE_INTERNAL_ERROR, 6335 ActionListener.FAILURE_IN_PROGRESS, 6336 ActionListener.FAILURE_BUSY, 6337 ActionListener.FAILURE_INVALID_ARGS, 6338 ActionListener.FAILURE_NOT_AUTHORIZED}) 6339 public @interface ActionListenerFailureReason {} 6340 6341 /* WPS specific errors */ 6342 /** WPS overlap detected 6343 * @deprecated This is deprecated 6344 */ 6345 public static final int WPS_OVERLAP_ERROR = 3; 6346 /** WEP on WPS is prohibited 6347 * @deprecated This is deprecated 6348 */ 6349 public static final int WPS_WEP_PROHIBITED = 4; 6350 /** TKIP only prohibited 6351 * @deprecated This is deprecated 6352 */ 6353 public static final int WPS_TKIP_ONLY_PROHIBITED = 5; 6354 /** Authentication failure on WPS 6355 * @deprecated This is deprecated 6356 */ 6357 public static final int WPS_AUTH_FAILURE = 6; 6358 /** WPS timed out 6359 * @deprecated This is deprecated 6360 */ 6361 public static final int WPS_TIMED_OUT = 7; 6362 6363 /** 6364 * Interface for callback invocation on an application action. 6365 * @hide 6366 */ 6367 @SystemApi 6368 public interface ActionListener { 6369 /** 6370 * Passed with {@link #onFailure}. 6371 * Indicates that the operation failed due to an internal error. 6372 */ 6373 int FAILURE_INTERNAL_ERROR = 0; 6374 6375 /** 6376 * Passed with {@link #onFailure}. 6377 * Indicates that the operation is already in progress. 6378 */ 6379 int FAILURE_IN_PROGRESS = 1; 6380 6381 /** 6382 * Passed with {@link #onFailure}. 6383 * Indicates that the operation failed because the framework is busy and is unable to 6384 * service the request. 6385 */ 6386 int FAILURE_BUSY = 2; 6387 6388 /** 6389 * Passed with {@link #onFailure}. 6390 * Indicates that the operation failed due to invalid inputs. 6391 */ 6392 int FAILURE_INVALID_ARGS = 3; 6393 6394 /** 6395 * Passed with {@link #onFailure}. 6396 * Indicates that the operation failed due to insufficient user permissions. 6397 */ 6398 int FAILURE_NOT_AUTHORIZED = 4; 6399 6400 /** 6401 * The operation succeeded. 6402 */ onSuccess()6403 void onSuccess(); 6404 /** 6405 * The operation failed. 6406 * @param reason The reason for failure depends on the operation. 6407 */ onFailure(@ctionListenerFailureReason int reason)6408 void onFailure(@ActionListenerFailureReason int reason); 6409 } 6410 6411 /** Interface for callback invocation on a start WPS action 6412 * @deprecated This is deprecated 6413 */ 6414 public static abstract class WpsCallback { 6415 6416 /** WPS start succeeded 6417 * @deprecated This API is deprecated 6418 */ onStarted(String pin)6419 public abstract void onStarted(String pin); 6420 6421 /** WPS operation completed successfully 6422 * @deprecated This API is deprecated 6423 */ onSucceeded()6424 public abstract void onSucceeded(); 6425 6426 /** 6427 * WPS operation failed 6428 * @param reason The reason for failure could be one of 6429 * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR}, 6430 * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE} 6431 * and some generic errors. 6432 * @deprecated This API is deprecated 6433 */ onFailed(int reason)6434 public abstract void onFailed(int reason); 6435 } 6436 6437 /** 6438 * Base class for soft AP callback. Should be extended by applications and set when calling 6439 * {@link WifiManager#registerSoftApCallback(Executor, SoftApCallback)}. 6440 * 6441 * @hide 6442 */ 6443 @SystemApi 6444 public interface SoftApCallback { 6445 /** 6446 * Called when soft AP state changes. 6447 * 6448 * @param state the new AP state. One of {@link #WIFI_AP_STATE_DISABLED}, 6449 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED}, 6450 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED} 6451 * @param failureReason reason when in failed state. One of 6452 * {@link #SAP_START_FAILURE_GENERAL}, 6453 * {@link #SAP_START_FAILURE_NO_CHANNEL}, 6454 * {@link #SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}, 6455 * {@link #SAP_START_FAILURE_USER_REJECTED} 6456 */ onStateChanged(@ifiApState int state, @SapStartFailure int failureReason)6457 default void onStateChanged(@WifiApState int state, @SapStartFailure int failureReason) {} 6458 6459 /** 6460 * Called when the connected clients to soft AP changes. 6461 * 6462 * @param clients the currently connected clients 6463 * 6464 * @deprecated This API is deprecated. 6465 * Use {@link #onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} instead. 6466 */ 6467 @Deprecated onConnectedClientsChanged(@onNull List<WifiClient> clients)6468 default void onConnectedClientsChanged(@NonNull List<WifiClient> clients) {} 6469 6470 6471 /** 6472 * Called when the connected clients for a soft AP instance change. 6473 * 6474 * When the Soft AP is configured in single AP mode, this callback is invoked 6475 * with the same {@link SoftApInfo} for all connected clients changes. 6476 * When the Soft AP is configured as multiple Soft AP instances (using 6477 * {@link SoftApConfiguration.Builder#setBands(int[])} or 6478 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}), this 6479 * callback is invoked with the corresponding {@link SoftApInfo} for the instance in which 6480 * the connected clients changed. 6481 * 6482 * @param info The {@link SoftApInfo} of the AP. 6483 * @param clients The currently connected clients on the AP instance specified by 6484 * {@code info}. 6485 */ onConnectedClientsChanged(@onNull SoftApInfo info, @NonNull List<WifiClient> clients)6486 default void onConnectedClientsChanged(@NonNull SoftApInfo info, 6487 @NonNull List<WifiClient> clients) {} 6488 6489 /** 6490 * Called when the Soft AP information changes. 6491 * 6492 * Note: this API remains valid only when the Soft AP is configured as a single AP - 6493 * not as multiple Soft APs (which are bridged to each other). When multiple Soft APs are 6494 * configured (using {@link SoftApConfiguration.Builder#setBands(int[])} or 6495 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}) 6496 * this callback will not be triggered - use the 6497 * {@link #onInfoChanged(List<SoftApInfo>)} callback in that case. 6498 * 6499 * @param softApInfo is the Soft AP information. {@link SoftApInfo} 6500 * 6501 * @deprecated This API is deprecated. Use {@link #onInfoChanged(List<SoftApInfo>)} 6502 * instead. 6503 */ 6504 @Deprecated onInfoChanged(@onNull SoftApInfo softApInfo)6505 default void onInfoChanged(@NonNull SoftApInfo softApInfo) { 6506 // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. 6507 } 6508 6509 /** 6510 * Called when the Soft AP information changes. 6511 * 6512 * Returns information on all configured Soft AP instances. The number of the elements in 6513 * the list depends on Soft AP configuration and state: 6514 * <ul> 6515 * <li>An empty list will be returned when the Soft AP is disabled. 6516 * <li>One information element will be returned in the list when the Soft AP is configured 6517 * as a single AP or when a single Soft AP remains active. 6518 * <li>Two information elements will be returned in the list when the multiple Soft APs are 6519 * configured and are active. 6520 * (configured using {@link SoftApConfiguration.Builder#setBands(int[])} or 6521 * {@link SoftApConfiguration.Builder#setChannels(android.util.SparseIntArray)}). 6522 * </ul> 6523 * 6524 * Note: When multiple Soft AP instances are configured, one of the Soft APs may 6525 * be shut down independently of the other by the framework. This can happen if no devices 6526 * are connected to it for some duration. In that case, one information element will be 6527 * returned. 6528 * 6529 * See {@link #isBridgedApConcurrencySupported()} for support info of multiple (bridged) AP. 6530 * 6531 * @param softApInfoList is the list of the Soft AP information elements - 6532 * {@link SoftApInfo}. 6533 */ onInfoChanged(@onNull List<SoftApInfo> softApInfoList)6534 default void onInfoChanged(@NonNull List<SoftApInfo> softApInfoList) { 6535 // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. 6536 } 6537 6538 /** 6539 * Called when capability of Soft AP changes. 6540 * 6541 * @param softApCapability is the Soft AP capability. {@link SoftApCapability} 6542 */ onCapabilityChanged(@onNull SoftApCapability softApCapability)6543 default void onCapabilityChanged(@NonNull SoftApCapability softApCapability) { 6544 // Do nothing: can be updated to add SoftApCapability details (e.g. meximum supported 6545 // client number) to the UI. 6546 } 6547 6548 /** 6549 * Called when client trying to connect but device blocked the client with specific reason. 6550 * 6551 * Can be used to ask user to update client to allowed list or blocked list 6552 * when reason is {@link SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER}, or 6553 * indicate the block due to maximum supported client number limitation when reason is 6554 * {@link SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS}. 6555 * 6556 * @param client the currently blocked client. 6557 * @param blockedReason one of blocked reason from {@link SapClientBlockedReason} 6558 */ onBlockedClientConnecting(@onNull WifiClient client, @SapClientBlockedReason int blockedReason)6559 default void onBlockedClientConnecting(@NonNull WifiClient client, 6560 @SapClientBlockedReason int blockedReason) { 6561 // Do nothing: can be used to ask user to update client to allowed list or blocked list. 6562 } 6563 } 6564 6565 /** 6566 * Callback proxy for SoftApCallback objects. 6567 * 6568 * @hide 6569 */ 6570 private class SoftApCallbackProxy extends ISoftApCallback.Stub { 6571 private final Executor mExecutor; 6572 private final SoftApCallback mCallback; 6573 // Either {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}. 6574 private final int mIpMode; 6575 private Map<String, List<WifiClient>> mCurrentClients = new HashMap<>(); 6576 private Map<String, SoftApInfo> mCurrentInfos = new HashMap<>(); 6577 getConnectedClientList(Map<String, List<WifiClient>> clientsMap)6578 private List<WifiClient> getConnectedClientList(Map<String, List<WifiClient>> clientsMap) { 6579 List<WifiClient> connectedClientList = new ArrayList<>(); 6580 for (List<WifiClient> it : clientsMap.values()) { 6581 connectedClientList.addAll(it); 6582 } 6583 return connectedClientList; 6584 } 6585 SoftApCallbackProxy(Executor executor, SoftApCallback callback, int mode)6586 SoftApCallbackProxy(Executor executor, SoftApCallback callback, int mode) { 6587 mExecutor = executor; 6588 mCallback = callback; 6589 mIpMode = mode; 6590 } 6591 6592 @Override onStateChanged(int state, int failureReason)6593 public void onStateChanged(int state, int failureReason) { 6594 if (mVerboseLoggingEnabled) { 6595 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode + ", onStateChanged: state=" 6596 + state + ", failureReason=" + failureReason); 6597 } 6598 6599 Binder.clearCallingIdentity(); 6600 mExecutor.execute(() -> { 6601 mCallback.onStateChanged(state, failureReason); 6602 }); 6603 } 6604 6605 @Override onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration)6606 public void onConnectedClientsOrInfoChanged(Map<String, SoftApInfo> infos, 6607 Map<String, List<WifiClient>> clients, boolean isBridged, boolean isRegistration) { 6608 if (mVerboseLoggingEnabled) { 6609 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6610 + ", onConnectedClientsOrInfoChanged: clients: " 6611 + clients + ", infos: " + infos + ", isBridged is " + isBridged 6612 + ", isRegistration is " + isRegistration); 6613 } 6614 6615 List<SoftApInfo> changedInfoList = new ArrayList<>(infos.values()); 6616 Map<SoftApInfo, List<WifiClient>> changedInfoClients = new HashMap<>(); 6617 // Some devices may not support infos callback, allow them to support client 6618 // connection changed callback. 6619 boolean areClientsChangedWithoutInfosChanged = 6620 infos.size() == 0 && getConnectedClientList(clients).size() 6621 != getConnectedClientList(mCurrentClients).size(); 6622 boolean isInfoChanged = infos.size() != mCurrentInfos.size(); 6623 6624 if (isRegistration) { 6625 // Check if there are clients connected, put it to changedInfoClients 6626 for (SoftApInfo currentInfo : infos.values()) { 6627 String instance = currentInfo.getApInstanceIdentifier(); 6628 if (clients.getOrDefault(instance, Collections.emptyList()).size() > 0) { 6629 changedInfoClients.put(currentInfo, clients.get(instance)); 6630 } 6631 } 6632 } 6633 6634 // Check if old info removed or not (client changed case) 6635 for (SoftApInfo info : mCurrentInfos.values()) { 6636 String changedInstance = info.getApInstanceIdentifier(); 6637 List<WifiClient> changedClientList = clients.getOrDefault( 6638 changedInstance, Collections.emptyList()); 6639 if (!changedInfoList.contains(info)) { 6640 isInfoChanged = true; 6641 if (mCurrentClients.getOrDefault(changedInstance, 6642 Collections.emptyList()).size() > 0) { 6643 SoftApInfo changedInfo = infos.get(changedInstance); 6644 if (changedInfo == null || changedInfo.getFrequency() == 0) { 6645 Log.d(TAG, "SoftApCallbackProxy on mode " + mIpMode 6646 + ", info changed on client connected instance(AP disabled)"); 6647 // Send old info with empty client list for shutdown case 6648 changedInfoClients.put(info, Collections.emptyList()); 6649 } else { 6650 Log.d(TAG, "SoftApCallbackProxy on mode " + mIpMode 6651 + ", info changed on client connected instance"); 6652 changedInfoClients.put(changedInfo, changedClientList); 6653 } 6654 } 6655 } else { 6656 // info doesn't change, check client list 6657 if (changedClientList.size() 6658 != mCurrentClients 6659 .getOrDefault(changedInstance, Collections.emptyList()).size()) { 6660 // Here should notify client changed on new info(same as old info) 6661 changedInfoClients.put(info, changedClientList); 6662 } 6663 } 6664 } 6665 6666 mCurrentClients = clients; 6667 mCurrentInfos = infos; 6668 if (!isInfoChanged && changedInfoClients.isEmpty() 6669 && !isRegistration && !areClientsChangedWithoutInfosChanged) { 6670 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6671 + ", No changed & Not Registration don't need to notify the client"); 6672 return; 6673 } 6674 Binder.clearCallingIdentity(); 6675 // Notify the clients changed first for old info shutdown case 6676 for (SoftApInfo changedInfo : changedInfoClients.keySet()) { 6677 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6678 + ", send onConnectedClientsChanged, changedInfo is " 6679 + changedInfo + " and clients are " + changedInfoClients.get(changedInfo)); 6680 mExecutor.execute(() -> { 6681 mCallback.onConnectedClientsChanged( 6682 changedInfo, changedInfoClients.get(changedInfo)); 6683 }); 6684 } 6685 6686 if (isInfoChanged || isRegistration) { 6687 if (!isBridged) { 6688 SoftApInfo newInfo = changedInfoList.isEmpty() 6689 ? new SoftApInfo() : changedInfoList.get(0); 6690 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6691 + ", send InfoChanged, newInfo: " + newInfo); 6692 mExecutor.execute(() -> { 6693 mCallback.onInfoChanged(newInfo); 6694 }); 6695 } 6696 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6697 + ", send InfoChanged, changedInfoList: " + changedInfoList); 6698 mExecutor.execute(() -> { 6699 mCallback.onInfoChanged(changedInfoList); 6700 }); 6701 } 6702 6703 if (isRegistration || !changedInfoClients.isEmpty() 6704 || areClientsChangedWithoutInfosChanged) { 6705 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6706 + ", send onConnectedClientsChanged(clients): " 6707 + getConnectedClientList(clients)); 6708 mExecutor.execute(() -> { 6709 mCallback.onConnectedClientsChanged(getConnectedClientList(clients)); 6710 }); 6711 } 6712 } 6713 6714 @Override onCapabilityChanged(SoftApCapability capability)6715 public void onCapabilityChanged(SoftApCapability capability) { 6716 if (mVerboseLoggingEnabled) { 6717 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6718 + ", onCapabilityChanged: SoftApCapability = " + capability); 6719 } 6720 6721 Binder.clearCallingIdentity(); 6722 mExecutor.execute(() -> { 6723 mCallback.onCapabilityChanged(capability); 6724 }); 6725 } 6726 6727 @Override onBlockedClientConnecting(@onNull WifiClient client, int blockedReason)6728 public void onBlockedClientConnecting(@NonNull WifiClient client, int blockedReason) { 6729 if (mVerboseLoggingEnabled) { 6730 Log.v(TAG, "SoftApCallbackProxy on mode " + mIpMode 6731 + ", onBlockedClientConnecting: client =" + client 6732 + " with reason = " + blockedReason); 6733 } 6734 6735 Binder.clearCallingIdentity(); 6736 mExecutor.execute(() -> { 6737 mCallback.onBlockedClientConnecting(client, blockedReason); 6738 }); 6739 } 6740 } 6741 6742 /** 6743 * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the 6744 * following callbacks on registration: 6745 * <ul> 6746 * <li> {@link SoftApCallback#onStateChanged(int, int)}</li> 6747 * <li> {@link SoftApCallback#onConnectedClientsChanged(List<WifiClient>)}</li> 6748 * <li> {@link SoftApCallback#onInfoChanged(SoftApInfo)}</li> 6749 * <li> {@link SoftApCallback#onInfoChanged(List<SoftApInfo>)}</li> 6750 * <li> {@link SoftApCallback#onCapabilityChanged(SoftApCapability)}</li> 6751 * </ul> 6752 * 6753 * Use {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} to know 6754 * if there are any clients connected to a specific bridged instance of this AP 6755 * (if bridged AP is enabled). 6756 * 6757 * Note: Caller will receive the callback 6758 * {@link SoftApCallback#onConnectedClientsChanged(SoftApInfo, List<WifiClient>)} 6759 * on registration when there are clients connected to AP. 6760 * 6761 * These will be dispatched on registration to provide the caller with the current state 6762 * (and are not an indication of any current change). Note that receiving an immediate 6763 * WIFI_AP_STATE_FAILED value for soft AP state indicates that the latest attempt to start 6764 * soft AP has failed. Caller can unregister a previously registered callback using 6765 * {@link #unregisterSoftApCallback} 6766 * <p> 6767 * Applications should have the 6768 * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers 6769 * without the permission will trigger a {@link java.lang.SecurityException}. 6770 * <p> 6771 * 6772 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 6773 * object. 6774 * @param callback Callback for soft AP events 6775 * @hide 6776 */ 6777 @SystemApi 6778 @RequiresPermission(anyOf = { 6779 android.Manifest.permission.NETWORK_SETTINGS, 6780 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 6781 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 6782 }) registerSoftApCallback(@onNull @allbackExecutor Executor executor, @NonNull SoftApCallback callback)6783 public void registerSoftApCallback(@NonNull @CallbackExecutor Executor executor, 6784 @NonNull SoftApCallback callback) { 6785 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 6786 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 6787 Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", executor=" + executor); 6788 6789 try { 6790 synchronized (sSoftApCallbackMap) { 6791 ISoftApCallback.Stub binderCallback = new SoftApCallbackProxy(executor, callback, 6792 IFACE_IP_MODE_TETHERED); 6793 sSoftApCallbackMap.put(System.identityHashCode(callback), binderCallback); 6794 mService.registerSoftApCallback(binderCallback); 6795 } 6796 } catch (RemoteException e) { 6797 throw e.rethrowFromSystemServer(); 6798 } 6799 } 6800 6801 /** 6802 * Allow callers to unregister a previously registered callback. After calling this method, 6803 * applications will no longer receive soft AP events. 6804 * 6805 * @param callback Callback to unregister for soft AP events 6806 * 6807 * @hide 6808 */ 6809 @SystemApi 6810 @RequiresPermission(anyOf = { 6811 android.Manifest.permission.NETWORK_SETTINGS, 6812 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 6813 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 6814 }) unregisterSoftApCallback(@onNull SoftApCallback callback)6815 public void unregisterSoftApCallback(@NonNull SoftApCallback callback) { 6816 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 6817 Log.v(TAG, "unregisterSoftApCallback: callback=" + callback); 6818 6819 try { 6820 synchronized (sSoftApCallbackMap) { 6821 int callbackIdentifier = System.identityHashCode(callback); 6822 if (!sSoftApCallbackMap.contains(callbackIdentifier)) { 6823 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 6824 return; 6825 } 6826 mService.unregisterSoftApCallback(sSoftApCallbackMap.get(callbackIdentifier)); 6827 sSoftApCallbackMap.remove(callbackIdentifier); 6828 } 6829 } catch (RemoteException e) { 6830 throw e.rethrowFromSystemServer(); 6831 } 6832 } 6833 6834 /** 6835 * LocalOnlyHotspotReservation that contains the {@link SoftApConfiguration} for the active 6836 * LocalOnlyHotspot request. 6837 * <p> 6838 * Applications requesting LocalOnlyHotspot for sharing will receive an instance of the 6839 * LocalOnlyHotspotReservation in the 6840 * {@link LocalOnlyHotspotCallback#onStarted(LocalOnlyHotspotReservation)} call. This 6841 * reservation contains the relevant {@link SoftApConfiguration}. 6842 * When an application is done with the LocalOnlyHotspot, they should call {@link 6843 * LocalOnlyHotspotReservation#close()}. Once this happens, the application will not receive 6844 * any further callbacks. If the LocalOnlyHotspot is stopped due to a 6845 * user triggered mode change, applications will be notified via the {@link 6846 * LocalOnlyHotspotCallback#onStopped()} callback. 6847 */ 6848 public class LocalOnlyHotspotReservation implements AutoCloseable { 6849 6850 private final CloseGuard mCloseGuard = new CloseGuard(); 6851 private final SoftApConfiguration mSoftApConfig; 6852 private final WifiConfiguration mWifiConfig; 6853 private boolean mClosed = false; 6854 6855 /** @hide */ 6856 @VisibleForTesting LocalOnlyHotspotReservation(SoftApConfiguration config)6857 public LocalOnlyHotspotReservation(SoftApConfiguration config) { 6858 mSoftApConfig = config; 6859 mWifiConfig = config.toWifiConfiguration(); 6860 mCloseGuard.open("close"); 6861 } 6862 6863 /** 6864 * Returns the {@link WifiConfiguration} of the current Local Only Hotspot (LOHS). 6865 * May be null if hotspot enabled and security type is not 6866 * {@code WifiConfiguration.KeyMgmt.None} or {@code WifiConfiguration.KeyMgmt.WPA2_PSK}. 6867 * 6868 * @deprecated Use {@code WifiManager#getSoftApConfiguration()} to get the 6869 * LOHS configuration. 6870 */ 6871 @Deprecated 6872 @Nullable getWifiConfiguration()6873 public WifiConfiguration getWifiConfiguration() { 6874 return mWifiConfig; 6875 } 6876 6877 /** 6878 * Returns the {@link SoftApConfiguration} of the current Local Only Hotspot (LOHS). 6879 */ 6880 @NonNull getSoftApConfiguration()6881 public SoftApConfiguration getSoftApConfiguration() { 6882 return mSoftApConfig; 6883 } 6884 6885 @Override close()6886 public void close() { 6887 try { 6888 synchronized (mLock) { 6889 if (!mClosed) { 6890 mClosed = true; 6891 stopLocalOnlyHotspot(); 6892 mCloseGuard.close(); 6893 } 6894 } 6895 } catch (Exception e) { 6896 Log.e(TAG, "Failed to stop Local Only Hotspot."); 6897 } finally { 6898 Reference.reachabilityFence(this); 6899 } 6900 } 6901 6902 @Override finalize()6903 protected void finalize() throws Throwable { 6904 try { 6905 if (mCloseGuard != null) { 6906 mCloseGuard.warnIfOpen(); 6907 } 6908 close(); 6909 } finally { 6910 super.finalize(); 6911 } 6912 } 6913 } 6914 6915 /** 6916 * Callback class for applications to receive updates about the LocalOnlyHotspot status. 6917 */ 6918 public static class LocalOnlyHotspotCallback { 6919 /** @hide */ 6920 public static final int REQUEST_REGISTERED = 0; 6921 6922 public static final int ERROR_NO_CHANNEL = 1; 6923 public static final int ERROR_GENERIC = 2; 6924 public static final int ERROR_INCOMPATIBLE_MODE = 3; 6925 public static final int ERROR_TETHERING_DISALLOWED = 4; 6926 6927 /** LocalOnlyHotspot start succeeded. */ onStarted(LocalOnlyHotspotReservation reservation)6928 public void onStarted(LocalOnlyHotspotReservation reservation) {}; 6929 6930 /** 6931 * LocalOnlyHotspot stopped. 6932 * <p> 6933 * The LocalOnlyHotspot can be disabled at any time by the user. When this happens, 6934 * applications will be notified that it was stopped. This will not be invoked when an 6935 * application calls {@link LocalOnlyHotspotReservation#close()}. 6936 */ onStopped()6937 public void onStopped() {}; 6938 6939 /** 6940 * LocalOnlyHotspot failed to start. 6941 * <p> 6942 * Applications can attempt to call 6943 * {@link WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)} again at 6944 * a later time. 6945 * <p> 6946 * @param reason The reason for failure could be one of: {@link 6947 * #ERROR_TETHERING_DISALLOWED}, {@link #ERROR_INCOMPATIBLE_MODE}, 6948 * {@link #ERROR_NO_CHANNEL}, or {@link #ERROR_GENERIC}. 6949 */ onFailed(int reason)6950 public void onFailed(int reason) { }; 6951 } 6952 6953 /** 6954 * Callback proxy for LocalOnlyHotspotCallback objects. 6955 */ 6956 private static class LocalOnlyHotspotCallbackProxy extends ILocalOnlyHotspotCallback.Stub { 6957 private final WeakReference<WifiManager> mWifiManager; 6958 private final Executor mExecutor; 6959 private final LocalOnlyHotspotCallback mCallback; 6960 6961 /** 6962 * Constructs a {@link LocalOnlyHotspotCallbackProxy} using the specified executor. All 6963 * callbacks will run using the given executor. 6964 * 6965 * @param manager WifiManager 6966 * @param executor Executor for delivering callbacks. 6967 * @param callback LocalOnlyHotspotCallback to notify the calling application, or null. 6968 */ LocalOnlyHotspotCallbackProxy( @onNull WifiManager manager, @NonNull @CallbackExecutor Executor executor, @Nullable LocalOnlyHotspotCallback callback)6969 LocalOnlyHotspotCallbackProxy( 6970 @NonNull WifiManager manager, 6971 @NonNull @CallbackExecutor Executor executor, 6972 @Nullable LocalOnlyHotspotCallback callback) { 6973 mWifiManager = new WeakReference<>(manager); 6974 mExecutor = executor; 6975 mCallback = callback; 6976 } 6977 6978 @Override onHotspotStarted(SoftApConfiguration config)6979 public void onHotspotStarted(SoftApConfiguration config) { 6980 WifiManager manager = mWifiManager.get(); 6981 if (manager == null) return; 6982 6983 if (config == null) { 6984 Log.e(TAG, "LocalOnlyHotspotCallbackProxy: config cannot be null."); 6985 onHotspotFailed(LocalOnlyHotspotCallback.ERROR_GENERIC); 6986 return; 6987 } 6988 final LocalOnlyHotspotReservation reservation = 6989 manager.new LocalOnlyHotspotReservation(config); 6990 if (mCallback == null) return; 6991 mExecutor.execute(() -> mCallback.onStarted(reservation)); 6992 } 6993 6994 @Override onHotspotStopped()6995 public void onHotspotStopped() { 6996 WifiManager manager = mWifiManager.get(); 6997 if (manager == null) return; 6998 6999 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: hotspot stopped"); 7000 if (mCallback == null) return; 7001 mExecutor.execute(() -> mCallback.onStopped()); 7002 } 7003 7004 @Override onHotspotFailed(int reason)7005 public void onHotspotFailed(int reason) { 7006 WifiManager manager = mWifiManager.get(); 7007 if (manager == null) return; 7008 7009 Log.w(TAG, "LocalOnlyHotspotCallbackProxy: failed to start. reason: " 7010 + reason); 7011 if (mCallback == null) return; 7012 mExecutor.execute(() -> mCallback.onFailed(reason)); 7013 } 7014 } 7015 7016 /** 7017 * LocalOnlyHotspotSubscription that is an AutoCloseable object for tracking applications 7018 * watching for LocalOnlyHotspot changes. 7019 * 7020 * @hide 7021 */ 7022 public class LocalOnlyHotspotSubscription implements AutoCloseable { 7023 private final CloseGuard mCloseGuard = new CloseGuard(); 7024 7025 /** @hide */ 7026 @VisibleForTesting LocalOnlyHotspotSubscription()7027 public LocalOnlyHotspotSubscription() { 7028 mCloseGuard.open("close"); 7029 } 7030 7031 @Override close()7032 public void close() { 7033 try { 7034 unregisterLocalOnlyHotspotObserver(); 7035 mCloseGuard.close(); 7036 } catch (Exception e) { 7037 Log.e(TAG, "Failed to unregister LocalOnlyHotspotObserver."); 7038 } finally { 7039 Reference.reachabilityFence(this); 7040 } 7041 } 7042 7043 @Override finalize()7044 protected void finalize() throws Throwable { 7045 try { 7046 if (mCloseGuard != null) { 7047 mCloseGuard.warnIfOpen(); 7048 } 7049 close(); 7050 } finally { 7051 super.finalize(); 7052 } 7053 } 7054 } 7055 7056 /** 7057 * Class to notify calling applications that watch for changes in LocalOnlyHotspot of updates. 7058 * 7059 * @hide 7060 */ 7061 public static class LocalOnlyHotspotObserver { 7062 /** 7063 * Confirm registration for LocalOnlyHotspotChanges by returning a 7064 * LocalOnlyHotspotSubscription. 7065 */ onRegistered(LocalOnlyHotspotSubscription subscription)7066 public void onRegistered(LocalOnlyHotspotSubscription subscription) {}; 7067 7068 /** 7069 * LocalOnlyHotspot started with the supplied config. 7070 */ onStarted(SoftApConfiguration config)7071 public void onStarted(SoftApConfiguration config) {}; 7072 7073 /** 7074 * LocalOnlyHotspot stopped. 7075 */ onStopped()7076 public void onStopped() {}; 7077 } 7078 7079 /** 7080 * Callback proxy for LocalOnlyHotspotObserver objects. 7081 */ 7082 private static class LocalOnlyHotspotObserverProxy extends ILocalOnlyHotspotCallback.Stub { 7083 private final WeakReference<WifiManager> mWifiManager; 7084 private final Executor mExecutor; 7085 private final LocalOnlyHotspotObserver mObserver; 7086 7087 /** 7088 * Constructs a {@link LocalOnlyHotspotObserverProxy} using the specified looper. 7089 * All callbacks will be delivered on the thread of the specified looper. 7090 * 7091 * @param manager WifiManager 7092 * @param executor Executor for delivering callbacks 7093 * @param observer LocalOnlyHotspotObserver to notify the calling application. 7094 */ LocalOnlyHotspotObserverProxy(WifiManager manager, Executor executor, final LocalOnlyHotspotObserver observer)7095 LocalOnlyHotspotObserverProxy(WifiManager manager, Executor executor, 7096 final LocalOnlyHotspotObserver observer) { 7097 mWifiManager = new WeakReference<>(manager); 7098 mExecutor = executor; 7099 mObserver = observer; 7100 } 7101 registered()7102 public void registered() throws RemoteException { 7103 WifiManager manager = mWifiManager.get(); 7104 if (manager == null) return; 7105 7106 mExecutor.execute(() -> 7107 mObserver.onRegistered(manager.new LocalOnlyHotspotSubscription())); 7108 } 7109 7110 @Override onHotspotStarted(SoftApConfiguration config)7111 public void onHotspotStarted(SoftApConfiguration config) { 7112 WifiManager manager = mWifiManager.get(); 7113 if (manager == null) return; 7114 7115 if (config == null) { 7116 Log.e(TAG, "LocalOnlyHotspotObserverProxy: config cannot be null."); 7117 return; 7118 } 7119 mExecutor.execute(() -> mObserver.onStarted(config)); 7120 } 7121 7122 @Override onHotspotStopped()7123 public void onHotspotStopped() { 7124 WifiManager manager = mWifiManager.get(); 7125 if (manager == null) return; 7126 7127 mExecutor.execute(() -> mObserver.onStopped()); 7128 } 7129 7130 @Override onHotspotFailed(int reason)7131 public void onHotspotFailed(int reason) { 7132 // do nothing 7133 } 7134 } 7135 7136 /** 7137 * Callback proxy for ActionListener objects. 7138 */ 7139 private class ActionListenerProxy extends IActionListener.Stub { 7140 private final String mActionTag; 7141 private final Handler mHandler; 7142 private final ActionListener mCallback; 7143 ActionListenerProxy(String actionTag, Looper looper, ActionListener callback)7144 ActionListenerProxy(String actionTag, Looper looper, ActionListener callback) { 7145 mActionTag = actionTag; 7146 mHandler = new Handler(looper); 7147 mCallback = callback; 7148 } 7149 7150 @Override onSuccess()7151 public void onSuccess() { 7152 if (mVerboseLoggingEnabled) { 7153 Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onSuccess"); 7154 } 7155 mHandler.post(() -> { 7156 mCallback.onSuccess(); 7157 }); 7158 } 7159 7160 @Override onFailure(@ctionListenerFailureReason int reason)7161 public void onFailure(@ActionListenerFailureReason int reason) { 7162 if (mVerboseLoggingEnabled) { 7163 Log.v(TAG, "ActionListenerProxy:" + mActionTag + ": onFailure=" + reason); 7164 } 7165 mHandler.post(() -> { 7166 mCallback.onFailure(reason); 7167 }); 7168 } 7169 } 7170 connectInternal(@ullable WifiConfiguration config, int networkId, @Nullable ActionListener listener)7171 private void connectInternal(@Nullable WifiConfiguration config, int networkId, 7172 @Nullable ActionListener listener) { 7173 ActionListenerProxy listenerProxy = null; 7174 if (listener != null) { 7175 listenerProxy = new ActionListenerProxy("connect", mLooper, listener); 7176 } 7177 try { 7178 mService.connect(config, networkId, listenerProxy, mContext.getOpPackageName()); 7179 } catch (RemoteException e) { 7180 if (listenerProxy != null) { 7181 listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7182 } 7183 } catch (SecurityException e) { 7184 if (listenerProxy != null) { 7185 listenerProxy.onFailure(ActionListener.FAILURE_NOT_AUTHORIZED); 7186 } 7187 } 7188 } 7189 7190 /** 7191 * Connect to a network with the given configuration. The network also 7192 * gets added to the list of configured networks for the foreground user. 7193 * 7194 * For a new network, this function is used instead of a 7195 * sequence of addNetwork(), enableNetwork(), and reconnect() 7196 * 7197 * @param config the set of variables that describe the configuration, 7198 * contained in a {@link WifiConfiguration} object. 7199 * @param listener for callbacks on success or failure. Can be null. 7200 * @throws IllegalStateException if the WifiManager instance needs to be 7201 * initialized again 7202 * 7203 * @hide 7204 */ 7205 @SystemApi 7206 @RequiresPermission(anyOf = { 7207 android.Manifest.permission.NETWORK_SETTINGS, 7208 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7209 android.Manifest.permission.NETWORK_STACK 7210 }) connect(@onNull WifiConfiguration config, @Nullable ActionListener listener)7211 public void connect(@NonNull WifiConfiguration config, @Nullable ActionListener listener) { 7212 if (config == null) throw new IllegalArgumentException("config cannot be null"); 7213 connectInternal(config, WifiConfiguration.INVALID_NETWORK_ID, listener); 7214 } 7215 7216 /** 7217 * Connect to a network with the given networkId. 7218 * 7219 * This function is used instead of a enableNetwork() and reconnect() 7220 * 7221 * <li> This API will cause reconnect if the credentials of the current active 7222 * connection has been changed.</li> 7223 * <li> This API will cause reconnect if the current active connection is marked metered.</li> 7224 * 7225 * @param networkId the ID of the network as returned by {@link #addNetwork} or {@link 7226 * getConfiguredNetworks}. 7227 * @param listener for callbacks on success or failure. Can be null. 7228 * @throws IllegalStateException if the WifiManager instance needs to be 7229 * initialized again 7230 * @hide 7231 */ 7232 @SystemApi 7233 @RequiresPermission(anyOf = { 7234 android.Manifest.permission.NETWORK_SETTINGS, 7235 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7236 android.Manifest.permission.NETWORK_STACK 7237 }) connect(int networkId, @Nullable ActionListener listener)7238 public void connect(int networkId, @Nullable ActionListener listener) { 7239 if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 7240 connectInternal(null, networkId, listener); 7241 } 7242 7243 /** 7244 * Temporarily disable autojoin for all currently visible and provisioned (saved, suggested) 7245 * wifi networks except merged carrier networks from the provided subscription ID. 7246 * 7247 * Disabled networks will get automatically re-enabled when they are out of range for a period 7248 * of time, or after the maximum disable duration specified in the framework. 7249 * 7250 * Calling {@link #stopRestrictingAutoJoinToSubscriptionId()} will immediately re-enable 7251 * autojoin on all disabled networks. 7252 * 7253 * @param subscriptionId the subscription ID of the carrier whose merged wifi networks won't be 7254 * disabled {@link android.telephony.SubscriptionInfo#getSubscriptionId()} 7255 * @hide 7256 */ 7257 @SystemApi 7258 @RequiresPermission(anyOf = { 7259 android.Manifest.permission.NETWORK_SETTINGS, 7260 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 7261 @RequiresApi(Build.VERSION_CODES.S) startRestrictingAutoJoinToSubscriptionId(int subscriptionId)7262 public void startRestrictingAutoJoinToSubscriptionId(int subscriptionId) { 7263 try { 7264 mService.startRestrictingAutoJoinToSubscriptionId(subscriptionId); 7265 } catch (RemoteException e) { 7266 throw e.rethrowFromSystemServer(); 7267 } 7268 } 7269 7270 /** 7271 * Re-enable autojoin for all non carrier merged wifi networks temporarily disconnected by 7272 * {@link #startRestrictingAutoJoinToSubscriptionId(int)}. 7273 * @hide 7274 */ 7275 @SystemApi 7276 @RequiresPermission(anyOf = { 7277 android.Manifest.permission.NETWORK_SETTINGS, 7278 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 7279 @RequiresApi(Build.VERSION_CODES.S) stopRestrictingAutoJoinToSubscriptionId()7280 public void stopRestrictingAutoJoinToSubscriptionId() { 7281 try { 7282 mService.stopRestrictingAutoJoinToSubscriptionId(); 7283 } catch (RemoteException e) { 7284 throw e.rethrowFromSystemServer(); 7285 } 7286 } 7287 7288 /** 7289 * Save the given network to the list of configured networks for the 7290 * foreground user. If the network already exists, the configuration 7291 * is updated. Any new network is enabled by default. 7292 * 7293 * For a new network, this function is used instead of a 7294 * sequence of addNetwork() and enableNetwork(). 7295 * 7296 * For an existing network, it accomplishes the task of updateNetwork() 7297 * 7298 * <li> This API will cause reconnect if the credentials of the current active 7299 * connection has been changed.</li> 7300 * <li> This API will cause disconnect if the current active connection is marked metered.</li> 7301 * 7302 * @param config the set of variables that describe the configuration, 7303 * contained in a {@link WifiConfiguration} object. 7304 * @param listener for callbacks on success or failure. Can be null. 7305 * @throws IllegalStateException if the WifiManager instance needs to be 7306 * initialized again 7307 * @hide 7308 */ 7309 @SystemApi 7310 @RequiresPermission(anyOf = { 7311 android.Manifest.permission.NETWORK_SETTINGS, 7312 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7313 android.Manifest.permission.NETWORK_STACK 7314 }) save(@onNull WifiConfiguration config, @Nullable ActionListener listener)7315 public void save(@NonNull WifiConfiguration config, @Nullable ActionListener listener) { 7316 if (config == null) throw new IllegalArgumentException("config cannot be null"); 7317 ActionListenerProxy listenerProxy = null; 7318 if (listener != null) { 7319 listenerProxy = new ActionListenerProxy("save", mLooper, listener); 7320 } 7321 try { 7322 mService.save(config, listenerProxy, mContext.getOpPackageName()); 7323 } catch (RemoteException e) { 7324 if (listenerProxy != null) { 7325 listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7326 } 7327 } catch (SecurityException e) { 7328 if (listenerProxy != null) { 7329 listenerProxy.onFailure(ActionListener.FAILURE_NOT_AUTHORIZED); 7330 } 7331 } 7332 } 7333 7334 /** 7335 * Delete the network from the list of configured networks for the 7336 * foreground user. 7337 * 7338 * This function is used instead of a sequence of removeNetwork() 7339 * 7340 * @param config the set of variables that describe the configuration, 7341 * contained in a {@link WifiConfiguration} object. 7342 * @param listener for callbacks on success or failure. Can be null. 7343 * @throws IllegalStateException if the WifiManager instance needs to be 7344 * initialized again 7345 * @hide 7346 */ 7347 @SystemApi 7348 @RequiresPermission(anyOf = { 7349 android.Manifest.permission.NETWORK_SETTINGS, 7350 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7351 android.Manifest.permission.NETWORK_STACK 7352 }) forget(int netId, @Nullable ActionListener listener)7353 public void forget(int netId, @Nullable ActionListener listener) { 7354 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 7355 ActionListenerProxy listenerProxy = null; 7356 if (listener != null) { 7357 listenerProxy = new ActionListenerProxy("forget", mLooper, listener); 7358 } 7359 try { 7360 mService.forget(netId, listenerProxy); 7361 } catch (RemoteException e) { 7362 if (listenerProxy != null) { 7363 listenerProxy.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7364 } 7365 } catch (SecurityException e) { 7366 if (listenerProxy != null) { 7367 listenerProxy.onFailure(ActionListener.FAILURE_NOT_AUTHORIZED); 7368 } 7369 } 7370 } 7371 7372 /** 7373 * Disable network 7374 * 7375 * @param netId is the network Id 7376 * @param listener for callbacks on success or failure. Can be null. 7377 * @throws IllegalStateException if the WifiManager instance needs to be 7378 * initialized again 7379 * @deprecated This API is deprecated. Use {@link #disableNetwork(int)} instead. 7380 * @hide 7381 */ 7382 @SystemApi 7383 @RequiresPermission(anyOf = { 7384 android.Manifest.permission.NETWORK_SETTINGS, 7385 android.Manifest.permission.NETWORK_SETUP_WIZARD, 7386 android.Manifest.permission.NETWORK_STACK 7387 }) 7388 @Deprecated disable(int netId, @Nullable ActionListener listener)7389 public void disable(int netId, @Nullable ActionListener listener) { 7390 if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); 7391 // Simple wrapper which forwards the call to disableNetwork. This is a temporary 7392 // implementation until we can remove this API completely. 7393 boolean status = disableNetwork(netId); 7394 if (listener != null) { 7395 if (status) { 7396 listener.onSuccess(); 7397 } else { 7398 listener.onFailure(ActionListener.FAILURE_INTERNAL_ERROR); 7399 } 7400 } 7401 } 7402 7403 /** 7404 * Control whether the device will automatically search for and connect to Wi-Fi networks - 7405 * auto-join Wi-Fi networks. Disabling this option will not impact manual connections - i.e. 7406 * the user will still be able to manually select and connect to a Wi-Fi network. Disabling 7407 * this option significantly impacts the device connectivity and is a restricted operation 7408 * (see below for permissions). Note that disabling this operation will also disable 7409 * connectivity initiated scanning operations. 7410 * <p> 7411 * Disabling the auto-join configuration is a temporary operation (with the exception of a 7412 * DO/PO caller): it will be reset (to enabled) when the device reboots or the user toggles 7413 * Wi-Fi off/on. When the caller is a DO/PO then toggling Wi-Fi will not reset the 7414 * configuration. Additionally, if a DO/PO disables auto-join then it cannot be (re)enabled by 7415 * a non-DO/PO caller. 7416 * 7417 * @param allowAutojoin true to allow auto-join, false to disallow auto-join 7418 * 7419 * Available for DO/PO apps. 7420 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 7421 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 7422 */ allowAutojoinGlobal(boolean allowAutojoin)7423 public void allowAutojoinGlobal(boolean allowAutojoin) { 7424 try { 7425 Bundle extras = new Bundle(); 7426 if (SdkLevel.isAtLeastS()) { 7427 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 7428 mContext.getAttributionSource()); 7429 } 7430 mService.allowAutojoinGlobal(allowAutojoin, mContext.getOpPackageName(), extras); 7431 } catch (RemoteException e) { 7432 throw e.rethrowFromSystemServer(); 7433 } 7434 } 7435 7436 /** 7437 * Query whether or not auto-join global is enabled/disabled 7438 * @see #allowAutojoinGlobal(boolean) 7439 * 7440 * Available for DO/PO apps. 7441 * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or 7442 * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. 7443 * 7444 * @param executor The executor on which callback will be invoked. 7445 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 7446 * whether auto-join global is enabled/disabled. 7447 * 7448 * @throws SecurityException if the caller does not have permission. 7449 * @throws NullPointerException if the caller provided invalid inputs. 7450 */ queryAutojoinGlobal(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)7451 public void queryAutojoinGlobal(@NonNull @CallbackExecutor Executor executor, 7452 @NonNull Consumer<Boolean> resultsCallback) { 7453 Objects.requireNonNull(executor, "executor cannot be null"); 7454 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 7455 try { 7456 mService.queryAutojoinGlobal( 7457 new IBooleanListener.Stub() { 7458 @Override 7459 public void onResult(boolean value) { 7460 Binder.clearCallingIdentity(); 7461 executor.execute(() -> { 7462 resultsCallback.accept(value); 7463 }); 7464 } 7465 }); 7466 } catch (RemoteException e) { 7467 throw e.rethrowFromSystemServer(); 7468 } 7469 } 7470 7471 /** 7472 * Sets the user choice for allowing auto-join to a network. 7473 * The updated choice will be made available through the updated config supplied by the 7474 * CONFIGURED_NETWORKS_CHANGED broadcast. 7475 * 7476 * @param netId the id of the network to allow/disallow auto-join for. 7477 * @param allowAutojoin true to allow auto-join, false to disallow auto-join 7478 * @hide 7479 */ 7480 @SystemApi 7481 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) allowAutojoin(int netId, boolean allowAutojoin)7482 public void allowAutojoin(int netId, boolean allowAutojoin) { 7483 try { 7484 mService.allowAutojoin(netId, allowAutojoin); 7485 } catch (RemoteException e) { 7486 throw e.rethrowFromSystemServer(); 7487 } 7488 } 7489 7490 /** 7491 * Configure auto-join settings for a Passpoint profile. 7492 * 7493 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 7494 * @param allowAutojoin true to enable auto-join, false to disable auto-join. 7495 * @hide 7496 */ 7497 @SystemApi 7498 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) allowAutojoinPasspoint(@onNull String fqdn, boolean allowAutojoin)7499 public void allowAutojoinPasspoint(@NonNull String fqdn, boolean allowAutojoin) { 7500 try { 7501 mService.allowAutojoinPasspoint(fqdn, allowAutojoin); 7502 } catch (RemoteException e) { 7503 throw e.rethrowFromSystemServer(); 7504 } 7505 } 7506 7507 /** 7508 * Configure MAC randomization setting for a Passpoint profile. 7509 * MAC randomization is enabled by default. 7510 * 7511 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 7512 * @param enable true to enable MAC randomization, false to disable MAC randomization. 7513 * @hide 7514 */ 7515 @SystemApi 7516 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setMacRandomizationSettingPasspointEnabled(@onNull String fqdn, boolean enable)7517 public void setMacRandomizationSettingPasspointEnabled(@NonNull String fqdn, boolean enable) { 7518 try { 7519 mService.setMacRandomizationSettingPasspointEnabled(fqdn, enable); 7520 } catch (RemoteException e) { 7521 throw e.rethrowFromSystemServer(); 7522 } 7523 } 7524 7525 /** 7526 * Sets the user's choice of metered override for a Passpoint profile. 7527 * 7528 * @param fqdn the FQDN (fully qualified domain name) of the passpoint profile. 7529 * @param meteredOverride One of three values: {@link WifiConfiguration#METERED_OVERRIDE_NONE}, 7530 * {@link WifiConfiguration#METERED_OVERRIDE_METERED}, 7531 * {@link WifiConfiguration#METERED_OVERRIDE_NOT_METERED} 7532 * @hide 7533 */ 7534 @SystemApi 7535 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setPasspointMeteredOverride(@onNull String fqdn, @WifiConfiguration.MeteredOverride int meteredOverride)7536 public void setPasspointMeteredOverride(@NonNull String fqdn, 7537 @WifiConfiguration.MeteredOverride int meteredOverride) { 7538 try { 7539 mService.setPasspointMeteredOverride(fqdn, meteredOverride); 7540 } catch (RemoteException e) { 7541 throw e.rethrowFromSystemServer(); 7542 } 7543 } 7544 7545 /** 7546 * Temporarily disable a network. Should always trigger with user disconnect network. 7547 * 7548 * @param network Input can be SSID or FQDN. And caller must ensure that the SSID passed thru 7549 * this API matched the WifiConfiguration.SSID rules, and thus be surrounded by 7550 * quotes. 7551 * @hide 7552 */ 7553 @SystemApi 7554 @RequiresPermission(anyOf = { 7555 android.Manifest.permission.NETWORK_SETTINGS, 7556 android.Manifest.permission.NETWORK_STACK 7557 }) disableEphemeralNetwork(@onNull String network)7558 public void disableEphemeralNetwork(@NonNull String network) { 7559 if (TextUtils.isEmpty(network)) { 7560 throw new IllegalArgumentException("SSID cannot be null or empty!"); 7561 } 7562 try { 7563 mService.disableEphemeralNetwork(network, mContext.getOpPackageName()); 7564 } catch (RemoteException e) { 7565 throw e.rethrowFromSystemServer(); 7566 } 7567 } 7568 7569 /** 7570 * WPS suport has been deprecated from Client mode and this method will immediately trigger 7571 * {@link WpsCallback#onFailed(int)} with a generic error. 7572 * 7573 * @param config WPS configuration (does not support {@link WpsInfo#LABEL}) 7574 * @param listener for callbacks on success or failure. Can be null. 7575 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 7576 * @deprecated This API is deprecated 7577 */ startWps(WpsInfo config, WpsCallback listener)7578 public void startWps(WpsInfo config, WpsCallback listener) { 7579 if (listener != null ) { 7580 listener.onFailed(ActionListener.FAILURE_INTERNAL_ERROR); 7581 } 7582 } 7583 7584 /** 7585 * WPS support has been deprecated from Client mode and this method will immediately trigger 7586 * {@link WpsCallback#onFailed(int)} with a generic error. 7587 * 7588 * @param listener for callbacks on success or failure. Can be null. 7589 * @throws IllegalStateException if the WifiManager instance needs to be initialized again 7590 * @deprecated This API is deprecated 7591 */ cancelWps(WpsCallback listener)7592 public void cancelWps(WpsCallback listener) { 7593 if (listener != null) { 7594 listener.onFailed(ActionListener.FAILURE_INTERNAL_ERROR); 7595 } 7596 } 7597 7598 /** 7599 * Allows an application to keep the Wi-Fi radio awake. 7600 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. 7601 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple 7602 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no 7603 * WifiLocks are held in any application. 7604 * <p> 7605 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or 7606 * could function over a mobile network, if available. A program that needs to download large 7607 * files should hold a WifiLock to ensure that the download will complete, but a program whose 7608 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely 7609 * affecting battery life. 7610 * <p> 7611 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane 7612 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device 7613 * is idle. 7614 * <p> 7615 * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK} 7616 * permission in an {@code <uses-permission>} element of the application's manifest. 7617 */ 7618 public class WifiLock { 7619 private String mTag; 7620 private final IBinder mBinder; 7621 private int mRefCount; 7622 int mLockType; 7623 private boolean mRefCounted; 7624 private boolean mHeld; 7625 private WorkSource mWorkSource; 7626 WifiLock(int lockType, String tag)7627 private WifiLock(int lockType, String tag) { 7628 mTag = tag; 7629 mLockType = lockType; 7630 mBinder = new Binder(); 7631 mRefCount = 0; 7632 mRefCounted = true; 7633 mHeld = false; 7634 } 7635 7636 /** 7637 * Locks the Wi-Fi radio on until {@link #release} is called. 7638 * 7639 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the 7640 * reference count, and the radio will remain locked as long as the reference count is 7641 * above zero. 7642 * 7643 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock 7644 * the radio, but subsequent calls will be ignored. Only one call to {@link #release} 7645 * will be required, regardless of the number of times that {@code acquire} is called. 7646 */ acquire()7647 public void acquire() { 7648 synchronized (mBinder) { 7649 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 7650 try { 7651 mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource); 7652 synchronized (WifiManager.this) { 7653 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 7654 mService.releaseWifiLock(mBinder); 7655 throw new UnsupportedOperationException( 7656 "Exceeded maximum number of wifi locks"); 7657 } 7658 mActiveLockCount++; 7659 } 7660 } catch (RemoteException e) { 7661 throw e.rethrowFromSystemServer(); 7662 } 7663 mHeld = true; 7664 } 7665 } 7666 } 7667 7668 /** 7669 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle. 7670 * 7671 * If this WifiLock is reference-counted, each call to {@code release} will decrement the 7672 * reference count, and the radio will be unlocked only when the reference count reaches 7673 * zero. If the reference count goes below zero (that is, if {@code release} is called 7674 * a greater number of times than {@link #acquire}), an exception is thrown. 7675 * 7676 * If this WifiLock is not reference-counted, the first call to {@code release} (after 7677 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent 7678 * calls will be ignored. 7679 */ release()7680 public void release() { 7681 synchronized (mBinder) { 7682 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 7683 try { 7684 mService.releaseWifiLock(mBinder); 7685 synchronized (WifiManager.this) { 7686 mActiveLockCount--; 7687 } 7688 } catch (RemoteException e) { 7689 throw e.rethrowFromSystemServer(); 7690 } 7691 mHeld = false; 7692 } 7693 if (mRefCount < 0) { 7694 throw new RuntimeException("WifiLock under-locked " + mTag); 7695 } 7696 } 7697 } 7698 7699 /** 7700 * Controls whether this is a reference-counted or non-reference-counted WifiLock. 7701 * 7702 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and 7703 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire} 7704 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks 7705 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the 7706 * radio whenever {@link #release} is called and it is locked. 7707 * 7708 * @param refCounted true if this WifiLock should keep a reference count 7709 */ setReferenceCounted(boolean refCounted)7710 public void setReferenceCounted(boolean refCounted) { 7711 mRefCounted = refCounted; 7712 } 7713 7714 /** 7715 * Checks whether this WifiLock is currently held. 7716 * 7717 * @return true if this WifiLock is held, false otherwise 7718 */ isHeld()7719 public boolean isHeld() { 7720 synchronized (mBinder) { 7721 return mHeld; 7722 } 7723 } 7724 setWorkSource(WorkSource ws)7725 public void setWorkSource(WorkSource ws) { 7726 synchronized (mBinder) { 7727 if (ws != null && ws.isEmpty()) { 7728 ws = null; 7729 } 7730 boolean changed = true; 7731 if (ws == null) { 7732 mWorkSource = null; 7733 } else { 7734 ws = ws.withoutNames(); 7735 if (mWorkSource == null) { 7736 changed = mWorkSource != null; 7737 mWorkSource = new WorkSource(ws); 7738 } else { 7739 changed = !mWorkSource.equals(ws); 7740 if (changed) { 7741 mWorkSource.set(ws); 7742 } 7743 } 7744 } 7745 if (changed && mHeld) { 7746 try { 7747 mService.updateWifiLockWorkSource(mBinder, mWorkSource); 7748 } catch (RemoteException e) { 7749 throw e.rethrowFromSystemServer(); 7750 } 7751 } 7752 } 7753 } 7754 toString()7755 public String toString() { 7756 String s1, s2, s3; 7757 synchronized (mBinder) { 7758 s1 = Integer.toHexString(System.identityHashCode(this)); 7759 s2 = mHeld ? "held; " : ""; 7760 if (mRefCounted) { 7761 s3 = "refcounted: refcount = " + mRefCount; 7762 } else { 7763 s3 = "not refcounted"; 7764 } 7765 return "WifiLock{ " + s1 + "; " + s2 + s3 + " }"; 7766 } 7767 } 7768 7769 @Override finalize()7770 protected void finalize() throws Throwable { 7771 super.finalize(); 7772 synchronized (mBinder) { 7773 if (mHeld) { 7774 try { 7775 mService.releaseWifiLock(mBinder); 7776 synchronized (WifiManager.this) { 7777 mActiveLockCount--; 7778 } 7779 } catch (RemoteException e) { 7780 throw e.rethrowFromSystemServer(); 7781 } 7782 } 7783 } 7784 } 7785 } 7786 7787 /** 7788 * Creates a new WifiLock. 7789 * 7790 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL_HIGH_PERF} 7791 * and {@link #WIFI_MODE_FULL_LOW_LATENCY} for descriptions of the types of Wi-Fi locks. 7792 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 7793 * never shown to the user under normal conditions, but should be descriptive 7794 * enough to identify your application and the specific WifiLock within it, if it 7795 * holds multiple WifiLocks. 7796 * 7797 * @return a new, unacquired WifiLock with the given tag. 7798 * 7799 * @see WifiLock 7800 */ createWifiLock(int lockType, String tag)7801 public WifiLock createWifiLock(int lockType, String tag) { 7802 return new WifiLock(lockType, tag); 7803 } 7804 7805 /** 7806 * Interface for low latency lock listener. Should be extended by application and 7807 * set when calling {@link WifiManager#addWifiLowLatencyLockListener(Executor, 7808 * WifiLowLatencyLockListener)}. 7809 * 7810 * @hide 7811 */ 7812 public interface WifiLowLatencyLockListener { 7813 /** 7814 * Provides low latency mode is activated or not. Triggered when Wi-Fi chip enters into low 7815 * latency mode. 7816 * 7817 * Note: Always called with current state when a new listener gets registered. 7818 */ onActivatedStateChanged(boolean activated)7819 void onActivatedStateChanged(boolean activated); 7820 7821 /** 7822 * Provides UIDs (lock owners) of the applications which currently acquired low latency 7823 * lock. Triggered when an application acquires or releases a lock. 7824 * 7825 * Note: Always called with UIDs of the current acquired locks when a new listener gets 7826 * registered. 7827 * 7828 * @param ownerUids An array of UIDs. 7829 */ onOwnershipChanged(@onNull int[] ownerUids)7830 default void onOwnershipChanged(@NonNull int[] ownerUids) {} 7831 7832 /** 7833 * Provides UIDs of the applications which acquired the low latency lock and is currently 7834 * active. See {@link WifiManager#WIFI_MODE_FULL_LOW_LATENCY} for the conditions to be 7835 * met for low latency lock to be active. Triggered when application acquiring the lock 7836 * satisfies or does not satisfy low latency conditions when the low latency mode is 7837 * activated. Also gets triggered when the lock becomes active, immediately after the 7838 * {@link WifiLowLatencyLockListener#onActivatedStateChanged(boolean)} callback is 7839 * triggered. 7840 * 7841 * Note: Always called with UIDs of the current active locks when a new listener gets 7842 * registered if the Wi-Fi chip is in low latency mode. 7843 * 7844 * @param activeUids An array of UIDs. 7845 */ onActiveUsersChanged(@onNull int[] activeUids)7846 default void onActiveUsersChanged(@NonNull int[] activeUids) {} 7847 } 7848 7849 /** 7850 * Helper class to support wifi low latency lock listener. 7851 */ 7852 private static class OnWifiLowLatencyLockProxy extends IWifiLowLatencyLockListener.Stub { 7853 @NonNull 7854 private Executor mExecutor; 7855 @NonNull 7856 private WifiLowLatencyLockListener mListener; 7857 OnWifiLowLatencyLockProxy(@onNull Executor executor, @NonNull WifiLowLatencyLockListener listener)7858 OnWifiLowLatencyLockProxy(@NonNull Executor executor, 7859 @NonNull WifiLowLatencyLockListener listener) { 7860 Objects.requireNonNull(executor); 7861 Objects.requireNonNull(listener); 7862 mExecutor = executor; 7863 mListener = listener; 7864 } 7865 7866 @Override onActivatedStateChanged(boolean activated)7867 public void onActivatedStateChanged(boolean activated) { 7868 Binder.clearCallingIdentity(); 7869 mExecutor.execute(() -> mListener.onActivatedStateChanged(activated)); 7870 7871 } 7872 7873 @Override onOwnershipChanged(@onNull int[] ownerUids)7874 public void onOwnershipChanged(@NonNull int[] ownerUids) { 7875 Binder.clearCallingIdentity(); 7876 mExecutor.execute(() -> mListener.onOwnershipChanged(ownerUids)); 7877 7878 } 7879 7880 @Override onActiveUsersChanged(@onNull int[] activeUids)7881 public void onActiveUsersChanged(@NonNull int[] activeUids) { 7882 Binder.clearCallingIdentity(); 7883 mExecutor.execute(() -> mListener.onActiveUsersChanged(activeUids)); 7884 } 7885 } 7886 7887 /** 7888 * Add a listener for monitoring the low latency lock. The caller can unregister a previously 7889 * registered listener using {@link WifiManager#removeWifiLowLatencyLockListener( 7890 * WifiLowLatencyLockListener)}. 7891 * 7892 * Applications should have the {@link android.Manifest.permission#NETWORK_SETTINGS} and 7893 * {@link android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. Callers 7894 * without the permission will trigger a {@link java.lang.SecurityException}. 7895 * 7896 * @param executor The Executor on which to execute the callbacks. 7897 * @param listener The listener for the latency mode change. 7898 * @throws IllegalArgumentException if incorrect input arguments are provided. 7899 * @throws SecurityException if the caller is not allowed to call this API 7900 * @hide 7901 */ 7902 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 7903 @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS, 7904 MANAGE_WIFI_NETWORK_SELECTION}) addWifiLowLatencyLockListener(@onNull @allbackExecutor Executor executor, @NonNull WifiLowLatencyLockListener listener)7905 public void addWifiLowLatencyLockListener(@NonNull @CallbackExecutor Executor executor, 7906 @NonNull WifiLowLatencyLockListener listener) { 7907 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 7908 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 7909 if (mVerboseLoggingEnabled) { 7910 Log.d(TAG, "addWifiLowLatencyLockListener: listener=" + listener + ", executor=" 7911 + executor); 7912 } 7913 final int listenerIdentifier = System.identityHashCode(listener); 7914 try { 7915 synchronized (sWifiLowLatencyLockListenerMap) { 7916 IWifiLowLatencyLockListener.Stub listenerProxy = new OnWifiLowLatencyLockProxy( 7917 executor, 7918 listener); 7919 sWifiLowLatencyLockListenerMap.put(listenerIdentifier, listenerProxy); 7920 mService.addWifiLowLatencyLockListener(listenerProxy); 7921 } 7922 } catch (RemoteException e) { 7923 sWifiLowLatencyLockListenerMap.remove(listenerIdentifier); 7924 throw e.rethrowFromSystemServer(); 7925 } 7926 } 7927 7928 /** 7929 * Removes a listener added using {@link WifiManager#addWifiLowLatencyLockListener(Executor, 7930 * WifiLowLatencyLockListener)}. After calling this method, applications will no longer 7931 * receive low latency mode notifications. 7932 * 7933 * @param listener the listener to be removed. 7934 * @throws IllegalArgumentException if incorrect input arguments are provided. 7935 * @hide 7936 */ removeWifiLowLatencyLockListener(@onNull WifiLowLatencyLockListener listener)7937 public void removeWifiLowLatencyLockListener(@NonNull WifiLowLatencyLockListener listener) { 7938 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 7939 if (mVerboseLoggingEnabled) { 7940 Log.d(TAG, "removeWifiLowLatencyLockListener: listener=" + listener); 7941 } 7942 final int listenerIdentifier = System.identityHashCode(listener); 7943 synchronized (sWifiLowLatencyLockListenerMap) { 7944 try { 7945 if (!sWifiLowLatencyLockListenerMap.contains(listenerIdentifier)) { 7946 Log.w(TAG, "Unknown external listener " + listenerIdentifier); 7947 return; 7948 } 7949 mService.removeWifiLowLatencyLockListener( 7950 sWifiLowLatencyLockListenerMap.get(listenerIdentifier)); 7951 7952 } catch (RemoteException e) { 7953 throw e.rethrowFromSystemServer(); 7954 } finally { 7955 sWifiLowLatencyLockListenerMap.remove(listenerIdentifier); 7956 } 7957 } 7958 } 7959 7960 /** 7961 * Creates a new WifiLock. 7962 * 7963 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is 7964 * never shown to the user under normal conditions, but should be descriptive 7965 * enough to identify your application and the specific WifiLock within it, if it 7966 * holds multiple WifiLocks. 7967 * 7968 * @return a new, unacquired WifiLock with the given tag. 7969 * 7970 * @see WifiLock 7971 * 7972 * @deprecated This API is non-functional. 7973 */ 7974 @Deprecated createWifiLock(String tag)7975 public WifiLock createWifiLock(String tag) { 7976 return new WifiLock(WIFI_MODE_FULL, tag); 7977 } 7978 7979 /** 7980 * Create a new MulticastLock 7981 * 7982 * @param tag a tag for the MulticastLock to identify it in debugging 7983 * messages. This string is never shown to the user under 7984 * normal conditions, but should be descriptive enough to 7985 * identify your application and the specific MulticastLock 7986 * within it, if it holds multiple MulticastLocks. 7987 * 7988 * @return a new, unacquired MulticastLock with the given tag. 7989 * 7990 * @see MulticastLock 7991 */ createMulticastLock(String tag)7992 public MulticastLock createMulticastLock(String tag) { 7993 return new MulticastLock(tag); 7994 } 7995 7996 /** 7997 * Allows an application to receive Wifi Multicast packets. 7998 * Normally the Wifi stack filters out packets not explicitly 7999 * addressed to this device. Acquring a MulticastLock will 8000 * cause the stack to receive packets addressed to multicast 8001 * addresses. Processing these extra packets can cause a noticeable 8002 * battery drain and should be disabled when not needed. 8003 */ 8004 public class MulticastLock { 8005 private String mTag; 8006 private final IBinder mBinder; 8007 private int mRefCount; 8008 private boolean mRefCounted; 8009 private boolean mHeld; 8010 MulticastLock(String tag)8011 private MulticastLock(String tag) { 8012 mTag = tag; 8013 mBinder = new Binder(); 8014 mRefCount = 0; 8015 mRefCounted = true; 8016 mHeld = false; 8017 } 8018 8019 /** 8020 * Locks Wifi Multicast on until {@link #release} is called. 8021 * 8022 * If this MulticastLock is reference-counted each call to 8023 * {@code acquire} will increment the reference count, and the 8024 * wifi interface will receive multicast packets as long as the 8025 * reference count is above zero. 8026 * 8027 * If this MulticastLock is not reference-counted, the first call to 8028 * {@code acquire} will turn on the multicast packets, but subsequent 8029 * calls will be ignored. Only one call to {@link #release} will 8030 * be required, regardless of the number of times that {@code acquire} 8031 * is called. 8032 * 8033 * Note that other applications may also lock Wifi Multicast on. 8034 * Only they can relinquish their lock. 8035 * 8036 * Also note that applications cannot leave Multicast locked on. 8037 * When an app exits or crashes, any Multicast locks will be released. 8038 */ acquire()8039 public void acquire() { 8040 synchronized (mBinder) { 8041 if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) { 8042 try { 8043 mService.acquireMulticastLock(mBinder, mTag); 8044 synchronized (WifiManager.this) { 8045 if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { 8046 mService.releaseMulticastLock(mTag); 8047 throw new UnsupportedOperationException( 8048 "Exceeded maximum number of wifi locks"); 8049 } 8050 mActiveLockCount++; 8051 } 8052 } catch (RemoteException e) { 8053 throw e.rethrowFromSystemServer(); 8054 } 8055 mHeld = true; 8056 } 8057 } 8058 } 8059 8060 /** 8061 * Unlocks Wifi Multicast, restoring the filter of packets 8062 * not addressed specifically to this device and saving power. 8063 * 8064 * If this MulticastLock is reference-counted, each call to 8065 * {@code release} will decrement the reference count, and the 8066 * multicast packets will only stop being received when the reference 8067 * count reaches zero. If the reference count goes below zero (that 8068 * is, if {@code release} is called a greater number of times than 8069 * {@link #acquire}), an exception is thrown. 8070 * 8071 * If this MulticastLock is not reference-counted, the first call to 8072 * {@code release} (after the radio was multicast locked using 8073 * {@link #acquire}) will unlock the multicast, and subsequent calls 8074 * will be ignored. 8075 * 8076 * Note that if any other Wifi Multicast Locks are still outstanding 8077 * this {@code release} call will not have an immediate effect. Only 8078 * when all applications have released all their Multicast Locks will 8079 * the Multicast filter be turned back on. 8080 * 8081 * Also note that when an app exits or crashes all of its Multicast 8082 * Locks will be automatically released. 8083 */ release()8084 public void release() { 8085 synchronized (mBinder) { 8086 if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { 8087 try { 8088 mService.releaseMulticastLock(mTag); 8089 synchronized (WifiManager.this) { 8090 mActiveLockCount--; 8091 } 8092 } catch (RemoteException e) { 8093 throw e.rethrowFromSystemServer(); 8094 } 8095 mHeld = false; 8096 } 8097 if (mRefCount < 0) { 8098 throw new RuntimeException("MulticastLock under-locked " 8099 + mTag); 8100 } 8101 } 8102 } 8103 8104 /** 8105 * Controls whether this is a reference-counted or non-reference- 8106 * counted MulticastLock. 8107 * 8108 * Reference-counted MulticastLocks keep track of the number of calls 8109 * to {@link #acquire} and {@link #release}, and only stop the 8110 * reception of multicast packets when every call to {@link #acquire} 8111 * has been balanced with a call to {@link #release}. Non-reference- 8112 * counted MulticastLocks allow the reception of multicast packets 8113 * whenever {@link #acquire} is called and stop accepting multicast 8114 * packets whenever {@link #release} is called. 8115 * 8116 * @param refCounted true if this MulticastLock should keep a reference 8117 * count 8118 */ setReferenceCounted(boolean refCounted)8119 public void setReferenceCounted(boolean refCounted) { 8120 mRefCounted = refCounted; 8121 } 8122 8123 /** 8124 * Checks whether this MulticastLock is currently held. 8125 * 8126 * @return true if this MulticastLock is held, false otherwise 8127 */ isHeld()8128 public boolean isHeld() { 8129 synchronized (mBinder) { 8130 return mHeld; 8131 } 8132 } 8133 toString()8134 public String toString() { 8135 String s1, s2, s3; 8136 synchronized (mBinder) { 8137 s1 = Integer.toHexString(System.identityHashCode(this)); 8138 s2 = mHeld ? "held; " : ""; 8139 if (mRefCounted) { 8140 s3 = "refcounted: refcount = " + mRefCount; 8141 } else { 8142 s3 = "not refcounted"; 8143 } 8144 return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; 8145 } 8146 } 8147 8148 @Override finalize()8149 protected void finalize() throws Throwable { 8150 super.finalize(); 8151 setReferenceCounted(false); 8152 release(); 8153 } 8154 } 8155 8156 /** 8157 * Check multicast filter status. 8158 * 8159 * @return true if multicast packets are allowed. 8160 * 8161 * @hide pending API council approval 8162 */ isMulticastEnabled()8163 public boolean isMulticastEnabled() { 8164 try { 8165 return mService.isMulticastEnabled(); 8166 } catch (RemoteException e) { 8167 throw e.rethrowFromSystemServer(); 8168 } 8169 } 8170 8171 /** 8172 * Initialize the multicast filtering to 'on' 8173 * @hide no intent to publish 8174 */ 8175 @UnsupportedAppUsage initializeMulticastFiltering()8176 public boolean initializeMulticastFiltering() { 8177 try { 8178 mService.initializeMulticastFiltering(); 8179 return true; 8180 } catch (RemoteException e) { 8181 throw e.rethrowFromSystemServer(); 8182 } 8183 } 8184 8185 /** 8186 * Set Wi-Fi verbose logging level from developer settings. 8187 * 8188 * @param enable true to enable verbose logging, false to disable. 8189 * 8190 * @hide 8191 */ 8192 @SystemApi 8193 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setVerboseLoggingEnabled(boolean enable)8194 public void setVerboseLoggingEnabled(boolean enable) { 8195 enableVerboseLogging(enable ? VERBOSE_LOGGING_LEVEL_ENABLED 8196 : VERBOSE_LOGGING_LEVEL_DISABLED); 8197 } 8198 8199 /** 8200 * Set Wi-Fi verbose logging level from developer settings. 8201 * 8202 * @param verbose the verbose logging mode which could be 8203 * {@link #VERBOSE_LOGGING_LEVEL_DISABLED}, {@link #VERBOSE_LOGGING_LEVEL_ENABLED}, or 8204 * {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}. 8205 * 8206 * @hide 8207 */ 8208 @SystemApi 8209 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setVerboseLoggingLevel(@erboseLoggingLevel int verbose)8210 public void setVerboseLoggingLevel(@VerboseLoggingLevel int verbose) { 8211 enableVerboseLogging(verbose); 8212 } 8213 8214 /** @hide */ 8215 @UnsupportedAppUsage( 8216 maxTargetSdk = Build.VERSION_CODES.Q, 8217 publicAlternatives = "Use {@code #setVerboseLoggingEnabled(boolean)} instead." 8218 ) 8219 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) enableVerboseLogging(@erboseLoggingLevel int verbose)8220 public void enableVerboseLogging(@VerboseLoggingLevel int verbose) { 8221 try { 8222 mService.enableVerboseLogging(verbose); 8223 mVerboseLoggingEnabled = verbose == VERBOSE_LOGGING_LEVEL_ENABLED; 8224 } catch (RemoteException e) { 8225 throw e.rethrowFromSystemServer(); 8226 } 8227 } 8228 8229 /** 8230 * Get the persisted Wi-Fi verbose logging level, set by 8231 * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}. 8232 * No permissions are required to call this method. 8233 * 8234 * @return true to indicate that verbose logging is enabled, false to indicate that verbose 8235 * logging is disabled. 8236 * 8237 * @hide 8238 */ 8239 @SystemApi isVerboseLoggingEnabled()8240 public boolean isVerboseLoggingEnabled() { 8241 return getVerboseLoggingLevel() > 0; 8242 } 8243 8244 /** 8245 * Get the persisted Wi-Fi verbose logging level, set by 8246 * {@link #setVerboseLoggingEnabled(boolean)} or {@link #setVerboseLoggingLevel(int)}. 8247 * No permissions are required to call this method. 8248 * 8249 * @return one of {@link #VERBOSE_LOGGING_LEVEL_DISABLED}, 8250 * {@link #VERBOSE_LOGGING_LEVEL_ENABLED}, 8251 * or {@link #VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY}. 8252 * 8253 * @hide 8254 */ 8255 @SystemApi getVerboseLoggingLevel()8256 public @VerboseLoggingLevel int getVerboseLoggingLevel() { 8257 try { 8258 return mService.getVerboseLoggingLevel(); 8259 } catch (RemoteException e) { 8260 throw e.rethrowFromSystemServer(); 8261 } 8262 } 8263 8264 /** 8265 * Removes all saved Wi-Fi networks, Passpoint configurations, ephemeral networks, Network 8266 * Requests, and Network Suggestions. 8267 * 8268 * @hide 8269 */ 8270 @SystemApi 8271 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) factoryReset()8272 public void factoryReset() { 8273 try { 8274 mService.factoryReset(mContext.getOpPackageName()); 8275 } catch (RemoteException e) { 8276 throw e.rethrowFromSystemServer(); 8277 } 8278 } 8279 8280 /** 8281 * Get {@link Network} object of current wifi network, or null if not connected. 8282 * @hide 8283 */ 8284 @Nullable 8285 @SystemApi 8286 @RequiresPermission(anyOf = { 8287 android.Manifest.permission.NETWORK_SETTINGS, 8288 android.Manifest.permission.NETWORK_SETUP_WIZARD 8289 }) getCurrentNetwork()8290 public Network getCurrentNetwork() { 8291 try { 8292 return mService.getCurrentNetwork(); 8293 } catch (RemoteException e) { 8294 throw e.rethrowFromSystemServer(); 8295 } 8296 } 8297 8298 /** 8299 * Deprecated 8300 * returns false 8301 * @hide 8302 * @deprecated 8303 */ setEnableAutoJoinWhenAssociated(boolean enabled)8304 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 8305 return false; 8306 } 8307 8308 /** 8309 * Deprecated 8310 * returns false 8311 * @hide 8312 * @deprecated 8313 */ getEnableAutoJoinWhenAssociated()8314 public boolean getEnableAutoJoinWhenAssociated() { 8315 return false; 8316 } 8317 8318 /** 8319 * Returns a byte stream representing the data that needs to be backed up to save the 8320 * current Wifi state. 8321 * This Wifi state can be restored by calling {@link #restoreBackupData(byte[])}. 8322 * @hide 8323 */ 8324 @NonNull 8325 @SystemApi 8326 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) retrieveBackupData()8327 public byte[] retrieveBackupData() { 8328 try { 8329 return mService.retrieveBackupData(); 8330 } catch (RemoteException e) { 8331 throw e.rethrowFromSystemServer(); 8332 } 8333 } 8334 8335 /** 8336 * Restore state from the backed up data. 8337 * @param data byte stream in the same format produced by {@link #retrieveBackupData()} 8338 * @hide 8339 */ 8340 @SystemApi 8341 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreBackupData(@onNull byte[] data)8342 public void restoreBackupData(@NonNull byte[] data) { 8343 try { 8344 mService.restoreBackupData(data); 8345 } catch (RemoteException e) { 8346 throw e.rethrowFromSystemServer(); 8347 } 8348 } 8349 8350 /** 8351 * Returns a byte stream representing the data that needs to be backed up to save the 8352 * current soft ap config data. 8353 * 8354 * This soft ap config can be restored by calling {@link #restoreSoftApBackupData(byte[])} 8355 * @hide 8356 */ 8357 @NonNull 8358 @SystemApi 8359 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) retrieveSoftApBackupData()8360 public byte[] retrieveSoftApBackupData() { 8361 try { 8362 return mService.retrieveSoftApBackupData(); 8363 } catch (RemoteException e) { 8364 throw e.rethrowFromSystemServer(); 8365 } 8366 } 8367 8368 /** 8369 * Returns soft ap config from the backed up data or null if data is invalid. 8370 * @param data byte stream in the same format produced by {@link #retrieveSoftApBackupData()} 8371 * 8372 * @hide 8373 */ 8374 @Nullable 8375 @SystemApi 8376 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreSoftApBackupData(@onNull byte[] data)8377 public SoftApConfiguration restoreSoftApBackupData(@NonNull byte[] data) { 8378 try { 8379 return mService.restoreSoftApBackupData(data); 8380 } catch (RemoteException e) { 8381 throw e.rethrowFromSystemServer(); 8382 } 8383 } 8384 8385 /** 8386 * Restore state from the older version of back up data. 8387 * The old backup data was essentially a backup of wpa_supplicant.conf 8388 * and ipconfig.txt file. 8389 * @param supplicantData bytes representing wpa_supplicant.conf 8390 * @param ipConfigData bytes representing ipconfig.txt 8391 * @hide 8392 */ 8393 @SystemApi 8394 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) restoreSupplicantBackupData( @onNull byte[] supplicantData, @NonNull byte[] ipConfigData)8395 public void restoreSupplicantBackupData( 8396 @NonNull byte[] supplicantData, @NonNull byte[] ipConfigData) { 8397 try { 8398 mService.restoreSupplicantBackupData(supplicantData, ipConfigData); 8399 } catch (RemoteException e) { 8400 throw e.rethrowFromSystemServer(); 8401 } 8402 } 8403 8404 /** 8405 * Start subscription provisioning flow 8406 * 8407 * @param provider {@link OsuProvider} to provision with 8408 * @param executor the Executor on which to run the callback. 8409 * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow 8410 * @hide 8411 */ 8412 @SystemApi 8413 @RequiresPermission(anyOf = { 8414 android.Manifest.permission.NETWORK_SETTINGS, 8415 android.Manifest.permission.NETWORK_SETUP_WIZARD 8416 }) startSubscriptionProvisioning(@onNull OsuProvider provider, @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback)8417 public void startSubscriptionProvisioning(@NonNull OsuProvider provider, 8418 @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback) { 8419 // Verify arguments 8420 if (executor == null) { 8421 throw new IllegalArgumentException("executor must not be null"); 8422 } 8423 if (callback == null) { 8424 throw new IllegalArgumentException("callback must not be null"); 8425 } 8426 try { 8427 mService.startSubscriptionProvisioning(provider, 8428 new ProvisioningCallbackProxy(executor, callback)); 8429 } catch (RemoteException e) { 8430 throw e.rethrowFromSystemServer(); 8431 } 8432 } 8433 8434 /** 8435 * Helper class to support OSU Provisioning callbacks 8436 */ 8437 private static class ProvisioningCallbackProxy extends IProvisioningCallback.Stub { 8438 private final Executor mExecutor; 8439 private final ProvisioningCallback mCallback; 8440 ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback)8441 ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback) { 8442 mExecutor = executor; 8443 mCallback = callback; 8444 } 8445 8446 @Override onProvisioningStatus(int status)8447 public void onProvisioningStatus(int status) { 8448 mExecutor.execute(() -> mCallback.onProvisioningStatus(status)); 8449 } 8450 8451 @Override onProvisioningFailure(int status)8452 public void onProvisioningFailure(int status) { 8453 mExecutor.execute(() -> mCallback.onProvisioningFailure(status)); 8454 } 8455 8456 @Override onProvisioningComplete()8457 public void onProvisioningComplete() { 8458 mExecutor.execute(() -> mCallback.onProvisioningComplete()); 8459 } 8460 } 8461 8462 /** 8463 * Interface for Traffic state callback. Should be extended by applications and set when 8464 * calling {@link #registerTrafficStateCallback(Executor, WifiManager.TrafficStateCallback)}. 8465 * @hide 8466 */ 8467 @SystemApi 8468 public interface TrafficStateCallback { 8469 /** @hide */ 8470 @Retention(RetentionPolicy.SOURCE) 8471 @IntDef(prefix = {"DATA_ACTIVITY_"}, value = { 8472 DATA_ACTIVITY_NONE, 8473 DATA_ACTIVITY_IN, 8474 DATA_ACTIVITY_OUT, 8475 DATA_ACTIVITY_INOUT}) 8476 @interface DataActivity {} 8477 8478 // Lowest bit indicates data reception and the second lowest bit indicates data transmitted 8479 /** No data in or out */ 8480 int DATA_ACTIVITY_NONE = 0x00; 8481 /** Data in, no data out */ 8482 int DATA_ACTIVITY_IN = 0x01; 8483 /** Data out, no data in */ 8484 int DATA_ACTIVITY_OUT = 0x02; 8485 /** Data in and out */ 8486 int DATA_ACTIVITY_INOUT = 0x03; 8487 8488 /** 8489 * Callback invoked to inform clients about the current traffic state. 8490 * 8491 * @param state One of the values: {@link #DATA_ACTIVITY_NONE}, {@link #DATA_ACTIVITY_IN}, 8492 * {@link #DATA_ACTIVITY_OUT} & {@link #DATA_ACTIVITY_INOUT}. 8493 */ onStateChanged(@ataActivity int state)8494 void onStateChanged(@DataActivity int state); 8495 } 8496 8497 /** 8498 * Callback proxy for TrafficStateCallback objects. 8499 * 8500 * @hide 8501 */ 8502 private class TrafficStateCallbackProxy extends ITrafficStateCallback.Stub { 8503 private final Executor mExecutor; 8504 private final TrafficStateCallback mCallback; 8505 TrafficStateCallbackProxy(Executor executor, TrafficStateCallback callback)8506 TrafficStateCallbackProxy(Executor executor, TrafficStateCallback callback) { 8507 mExecutor = executor; 8508 mCallback = callback; 8509 } 8510 8511 @Override onStateChanged(int state)8512 public void onStateChanged(int state) { 8513 if (mVerboseLoggingEnabled) { 8514 Log.v(TAG, "TrafficStateCallbackProxy: onStateChanged state=" + state); 8515 } 8516 Binder.clearCallingIdentity(); 8517 mExecutor.execute(() -> { 8518 mCallback.onStateChanged(state); 8519 }); 8520 } 8521 } 8522 8523 /** 8524 * Registers a callback for monitoring traffic state. See {@link TrafficStateCallback}. These 8525 * callbacks will be invoked periodically by platform to inform clients about the current 8526 * traffic state. Caller can unregister a previously registered callback using 8527 * {@link #unregisterTrafficStateCallback(TrafficStateCallback)} 8528 * <p> 8529 * Applications should have the 8530 * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers 8531 * without the permission will trigger a {@link java.lang.SecurityException}. 8532 * <p> 8533 * 8534 * @param executor The Executor on whose thread to execute the callbacks of the {@code callback} 8535 * object. 8536 * @param callback Callback for traffic state events 8537 * @hide 8538 */ 8539 @SystemApi 8540 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) registerTrafficStateCallback(@onNull @allbackExecutor Executor executor, @NonNull TrafficStateCallback callback)8541 public void registerTrafficStateCallback(@NonNull @CallbackExecutor Executor executor, 8542 @NonNull TrafficStateCallback callback) { 8543 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 8544 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 8545 Log.v(TAG, "registerTrafficStateCallback: callback=" + callback + ", executor=" + executor); 8546 8547 try { 8548 synchronized (sTrafficStateCallbackMap) { 8549 ITrafficStateCallback.Stub binderCallback = new TrafficStateCallbackProxy(executor, 8550 callback); 8551 sTrafficStateCallbackMap.put(System.identityHashCode(callback), binderCallback); 8552 mService.registerTrafficStateCallback(binderCallback); 8553 } 8554 } catch (RemoteException e) { 8555 throw e.rethrowFromSystemServer(); 8556 } 8557 } 8558 8559 /** 8560 * Allow callers to unregister a previously registered callback. After calling this method, 8561 * applications will no longer receive traffic state notifications. 8562 * 8563 * @param callback Callback to unregister for traffic state events 8564 * @hide 8565 */ 8566 @SystemApi 8567 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) unregisterTrafficStateCallback(@onNull TrafficStateCallback callback)8568 public void unregisterTrafficStateCallback(@NonNull TrafficStateCallback callback) { 8569 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 8570 Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback); 8571 8572 try { 8573 synchronized (sTrafficStateCallbackMap) { 8574 int callbackIdentifier = System.identityHashCode(callback); 8575 if (!sTrafficStateCallbackMap.contains(callbackIdentifier)) { 8576 Log.w(TAG, "Unknown external callback " + callbackIdentifier); 8577 return; 8578 } 8579 mService.unregisterTrafficStateCallback( 8580 sTrafficStateCallbackMap.get(callbackIdentifier)); 8581 sTrafficStateCallbackMap.remove(callbackIdentifier); 8582 } 8583 } catch (RemoteException e) { 8584 throw e.rethrowFromSystemServer(); 8585 } 8586 } 8587 8588 /** 8589 * Helper method to update the local verbose logging flag based on the verbose logging 8590 * level from wifi service. 8591 */ updateVerboseLoggingEnabledFromService()8592 private void updateVerboseLoggingEnabledFromService() { 8593 mVerboseLoggingEnabled = isVerboseLoggingEnabled(); 8594 } 8595 8596 /** 8597 * @return true if this device supports WPA3-Personal SAE 8598 */ isWpa3SaeSupported()8599 public boolean isWpa3SaeSupported() { 8600 return isFeatureSupported(WIFI_FEATURE_WPA3_SAE); 8601 } 8602 8603 /** 8604 * @return true if this device supports WPA3-Enterprise Suite-B-192 8605 */ isWpa3SuiteBSupported()8606 public boolean isWpa3SuiteBSupported() { 8607 return isFeatureSupported(WIFI_FEATURE_WPA3_SUITE_B); 8608 } 8609 8610 /** 8611 * @return true if this device supports Wi-Fi Enhanced Open (OWE) 8612 */ isEnhancedOpenSupported()8613 public boolean isEnhancedOpenSupported() { 8614 return isFeatureSupported(WIFI_FEATURE_OWE); 8615 } 8616 8617 /** 8618 * Wi-Fi Easy Connect (DPP) introduces standardized mechanisms to simplify the provisioning and 8619 * configuration of Wi-Fi devices. 8620 * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and 8621 * search for "Easy Connect" or "Device Provisioning Protocol specification". 8622 * 8623 * @return true if this device supports Wi-Fi Easy-connect (Device Provisioning Protocol) 8624 */ isEasyConnectSupported()8625 public boolean isEasyConnectSupported() { 8626 return isFeatureSupported(WIFI_FEATURE_DPP); 8627 } 8628 8629 /** 8630 * @return true if this device supports Wi-Fi Easy Connect (DPP) Enrollee Responder mode. 8631 */ isEasyConnectEnrolleeResponderModeSupported()8632 public boolean isEasyConnectEnrolleeResponderModeSupported() { 8633 return isFeatureSupported(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER); 8634 } 8635 8636 /** 8637 * @return true if this device supports WAPI. 8638 */ isWapiSupported()8639 public boolean isWapiSupported() { 8640 return isFeatureSupported(WIFI_FEATURE_WAPI); 8641 } 8642 8643 /** 8644 * @return true if this device supports WPA3 SAE Public Key. 8645 */ isWpa3SaePublicKeySupported()8646 public boolean isWpa3SaePublicKeySupported() { 8647 // This feature is not fully implemented in the framework yet. 8648 // After the feature complete, it returns whether WIFI_FEATURE_SAE_PK 8649 // is supported or not directly. 8650 return false; 8651 } 8652 8653 /** 8654 * @return true if this device supports Wi-Fi Passpoint Terms and Conditions feature. 8655 */ isPasspointTermsAndConditionsSupported()8656 public boolean isPasspointTermsAndConditionsSupported() { 8657 return isFeatureSupported(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS); 8658 } 8659 8660 /** 8661 * @return true if this device supports WPA3 SAE Hash-to-Element. 8662 */ isWpa3SaeH2eSupported()8663 public boolean isWpa3SaeH2eSupported() { 8664 return isFeatureSupported(WIFI_FEATURE_SAE_H2E); 8665 } 8666 8667 /** 8668 * @return true if this device supports Wi-Fi Display R2. 8669 */ isWifiDisplayR2Supported()8670 public boolean isWifiDisplayR2Supported() { 8671 return isFeatureSupported(WIFI_FEATURE_WFD_R2); 8672 } 8673 8674 /** 8675 * @return true if this device supports RFC 7542 decorated identity. 8676 */ isDecoratedIdentitySupported()8677 public boolean isDecoratedIdentitySupported() { 8678 return isFeatureSupported(WIFI_FEATURE_DECORATED_IDENTITY); 8679 } 8680 8681 /** 8682 * @return true if this device supports Trust On First Use (TOFU). 8683 */ isTrustOnFirstUseSupported()8684 public boolean isTrustOnFirstUseSupported() { 8685 return isFeatureSupported(WIFI_FEATURE_TRUST_ON_FIRST_USE); 8686 } 8687 8688 /** 8689 * Wi-Fi Easy Connect DPP AKM enables provisioning and configuration of Wi-Fi devices without 8690 * the need of using the device PSK passphrase. 8691 * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and 8692 * search for "Easy Connect" or "Device Provisioning Protocol specification". 8693 * 8694 * @return true if this device supports Wi-Fi Easy-connect DPP (Device Provisioning Protocol) 8695 * AKM, false otherwise. 8696 */ isEasyConnectDppAkmSupported()8697 public boolean isEasyConnectDppAkmSupported() { 8698 return isFeatureSupported(WIFI_FEATURE_DPP_AKM); 8699 } 8700 8701 /** 8702 * Indicate that whether or not settings required TLS minimum version is supported. 8703 * 8704 * If the device doesn't support this capability, the minimum accepted TLS version is 1.0. 8705 * 8706 * @return true if this device supports setting TLS minimum version. 8707 */ isTlsMinimumVersionSupported()8708 public boolean isTlsMinimumVersionSupported() { 8709 return isFeatureSupported(WIFI_FEATURE_SET_TLS_MINIMUM_VERSION); 8710 } 8711 8712 /** 8713 * Indicate that whether or not TLS v1.3 is supported. 8714 * 8715 * If requested minimum is not supported, it will default to the maximum supported version. 8716 * 8717 * @return true if this device supports TLS v1.3. 8718 */ isTlsV13Supported()8719 public boolean isTlsV13Supported() { 8720 return isFeatureSupported(WIFI_FEATURE_TLS_V1_3); 8721 } 8722 8723 /** 8724 * @return true if this device supports Dual Band Simultaneous (DBS) operation. 8725 */ isDualBandSimultaneousSupported()8726 public boolean isDualBandSimultaneousSupported() { 8727 return isFeatureSupported(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS); 8728 } 8729 8730 /** 8731 * @return true if this device supports TID-To-Link Mapping Negotiation. 8732 */ isTidToLinkMappingNegotiationSupported()8733 public boolean isTidToLinkMappingNegotiationSupported() { 8734 return isFeatureSupported(WIFI_FEATURE_T2LM_NEGOTIATION); 8735 } 8736 8737 /** 8738 * Gets the factory Wi-Fi MAC addresses. 8739 * @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array 8740 * if failed. 8741 * @hide 8742 */ 8743 @NonNull 8744 @SystemApi 8745 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) getFactoryMacAddresses()8746 public String[] getFactoryMacAddresses() { 8747 try { 8748 return mService.getFactoryMacAddresses(); 8749 } catch (RemoteException e) { 8750 throw e.rethrowFromSystemServer(); 8751 } 8752 } 8753 8754 /** @hide */ 8755 @Retention(RetentionPolicy.SOURCE) 8756 @IntDef(prefix = {"DEVICE_MOBILITY_STATE_"}, value = { 8757 DEVICE_MOBILITY_STATE_UNKNOWN, 8758 DEVICE_MOBILITY_STATE_HIGH_MVMT, 8759 DEVICE_MOBILITY_STATE_LOW_MVMT, 8760 DEVICE_MOBILITY_STATE_STATIONARY}) 8761 public @interface DeviceMobilityState {} 8762 8763 /** 8764 * Unknown device mobility state 8765 * 8766 * @see #setDeviceMobilityState(int) 8767 * 8768 * @hide 8769 */ 8770 @SystemApi 8771 public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0; 8772 8773 /** 8774 * High movement device mobility state. 8775 * e.g. on a bike, in a motor vehicle 8776 * 8777 * @see #setDeviceMobilityState(int) 8778 * 8779 * @hide 8780 */ 8781 @SystemApi 8782 public static final int DEVICE_MOBILITY_STATE_HIGH_MVMT = 1; 8783 8784 /** 8785 * Low movement device mobility state. 8786 * e.g. walking, running 8787 * 8788 * @see #setDeviceMobilityState(int) 8789 * 8790 * @hide 8791 */ 8792 @SystemApi 8793 public static final int DEVICE_MOBILITY_STATE_LOW_MVMT = 2; 8794 8795 /** 8796 * Stationary device mobility state 8797 * 8798 * @see #setDeviceMobilityState(int) 8799 * 8800 * @hide 8801 */ 8802 @SystemApi 8803 public static final int DEVICE_MOBILITY_STATE_STATIONARY = 3; 8804 8805 /** 8806 * Updates the device mobility state. Wifi uses this information to adjust the interval between 8807 * Wifi scans in order to balance power consumption with scan accuracy. 8808 * The default mobility state when the device boots is {@link #DEVICE_MOBILITY_STATE_UNKNOWN}. 8809 * This API should be called whenever there is a change in the mobility state. 8810 * @param state the updated device mobility state 8811 * @hide 8812 */ 8813 @SystemApi 8814 @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) setDeviceMobilityState(@eviceMobilityState int state)8815 public void setDeviceMobilityState(@DeviceMobilityState int state) { 8816 try { 8817 mService.setDeviceMobilityState(state); 8818 } catch (RemoteException e) { 8819 throw e.rethrowFromSystemServer(); 8820 } 8821 } 8822 8823 /* Easy Connect - AKA Device Provisioning Protocol (DPP) */ 8824 8825 /** 8826 * Easy Connect Network role: Station. 8827 * 8828 * @hide 8829 */ 8830 @SystemApi 8831 public static final int EASY_CONNECT_NETWORK_ROLE_STA = 0; 8832 8833 /** 8834 * Easy Connect Network role: Access Point. 8835 * 8836 * @hide 8837 */ 8838 @SystemApi 8839 public static final int EASY_CONNECT_NETWORK_ROLE_AP = 1; 8840 8841 /** @hide */ 8842 @IntDef(prefix = {"EASY_CONNECT_NETWORK_ROLE_"}, value = { 8843 EASY_CONNECT_NETWORK_ROLE_STA, 8844 EASY_CONNECT_NETWORK_ROLE_AP, 8845 }) 8846 @Retention(RetentionPolicy.SOURCE) 8847 public @interface EasyConnectNetworkRole { 8848 } 8849 8850 /** Easy Connect Device information maximum allowed length */ 8851 private static final int EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH = 40; 8852 8853 /** 8854 * Easy Connect Cryptography Curve name: prime256v1 8855 * 8856 * @hide 8857 */ 8858 @SystemApi 8859 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1 = 0; 8860 8861 /** 8862 * Easy Connect Cryptography Curve name: secp384r1 8863 * 8864 * @hide 8865 */ 8866 @SystemApi 8867 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1 = 1; 8868 8869 /** 8870 * Easy Connect Cryptography Curve name: secp521r1 8871 * 8872 * @hide 8873 */ 8874 @SystemApi 8875 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1 = 2; 8876 8877 8878 /** 8879 * Easy Connect Cryptography Curve name: brainpoolP256r1 8880 * 8881 * @hide 8882 */ 8883 @SystemApi 8884 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1 = 3; 8885 8886 8887 /** 8888 * Easy Connect Cryptography Curve name: brainpoolP384r1 8889 * 8890 * @hide 8891 */ 8892 @SystemApi 8893 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1 = 4; 8894 8895 8896 /** 8897 * Easy Connect Cryptography Curve name: brainpoolP512r1 8898 * 8899 * @hide 8900 */ 8901 @SystemApi 8902 public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1 = 5; 8903 8904 /** @hide */ 8905 @IntDef(prefix = {"EASY_CONNECT_CRYPTOGRAPHY_CURVE_"}, value = { 8906 EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1, 8907 EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1, 8908 EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1, 8909 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1, 8910 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1, 8911 EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1, 8912 }) 8913 @Retention(RetentionPolicy.SOURCE) 8914 public @interface EasyConnectCryptographyCurve { 8915 } 8916 8917 /** 8918 * Verbose logging mode: DISABLED. 8919 * @hide 8920 */ 8921 @SystemApi 8922 public static final int VERBOSE_LOGGING_LEVEL_DISABLED = 0; 8923 8924 /** 8925 * Verbose logging mode: ENABLED. 8926 * @hide 8927 */ 8928 @SystemApi 8929 public static final int VERBOSE_LOGGING_LEVEL_ENABLED = 1; 8930 8931 /** 8932 * Verbose logging mode: ENABLED_SHOW_KEY. 8933 * This mode causes the Wi-Fi password and encryption keys to be output to the logcat. 8934 * This is security sensitive information useful for debugging. 8935 * This configuration is enabled for 30 seconds and then falls back to 8936 * the regular verbose mode (i.e. to {@link VERBOSE_LOGGING_LEVEL_ENABLED}). 8937 * Show key mode is not persistent, i.e. rebooting the device would fallback to 8938 * the regular verbose mode. 8939 * @hide 8940 */ 8941 @SystemApi 8942 public static final int VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY = 2; 8943 8944 /** @hide */ 8945 @IntDef(prefix = {"VERBOSE_LOGGING_LEVEL_"}, value = { 8946 VERBOSE_LOGGING_LEVEL_DISABLED, 8947 VERBOSE_LOGGING_LEVEL_ENABLED, 8948 VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY, 8949 }) 8950 @Retention(RetentionPolicy.SOURCE) 8951 public @interface VerboseLoggingLevel { 8952 } 8953 8954 /** 8955 * Start Easy Connect (DPP) in Configurator-Initiator role. The current device will initiate 8956 * Easy Connect bootstrapping with a peer, and configure the peer with the SSID and password of 8957 * the specified network using the Easy Connect protocol on an encrypted link. 8958 * 8959 * @param enrolleeUri URI of the Enrollee obtained separately (e.g. QR code scanning) 8960 * @param selectedNetworkId Selected network ID to be sent to the peer 8961 * @param enrolleeNetworkRole The network role of the enrollee 8962 * @param callback Callback for status updates 8963 * @param executor The Executor on which to run the callback. 8964 * @hide 8965 */ 8966 @SystemApi 8967 @RequiresPermission(anyOf = { 8968 android.Manifest.permission.NETWORK_SETTINGS, 8969 android.Manifest.permission.NETWORK_SETUP_WIZARD}) startEasyConnectAsConfiguratorInitiator(@onNull String enrolleeUri, int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)8970 public void startEasyConnectAsConfiguratorInitiator(@NonNull String enrolleeUri, 8971 int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole, 8972 @NonNull @CallbackExecutor Executor executor, 8973 @NonNull EasyConnectStatusCallback callback) { 8974 Binder binder = new Binder(); 8975 try { 8976 mService.startDppAsConfiguratorInitiator(binder, mContext.getOpPackageName(), 8977 enrolleeUri, selectedNetworkId, enrolleeNetworkRole, 8978 new EasyConnectCallbackProxy(executor, callback)); 8979 } catch (RemoteException e) { 8980 throw e.rethrowFromSystemServer(); 8981 } 8982 } 8983 8984 /** 8985 * Start Easy Connect (DPP) in Enrollee-Initiator role. The current device will initiate Easy 8986 * Connect bootstrapping with a peer, and receive the SSID and password from the peer 8987 * configurator. 8988 * 8989 * @param configuratorUri URI of the Configurator obtained separately (e.g. QR code scanning) 8990 * @param callback Callback for status updates 8991 * @param executor The Executor on which to run the callback. 8992 * @hide 8993 */ 8994 @SystemApi 8995 @RequiresPermission(anyOf = { 8996 android.Manifest.permission.NETWORK_SETTINGS, 8997 android.Manifest.permission.NETWORK_SETUP_WIZARD}) startEasyConnectAsEnrolleeInitiator(@onNull String configuratorUri, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)8998 public void startEasyConnectAsEnrolleeInitiator(@NonNull String configuratorUri, 8999 @NonNull @CallbackExecutor Executor executor, 9000 @NonNull EasyConnectStatusCallback callback) { 9001 Binder binder = new Binder(); 9002 try { 9003 mService.startDppAsEnrolleeInitiator(binder, configuratorUri, 9004 new EasyConnectCallbackProxy(executor, callback)); 9005 } catch (RemoteException e) { 9006 throw e.rethrowFromSystemServer(); 9007 } 9008 } 9009 9010 /** 9011 * Start Easy Connect (DPP) in Enrollee-Responder role. 9012 * The device will: 9013 * 1. Generate a DPP bootstrap URI and return it using the 9014 * {@link EasyConnectStatusCallback#onBootstrapUriGenerated(Uri)} method. 9015 * 2. Start DPP as a Responder, waiting for an Initiator device to start the DPP 9016 * authentication process. 9017 * The caller should use the URI provided in step #1, for instance display it as a QR code 9018 * or communicate it in some other way to the initiator device. 9019 * 9020 * @param deviceInfo Device specific information to add to the DPP URI. This field allows 9021 * the users of the configurators to identify the device. 9022 * Optional - if not provided or in case of an empty string, 9023 * Info field (I:) will be skipped in the generated DPP URI. 9024 * Allowed Range of ASCII characters in deviceInfo - %x20-7E. 9025 * semicolon and space are not allowed. Due to the limitation of maximum 9026 * allowed characters in QR code, framework adds a limit to maximum 9027 * characters in deviceInfo. Users must call 9028 * {@link WifiManager#getEasyConnectMaxAllowedResponderDeviceInfoLength() 9029 * } method to know max allowed length. Violation of these rules will 9030 * result in an exception. 9031 * @param curve Elliptic curve cryptography used to generate DPP 9032 * public/private key pair. If application is not interested in a 9033 * specific curve, use specification mandated NIST P-256 elliptic curve, 9034 * {@link WifiManager#EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1}. 9035 * @param callback Callback for status updates 9036 * @param executor The Executor on which to run the callback. 9037 * @hide 9038 */ 9039 @SystemApi 9040 @RequiresPermission(anyOf = { 9041 android.Manifest.permission.NETWORK_SETTINGS, 9042 android.Manifest.permission.NETWORK_SETUP_WIZARD}) 9043 @RequiresApi(Build.VERSION_CODES.S) startEasyConnectAsEnrolleeResponder(@ullable String deviceInfo, @EasyConnectCryptographyCurve int curve, @NonNull @CallbackExecutor Executor executor, @NonNull EasyConnectStatusCallback callback)9044 public void startEasyConnectAsEnrolleeResponder(@Nullable String deviceInfo, 9045 @EasyConnectCryptographyCurve int curve, 9046 @NonNull @CallbackExecutor Executor executor, 9047 @NonNull EasyConnectStatusCallback callback) { 9048 Binder binder = new Binder(); 9049 try { 9050 mService.startDppAsEnrolleeResponder(binder, deviceInfo, curve, 9051 new EasyConnectCallbackProxy(executor, callback)); 9052 } catch (RemoteException e) { 9053 throw e.rethrowFromSystemServer(); 9054 } 9055 } 9056 9057 /** 9058 * Maximum allowed length of Device specific information that can be added to the URI of 9059 * Easy Connect responder device. 9060 * @see #startEasyConnectAsEnrolleeResponder(String, int, Executor, EasyConnectStatusCallback)} 9061 * 9062 * @hide 9063 */ 9064 @SystemApi getEasyConnectMaxAllowedResponderDeviceInfoLength()9065 public static int getEasyConnectMaxAllowedResponderDeviceInfoLength() { 9066 return EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH; 9067 } 9068 9069 /** 9070 * Stop or abort a current Easy Connect (DPP) session. This call, once processed, will 9071 * terminate any ongoing transaction, and clean up all associated resources. Caller should not 9072 * expect any callbacks once this call is made. However, due to the asynchronous nature of 9073 * this call, a callback may be fired if it was already pending in the queue. 9074 * 9075 * @hide 9076 */ 9077 @SystemApi 9078 @RequiresPermission(anyOf = { 9079 android.Manifest.permission.NETWORK_SETTINGS, 9080 android.Manifest.permission.NETWORK_SETUP_WIZARD}) stopEasyConnectSession()9081 public void stopEasyConnectSession() { 9082 try { 9083 /* Request lower layers to stop/abort and clear resources */ 9084 mService.stopDppSession(); 9085 } catch (RemoteException e) { 9086 throw e.rethrowFromSystemServer(); 9087 } 9088 } 9089 9090 /** 9091 * Helper class to support Easy Connect (DPP) callbacks 9092 * 9093 * @hide 9094 */ 9095 private static class EasyConnectCallbackProxy extends IDppCallback.Stub { 9096 private final Executor mExecutor; 9097 private final EasyConnectStatusCallback mEasyConnectStatusCallback; 9098 EasyConnectCallbackProxy(Executor executor, EasyConnectStatusCallback easyConnectStatusCallback)9099 EasyConnectCallbackProxy(Executor executor, 9100 EasyConnectStatusCallback easyConnectStatusCallback) { 9101 mExecutor = executor; 9102 mEasyConnectStatusCallback = easyConnectStatusCallback; 9103 } 9104 9105 @Override onSuccessConfigReceived(int newNetworkId)9106 public void onSuccessConfigReceived(int newNetworkId) { 9107 Log.d(TAG, "Easy Connect onSuccessConfigReceived callback"); 9108 Binder.clearCallingIdentity(); 9109 mExecutor.execute(() -> { 9110 mEasyConnectStatusCallback.onEnrolleeSuccess(newNetworkId); 9111 }); 9112 } 9113 9114 @Override onSuccess(int status)9115 public void onSuccess(int status) { 9116 Log.d(TAG, "Easy Connect onSuccess callback"); 9117 Binder.clearCallingIdentity(); 9118 mExecutor.execute(() -> { 9119 mEasyConnectStatusCallback.onConfiguratorSuccess(status); 9120 }); 9121 } 9122 9123 @Override onFailure(int status, String ssid, String channelList, int[] operatingClassArray)9124 public void onFailure(int status, String ssid, String channelList, 9125 int[] operatingClassArray) { 9126 Log.d(TAG, "Easy Connect onFailure callback"); 9127 Binder.clearCallingIdentity(); 9128 mExecutor.execute(() -> { 9129 SparseArray<int[]> channelListArray = parseDppChannelList(channelList); 9130 mEasyConnectStatusCallback.onFailure(status, ssid, channelListArray, 9131 operatingClassArray); 9132 }); 9133 } 9134 9135 @Override onProgress(int status)9136 public void onProgress(int status) { 9137 Log.d(TAG, "Easy Connect onProgress callback"); 9138 Binder.clearCallingIdentity(); 9139 mExecutor.execute(() -> { 9140 mEasyConnectStatusCallback.onProgress(status); 9141 }); 9142 } 9143 9144 @Override onBootstrapUriGenerated(@onNull String uri)9145 public void onBootstrapUriGenerated(@NonNull String uri) { 9146 Log.d(TAG, "Easy Connect onBootstrapUriGenerated callback"); 9147 if (!SdkLevel.isAtLeastS()) { 9148 Log.e(TAG, "Easy Connect bootstrap URI callback supported only on S+"); 9149 return; 9150 } 9151 Binder.clearCallingIdentity(); 9152 mExecutor.execute(() -> { 9153 mEasyConnectStatusCallback.onBootstrapUriGenerated(Uri.parse(uri)); 9154 }); 9155 } 9156 } 9157 9158 /** 9159 * Interface for Wi-Fi usability statistics listener. Should be implemented by applications and 9160 * set when calling {@link WifiManager#addOnWifiUsabilityStatsListener(Executor, 9161 * OnWifiUsabilityStatsListener)}. 9162 * 9163 * @hide 9164 */ 9165 @SystemApi 9166 public interface OnWifiUsabilityStatsListener { 9167 /** 9168 * Called when Wi-Fi usability statistics is updated. 9169 * 9170 * @param seqNum The sequence number of statistics, used to derive the timing of updated 9171 * Wi-Fi usability statistics, set by framework and incremented by one after 9172 * each update. 9173 * @param isSameBssidAndFreq The flag to indicate whether the BSSID and the frequency of 9174 * network stays the same or not relative to the last update of 9175 * Wi-Fi usability stats. 9176 * @param stats The updated Wi-Fi usability statistics. 9177 */ onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, @NonNull WifiUsabilityStatsEntry stats)9178 void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, 9179 @NonNull WifiUsabilityStatsEntry stats); 9180 } 9181 9182 /** 9183 * Interface for Wi-Fi verbose logging status listener. Should be implemented by applications 9184 * and set when calling {@link WifiManager#addWifiVerboseLoggingStatusListener(Executor, 9185 * WifiVerboseLoggingStatusListener)}. 9186 * 9187 * @hide 9188 */ 9189 @SystemApi 9190 public interface WifiVerboseLoggingStatusChangedListener { 9191 /** 9192 * Called when Wi-Fi verbose logging setting is updated. 9193 * 9194 * @param enabled true if verbose logging is enabled, false if verbose logging is disabled. 9195 */ onWifiVerboseLoggingStatusChanged(boolean enabled)9196 void onWifiVerboseLoggingStatusChanged(boolean enabled); 9197 } 9198 9199 /** 9200 * Adds a listener for Wi-Fi usability statistics. See {@link OnWifiUsabilityStatsListener}. 9201 * Multiple listeners can be added. Callers will be invoked periodically by framework to 9202 * inform clients about the current Wi-Fi usability statistics. Callers can remove a previously 9203 * added listener using 9204 * {@link #removeOnWifiUsabilityStatsListener(OnWifiUsabilityStatsListener)}. 9205 * 9206 * @param executor The executor on which callback will be invoked. 9207 * @param listener Listener for Wifi usability statistics. 9208 * 9209 * @hide 9210 */ 9211 @SystemApi 9212 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) addOnWifiUsabilityStatsListener(@onNull @allbackExecutor Executor executor, @NonNull OnWifiUsabilityStatsListener listener)9213 public void addOnWifiUsabilityStatsListener(@NonNull @CallbackExecutor Executor executor, 9214 @NonNull OnWifiUsabilityStatsListener listener) { 9215 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 9216 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 9217 if (mVerboseLoggingEnabled) { 9218 Log.v(TAG, "addOnWifiUsabilityStatsListener: listener=" + listener); 9219 } 9220 try { 9221 synchronized (sOnWifiUsabilityStatsListenerMap) { 9222 IOnWifiUsabilityStatsListener.Stub binderCallback = 9223 new IOnWifiUsabilityStatsListener.Stub() { 9224 @Override 9225 public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq, 9226 WifiUsabilityStatsEntry stats) { 9227 if (mVerboseLoggingEnabled) { 9228 Log.v(TAG, "OnWifiUsabilityStatsListener: " 9229 + "onWifiUsabilityStats: seqNum=" + seqNum); 9230 } 9231 Binder.clearCallingIdentity(); 9232 executor.execute(() -> listener.onWifiUsabilityStats( 9233 seqNum, isSameBssidAndFreq, stats)); 9234 } 9235 }; 9236 sOnWifiUsabilityStatsListenerMap.put(System.identityHashCode(listener), 9237 binderCallback); 9238 mService.addOnWifiUsabilityStatsListener(binderCallback); 9239 } 9240 } catch (RemoteException e) { 9241 throw e.rethrowFromSystemServer(); 9242 } 9243 } 9244 9245 /** 9246 * Allow callers to remove a previously registered listener. After calling this method, 9247 * applications will no longer receive Wi-Fi usability statistics. 9248 * 9249 * @param listener Listener to remove the Wi-Fi usability statistics. 9250 * 9251 * @hide 9252 */ 9253 @SystemApi 9254 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) removeOnWifiUsabilityStatsListener(@onNull OnWifiUsabilityStatsListener listener)9255 public void removeOnWifiUsabilityStatsListener(@NonNull OnWifiUsabilityStatsListener listener) { 9256 if (listener == null) throw new IllegalArgumentException("listener cannot be null"); 9257 if (mVerboseLoggingEnabled) { 9258 Log.v(TAG, "removeOnWifiUsabilityStatsListener: listener=" + listener); 9259 } 9260 try { 9261 synchronized (sOnWifiUsabilityStatsListenerMap) { 9262 int listenerIdentifier = System.identityHashCode(listener); 9263 if (!sOnWifiUsabilityStatsListenerMap.contains(listenerIdentifier)) { 9264 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 9265 return; 9266 } 9267 mService.removeOnWifiUsabilityStatsListener( 9268 sOnWifiUsabilityStatsListenerMap.get(listenerIdentifier)); 9269 sOnWifiUsabilityStatsListenerMap.remove(listenerIdentifier); 9270 } 9271 } catch (RemoteException e) { 9272 throw e.rethrowFromSystemServer(); 9273 } 9274 } 9275 9276 /** 9277 * Provide a Wi-Fi usability score information to be recorded (but not acted upon) by the 9278 * framework. The Wi-Fi usability score is derived from {@link OnWifiUsabilityStatsListener} 9279 * where a score is matched to Wi-Fi usability statistics using the sequence number. The score 9280 * is used to quantify whether Wi-Fi is usable in a future time. 9281 * 9282 * @param seqNum Sequence number of the Wi-Fi usability score. 9283 * @param score The Wi-Fi usability score, expected range: [0, 100]. 9284 * @param predictionHorizonSec Prediction horizon of the Wi-Fi usability score in second, 9285 * expected range: [0, 30]. 9286 * 9287 * @hide 9288 */ 9289 @SystemApi 9290 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec)9291 public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { 9292 try { 9293 mService.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec); 9294 } catch (RemoteException e) { 9295 throw e.rethrowFromSystemServer(); 9296 } 9297 } 9298 9299 /** 9300 * Abstract class for scan results callback. Should be extended by applications and set when 9301 * calling {@link WifiManager#registerScanResultsCallback(Executor, ScanResultsCallback)}. 9302 */ 9303 public abstract static class ScanResultsCallback { 9304 private final ScanResultsCallbackProxy mScanResultsCallbackProxy; 9305 ScanResultsCallback()9306 public ScanResultsCallback() { 9307 mScanResultsCallbackProxy = new ScanResultsCallbackProxy(); 9308 } 9309 9310 /** 9311 * Called when new scan results are available. 9312 * Clients should use {@link WifiManager#getScanResults()} to get the scan results. 9313 */ onScanResultsAvailable()9314 public abstract void onScanResultsAvailable(); 9315 getProxy()9316 /*package*/ @NonNull ScanResultsCallbackProxy getProxy() { 9317 return mScanResultsCallbackProxy; 9318 } 9319 9320 private static class ScanResultsCallbackProxy extends IScanResultsCallback.Stub { 9321 private final Object mLock = new Object(); 9322 @Nullable @GuardedBy("mLock") private Executor mExecutor; 9323 @Nullable @GuardedBy("mLock") private ScanResultsCallback mCallback; 9324 ScanResultsCallbackProxy()9325 ScanResultsCallbackProxy() { 9326 mCallback = null; 9327 mExecutor = null; 9328 } 9329 initProxy(@onNull Executor executor, @NonNull ScanResultsCallback callback)9330 /*package*/ void initProxy(@NonNull Executor executor, 9331 @NonNull ScanResultsCallback callback) { 9332 synchronized (mLock) { 9333 mExecutor = executor; 9334 mCallback = callback; 9335 } 9336 } 9337 cleanUpProxy()9338 /*package*/ void cleanUpProxy() { 9339 synchronized (mLock) { 9340 mExecutor = null; 9341 mCallback = null; 9342 } 9343 } 9344 9345 @Override onScanResultsAvailable()9346 public void onScanResultsAvailable() { 9347 ScanResultsCallback callback; 9348 Executor executor; 9349 synchronized (mLock) { 9350 executor = mExecutor; 9351 callback = mCallback; 9352 } 9353 if (callback == null || executor == null) { 9354 return; 9355 } 9356 Binder.clearCallingIdentity(); 9357 executor.execute(callback::onScanResultsAvailable); 9358 } 9359 } 9360 } 9361 9362 /** 9363 * Register a callback for Scan Results. See {@link ScanResultsCallback}. 9364 * Caller will receive the event when scan results are available. 9365 * Caller should use {@link WifiManager#getScanResults()} requires 9366 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} to get the scan results. 9367 * Caller can remove a previously registered callback using 9368 * {@link WifiManager#unregisterScanResultsCallback(ScanResultsCallback)} 9369 * Same caller can add multiple listeners. 9370 * <p> 9371 * Applications should have the 9372 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission. Callers 9373 * without the permission will trigger a {@link java.lang.SecurityException}. 9374 * <p> 9375 * 9376 * @param executor The executor to execute the callback of the {@code callback} object. 9377 * @param callback callback for Scan Results events 9378 */ 9379 9380 @RequiresPermission(ACCESS_WIFI_STATE) registerScanResultsCallback(@onNull @allbackExecutor Executor executor, @NonNull ScanResultsCallback callback)9381 public void registerScanResultsCallback(@NonNull @CallbackExecutor Executor executor, 9382 @NonNull ScanResultsCallback callback) { 9383 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 9384 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 9385 9386 Log.v(TAG, "registerScanResultsCallback: callback=" + callback 9387 + ", executor=" + executor); 9388 ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy(); 9389 proxy.initProxy(executor, callback); 9390 try { 9391 mService.registerScanResultsCallback(proxy); 9392 } catch (RemoteException e) { 9393 throw e.rethrowFromSystemServer(); 9394 } 9395 } 9396 9397 /** 9398 * Allow callers to unregister a previously registered callback. After calling this method, 9399 * applications will no longer receive Scan Results events. 9400 * 9401 * @param callback callback to unregister for Scan Results events 9402 */ 9403 @RequiresPermission(ACCESS_WIFI_STATE) unregisterScanResultsCallback(@onNull ScanResultsCallback callback)9404 public void unregisterScanResultsCallback(@NonNull ScanResultsCallback callback) { 9405 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 9406 Log.v(TAG, "unregisterScanResultsCallback: Callback=" + callback); 9407 ScanResultsCallback.ScanResultsCallbackProxy proxy = callback.getProxy(); 9408 try { 9409 mService.unregisterScanResultsCallback(proxy); 9410 } catch (RemoteException e) { 9411 throw e.rethrowFromSystemServer(); 9412 } finally { 9413 proxy.cleanUpProxy(); 9414 } 9415 } 9416 9417 /** 9418 * Interface for suggestion connection status listener. 9419 * Should be implemented by applications and set when calling 9420 * {@link WifiManager#addSuggestionConnectionStatusListener( 9421 * Executor, SuggestionConnectionStatusListener)}. 9422 */ 9423 public interface SuggestionConnectionStatusListener { 9424 9425 /** 9426 * Called when the framework attempted to connect to a suggestion provided by the 9427 * registering app, but the connection to the suggestion failed. 9428 * @param wifiNetworkSuggestion The suggestion which failed to connect. 9429 * @param failureReason the connection failure reason code. 9430 */ onConnectionStatus( @onNull WifiNetworkSuggestion wifiNetworkSuggestion, @SuggestionConnectionStatusCode int failureReason)9431 void onConnectionStatus( 9432 @NonNull WifiNetworkSuggestion wifiNetworkSuggestion, 9433 @SuggestionConnectionStatusCode int failureReason); 9434 } 9435 9436 private class SuggestionConnectionStatusListenerProxy extends 9437 ISuggestionConnectionStatusListener.Stub { 9438 private final Executor mExecutor; 9439 private final SuggestionConnectionStatusListener mListener; 9440 SuggestionConnectionStatusListenerProxy(@onNull Executor executor, @NonNull SuggestionConnectionStatusListener listener)9441 SuggestionConnectionStatusListenerProxy(@NonNull Executor executor, 9442 @NonNull SuggestionConnectionStatusListener listener) { 9443 mExecutor = executor; 9444 mListener = listener; 9445 } 9446 9447 @Override onConnectionStatus(@onNull WifiNetworkSuggestion wifiNetworkSuggestion, int failureReason)9448 public void onConnectionStatus(@NonNull WifiNetworkSuggestion wifiNetworkSuggestion, 9449 int failureReason) { 9450 Binder.clearCallingIdentity(); 9451 mExecutor.execute(() -> 9452 mListener.onConnectionStatus(wifiNetworkSuggestion, failureReason)); 9453 } 9454 9455 } 9456 9457 /** 9458 * Interface for local-only connection failure listener. 9459 * Should be implemented by applications and set when calling 9460 * {@link WifiManager#addLocalOnlyConnectionFailureListener(Executor, LocalOnlyConnectionFailureListener)} 9461 */ 9462 public interface LocalOnlyConnectionFailureListener { 9463 9464 /** 9465 * Called when the framework attempted to connect to a local-only network requested by the 9466 * registering app, but the connection to the network failed. 9467 * @param wifiNetworkSpecifier The {@link WifiNetworkSpecifier} which failed to connect. 9468 * @param failureReason the connection failure reason code. 9469 */ onConnectionFailed( @onNull WifiNetworkSpecifier wifiNetworkSpecifier, @LocalOnlyConnectionStatusCode int failureReason)9470 void onConnectionFailed( 9471 @NonNull WifiNetworkSpecifier wifiNetworkSpecifier, 9472 @LocalOnlyConnectionStatusCode int failureReason); 9473 } 9474 9475 private static class LocalOnlyConnectionStatusListenerProxy extends 9476 ILocalOnlyConnectionStatusListener.Stub { 9477 private final Executor mExecutor; 9478 private final LocalOnlyConnectionFailureListener mListener; 9479 LocalOnlyConnectionStatusListenerProxy(@onNull Executor executor, @NonNull LocalOnlyConnectionFailureListener listener)9480 LocalOnlyConnectionStatusListenerProxy(@NonNull Executor executor, 9481 @NonNull LocalOnlyConnectionFailureListener listener) { 9482 mExecutor = executor; 9483 mListener = listener; 9484 } 9485 9486 @Override onConnectionStatus(@onNull WifiNetworkSpecifier networkSpecifier, int failureReason)9487 public void onConnectionStatus(@NonNull WifiNetworkSpecifier networkSpecifier, 9488 int failureReason) { 9489 Binder.clearCallingIdentity(); 9490 mExecutor.execute(() -> 9491 mListener.onConnectionFailed(networkSpecifier, failureReason)); 9492 } 9493 9494 } 9495 9496 /** 9497 * Add a listener listening to wifi verbose logging changes. 9498 * See {@link WifiVerboseLoggingStatusChangedListener}. 9499 * Caller can remove a previously registered listener using 9500 * {@link WifiManager#removeWifiVerboseLoggingStatusChangedListener( 9501 * WifiVerboseLoggingStatusChangedListener)} 9502 * Same caller can add multiple listeners to monitor the event. 9503 * <p> 9504 * Applications should have the 9505 * {@link android.Manifest.permission#ACCESS_WIFI_STATE}. 9506 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 9507 * <p> 9508 * @param executor The executor to execute the listener of the {@code listener} object. 9509 * @param listener listener for changes in wifi verbose logging. 9510 * 9511 * @hide 9512 */ 9513 @SystemApi 9514 @RequiresPermission(ACCESS_WIFI_STATE) addWifiVerboseLoggingStatusChangedListener( @onNull @allbackExecutor Executor executor, @NonNull WifiVerboseLoggingStatusChangedListener listener)9515 public void addWifiVerboseLoggingStatusChangedListener( 9516 @NonNull @CallbackExecutor Executor executor, 9517 @NonNull WifiVerboseLoggingStatusChangedListener listener) { 9518 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9519 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 9520 if (mVerboseLoggingEnabled) { 9521 Log.v(TAG, "addWifiVerboseLoggingStatusChangedListener listener=" + listener 9522 + ", executor=" + executor); 9523 } 9524 try { 9525 synchronized (sWifiVerboseLoggingStatusChangedListenerMap) { 9526 IWifiVerboseLoggingStatusChangedListener.Stub binderCallback = 9527 new IWifiVerboseLoggingStatusChangedListener.Stub() { 9528 @Override 9529 public void onStatusChanged(boolean enabled) { 9530 if (mVerboseLoggingEnabled) { 9531 Log.v(TAG, "WifiVerboseLoggingStatusListener: " 9532 + "onVerboseLoggingStatusChanged: enabled=" + enabled); 9533 } 9534 Binder.clearCallingIdentity(); 9535 executor.execute(() -> listener.onWifiVerboseLoggingStatusChanged( 9536 enabled)); 9537 } 9538 }; 9539 sWifiVerboseLoggingStatusChangedListenerMap.put(System.identityHashCode(listener), 9540 binderCallback); 9541 mService.addWifiVerboseLoggingStatusChangedListener(binderCallback); 9542 } 9543 } catch (RemoteException e) { 9544 throw e.rethrowFromSystemServer(); 9545 } 9546 } 9547 9548 /** 9549 * Allow callers to remove a previously registered listener. 9550 * <p> 9551 * Applications should have the 9552 * {@link android.Manifest.permission#ACCESS_WIFI_STATE}. 9553 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 9554 * <p> 9555 * @param listener listener to remove. 9556 * 9557 * @hide 9558 */ 9559 @SystemApi 9560 @RequiresPermission(ACCESS_WIFI_STATE) removeWifiVerboseLoggingStatusChangedListener( @onNull WifiVerboseLoggingStatusChangedListener listener)9561 public void removeWifiVerboseLoggingStatusChangedListener( 9562 @NonNull WifiVerboseLoggingStatusChangedListener listener) { 9563 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9564 Log.v(TAG, "removeWifiVerboseLoggingStatusChangedListener: listener=" + listener); 9565 try { 9566 synchronized (sWifiVerboseLoggingStatusChangedListenerMap) { 9567 int listenerIdentifier = System.identityHashCode(listener); 9568 if (!sWifiVerboseLoggingStatusChangedListenerMap.contains(listenerIdentifier)) { 9569 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 9570 return; 9571 } 9572 mService.removeWifiVerboseLoggingStatusChangedListener( 9573 sWifiVerboseLoggingStatusChangedListenerMap.get(listenerIdentifier)); 9574 sWifiVerboseLoggingStatusChangedListenerMap.remove(listenerIdentifier); 9575 } 9576 } catch (RemoteException e) { 9577 throw e.rethrowFromSystemServer(); 9578 } 9579 } 9580 9581 /** 9582 * Add a listener for suggestion networks. See {@link SuggestionConnectionStatusListener}. 9583 * Caller will receive the event when suggested network have connection failure. 9584 * Caller can remove a previously registered listener using 9585 * {@link WifiManager#removeSuggestionConnectionStatusListener( 9586 * SuggestionConnectionStatusListener)} 9587 * Same caller can add multiple listeners to monitor the event. 9588 * <p> 9589 * Applications should have the 9590 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and 9591 * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permissions. 9592 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 9593 * <p> 9594 * 9595 * @param executor The executor to execute the listener of the {@code listener} object. 9596 * @param listener listener for suggestion network connection failure. 9597 */ 9598 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE}) addSuggestionConnectionStatusListener(@onNull @allbackExecutor Executor executor, @NonNull SuggestionConnectionStatusListener listener)9599 public void addSuggestionConnectionStatusListener(@NonNull @CallbackExecutor Executor executor, 9600 @NonNull SuggestionConnectionStatusListener listener) { 9601 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9602 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 9603 Log.v(TAG, "addSuggestionConnectionStatusListener listener=" + listener 9604 + ", executor=" + executor); 9605 try { 9606 synchronized (sSuggestionConnectionStatusListenerMap) { 9607 ISuggestionConnectionStatusListener.Stub binderCallback = 9608 new SuggestionConnectionStatusListenerProxy(executor, listener); 9609 sSuggestionConnectionStatusListenerMap.put(System.identityHashCode(listener), 9610 binderCallback); 9611 mService.registerSuggestionConnectionStatusListener(binderCallback, 9612 mContext.getOpPackageName(), mContext.getAttributionTag()); 9613 } 9614 } catch (RemoteException e) { 9615 throw e.rethrowFromSystemServer(); 9616 } 9617 9618 } 9619 9620 /** 9621 * Allow callers to remove a previously registered listener. After calling this method, 9622 * applications will no longer receive suggestion connection events through that listener. 9623 * 9624 * @param listener listener to remove. 9625 */ 9626 @RequiresPermission(ACCESS_WIFI_STATE) removeSuggestionConnectionStatusListener( @onNull SuggestionConnectionStatusListener listener)9627 public void removeSuggestionConnectionStatusListener( 9628 @NonNull SuggestionConnectionStatusListener listener) { 9629 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9630 Log.v(TAG, "removeSuggestionConnectionStatusListener: listener=" + listener); 9631 try { 9632 synchronized (sSuggestionConnectionStatusListenerMap) { 9633 int listenerIdentifier = System.identityHashCode(listener); 9634 if (!sSuggestionConnectionStatusListenerMap.contains(listenerIdentifier)) { 9635 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 9636 return; 9637 } 9638 mService.unregisterSuggestionConnectionStatusListener( 9639 sSuggestionConnectionStatusListenerMap.get(listenerIdentifier), 9640 mContext.getOpPackageName()); 9641 sSuggestionConnectionStatusListenerMap.remove(listenerIdentifier); 9642 } 9643 } catch (RemoteException e) { 9644 throw e.rethrowFromSystemServer(); 9645 } 9646 } 9647 9648 /** 9649 * Add a listener for local-only networks. See {@link WifiNetworkSpecifier}. 9650 * Specify the caller will only get connection failures for networks they requested. 9651 * Caller can remove a previously registered listener using 9652 * {@link WifiManager#removeLocalOnlyConnectionFailureListener(LocalOnlyConnectionFailureListener)} 9653 * Same caller can add multiple listeners to monitor the event. 9654 * <p> 9655 * Applications should have the {@link android.Manifest.permission#ACCESS_WIFI_STATE} 9656 * permissions. 9657 * Callers without the permission will trigger a {@link java.lang.SecurityException}. 9658 * <p> 9659 * 9660 * @param executor The executor to execute the listener of the {@code listener} object. 9661 * @param listener listener for local-only network connection failure. 9662 */ 9663 @RequiresPermission(ACCESS_WIFI_STATE) addLocalOnlyConnectionFailureListener(@onNull @allbackExecutor Executor executor, @NonNull LocalOnlyConnectionFailureListener listener)9664 public void addLocalOnlyConnectionFailureListener(@NonNull @CallbackExecutor Executor executor, 9665 @NonNull LocalOnlyConnectionFailureListener listener) { 9666 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9667 if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); 9668 try { 9669 synchronized (sLocalOnlyConnectionStatusListenerMap) { 9670 if (sLocalOnlyConnectionStatusListenerMap 9671 .contains(System.identityHashCode(listener))) { 9672 Log.w(TAG, "Same listener already registered"); 9673 return; 9674 } 9675 ILocalOnlyConnectionStatusListener.Stub binderCallback = 9676 new LocalOnlyConnectionStatusListenerProxy(executor, listener); 9677 sLocalOnlyConnectionStatusListenerMap.put(System.identityHashCode(listener), 9678 binderCallback); 9679 mService.addLocalOnlyConnectionStatusListener(binderCallback, 9680 mContext.getOpPackageName(), mContext.getAttributionTag()); 9681 } 9682 } catch (RemoteException e) { 9683 throw e.rethrowFromSystemServer(); 9684 } 9685 } 9686 9687 /** 9688 * Allow callers to remove a previously registered listener. After calling this method, 9689 * applications will no longer receive local-only connection events through that listener. 9690 * 9691 * @param listener listener to remove. 9692 */ 9693 @RequiresPermission(ACCESS_WIFI_STATE) removeLocalOnlyConnectionFailureListener( @onNull LocalOnlyConnectionFailureListener listener)9694 public void removeLocalOnlyConnectionFailureListener( 9695 @NonNull LocalOnlyConnectionFailureListener listener) { 9696 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 9697 try { 9698 synchronized (sLocalOnlyConnectionStatusListenerMap) { 9699 int listenerIdentifier = System.identityHashCode(listener); 9700 if (!sLocalOnlyConnectionStatusListenerMap.contains(listenerIdentifier)) { 9701 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 9702 return; 9703 } 9704 mService.removeLocalOnlyConnectionStatusListener( 9705 sLocalOnlyConnectionStatusListenerMap.get(listenerIdentifier), 9706 mContext.getOpPackageName()); 9707 sLocalOnlyConnectionStatusListenerMap.remove(listenerIdentifier); 9708 } 9709 } catch (RemoteException e) { 9710 throw e.rethrowFromSystemServer(); 9711 } 9712 } 9713 9714 /** 9715 * Parse the list of channels the DPP enrollee reports when it fails to find an AP. 9716 * 9717 * @param channelList List of channels in the format defined in the DPP specification. 9718 * @return A parsed sparse array, where the operating class is the key. 9719 * @hide 9720 */ 9721 @VisibleForTesting parseDppChannelList(String channelList)9722 public static SparseArray<int[]> parseDppChannelList(String channelList) { 9723 SparseArray<int[]> channelListArray = new SparseArray<>(); 9724 9725 if (TextUtils.isEmpty(channelList)) { 9726 return channelListArray; 9727 } 9728 StringTokenizer str = new StringTokenizer(channelList, ","); 9729 String classStr = null; 9730 List<Integer> channelsInClass = new ArrayList<>(); 9731 9732 try { 9733 while (str.hasMoreElements()) { 9734 String cur = str.nextToken(); 9735 9736 /** 9737 * Example for a channel list: 9738 * 9739 * 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, 9740 * 116,120,124,128,132,136,140,0/144,124/149,153,157,161,125/165 9741 * 9742 * Detect operating class by the delimiter of '/' and use a string tokenizer with 9743 * ',' as a delimiter. 9744 */ 9745 int classDelim = cur.indexOf('/'); 9746 if (classDelim != -1) { 9747 if (classStr != null) { 9748 // Store the last channel array in the sparse array, where the operating 9749 // class is the key (as an integer). 9750 int[] channelsArray = new int[channelsInClass.size()]; 9751 for (int i = 0; i < channelsInClass.size(); i++) { 9752 channelsArray[i] = channelsInClass.get(i); 9753 } 9754 channelListArray.append(Integer.parseInt(classStr), channelsArray); 9755 channelsInClass = new ArrayList<>(); 9756 } 9757 9758 // Init a new operating class and store the first channel 9759 classStr = cur.substring(0, classDelim); 9760 String channelStr = cur.substring(classDelim + 1); 9761 channelsInClass.add(Integer.parseInt(channelStr)); 9762 } else { 9763 if (classStr == null) { 9764 // Invalid format 9765 Log.e(TAG, "Cannot parse DPP channel list"); 9766 return new SparseArray<>(); 9767 } 9768 channelsInClass.add(Integer.parseInt(cur)); 9769 } 9770 } 9771 9772 // Store the last array 9773 if (classStr != null) { 9774 int[] channelsArray = new int[channelsInClass.size()]; 9775 for (int i = 0; i < channelsInClass.size(); i++) { 9776 channelsArray[i] = channelsInClass.get(i); 9777 } 9778 channelListArray.append(Integer.parseInt(classStr), channelsArray); 9779 } 9780 return channelListArray; 9781 } catch (NumberFormatException e) { 9782 Log.e(TAG, "Cannot parse DPP channel list"); 9783 return new SparseArray<>(); 9784 } 9785 } 9786 9787 /** 9788 * Callback interface for framework to receive network status updates and trigger of updating 9789 * {@link WifiUsabilityStatsEntry}. 9790 * 9791 * @hide 9792 */ 9793 @SystemApi 9794 public interface ScoreUpdateObserver { 9795 /** 9796 * Called by applications to indicate network status. For applications targeting 9797 * {@link android.os.Build.VERSION_CODES#S} or above: The score is not used to take action 9798 * on network selection but for the purpose of Wifi metric collection only; Network 9799 * selection is influenced by inputs from 9800 * {@link ScoreUpdateObserver#notifyStatusUpdate(int, boolean)}, 9801 * {@link ScoreUpdateObserver#requestNudOperation(int, boolean)}, and 9802 * {@link ScoreUpdateObserver#blocklistCurrentBssid(int)}. 9803 * 9804 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 9805 * {@link WifiConnectedNetworkScorer#onStart(int)}. 9806 * @param score The score representing link quality of current Wi-Fi network connection. 9807 * Populated by connected network scorer in applications.. 9808 */ notifyScoreUpdate(int sessionId, int score)9809 void notifyScoreUpdate(int sessionId, int score); 9810 9811 /** 9812 * Called by applications to trigger an update of {@link WifiUsabilityStatsEntry}. 9813 * To receive update applications need to add WifiUsabilityStatsEntry listener. See 9814 * {@link addOnWifiUsabilityStatsListener(Executor, OnWifiUsabilityStatsListener)}. 9815 * 9816 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 9817 * {@link WifiConnectedNetworkScorer#onStart(int)}. 9818 */ triggerUpdateOfWifiUsabilityStats(int sessionId)9819 void triggerUpdateOfWifiUsabilityStats(int sessionId); 9820 9821 /** 9822 * Called by applications to indicate whether current Wi-Fi network is usable or not. 9823 * 9824 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 9825 * {@link WifiConnectedNetworkScorer#onStart(int)}. 9826 * @param isUsable The boolean representing whether current Wi-Fi network is usable, and it 9827 * may be sent to ConnectivityService and used for setting default network. 9828 * Populated by connected network scorer in applications. 9829 */ 9830 @RequiresApi(Build.VERSION_CODES.S) notifyStatusUpdate(int sessionId, boolean isUsable)9831 default void notifyStatusUpdate(int sessionId, boolean isUsable) {} 9832 9833 /** 9834 * Called by applications to start a NUD (Neighbor Unreachability Detection) operation. The 9835 * framework throttles NUD operations to no more frequently than every five seconds 9836 * (see {@link WifiScoreReport#NUD_THROTTLE_MILLIS}). The framework keeps track of requests 9837 * and executes them as soon as possible based on the throttling criteria. 9838 * 9839 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 9840 * {@link WifiConnectedNetworkScorer#onStart(int)}. 9841 */ 9842 @RequiresApi(Build.VERSION_CODES.S) requestNudOperation(int sessionId)9843 default void requestNudOperation(int sessionId) {} 9844 9845 /** 9846 * Called by applications to blocklist currently connected BSSID. No blocklisting operation 9847 * if called after disconnection. 9848 * 9849 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 9850 * {@link WifiConnectedNetworkScorer#onStart(int)}. 9851 */ 9852 @RequiresApi(Build.VERSION_CODES.S) blocklistCurrentBssid(int sessionId)9853 default void blocklistCurrentBssid(int sessionId) {} 9854 } 9855 9856 /** 9857 * Callback proxy for {@link ScoreUpdateObserver} objects. 9858 * 9859 * @hide 9860 */ 9861 private class ScoreUpdateObserverProxy implements ScoreUpdateObserver { 9862 private final IScoreUpdateObserver mScoreUpdateObserver; 9863 ScoreUpdateObserverProxy(IScoreUpdateObserver observer)9864 private ScoreUpdateObserverProxy(IScoreUpdateObserver observer) { 9865 mScoreUpdateObserver = observer; 9866 } 9867 9868 @Override notifyScoreUpdate(int sessionId, int score)9869 public void notifyScoreUpdate(int sessionId, int score) { 9870 try { 9871 mScoreUpdateObserver.notifyScoreUpdate(sessionId, score); 9872 } catch (RemoteException e) { 9873 throw e.rethrowFromSystemServer(); 9874 } 9875 } 9876 9877 @Override triggerUpdateOfWifiUsabilityStats(int sessionId)9878 public void triggerUpdateOfWifiUsabilityStats(int sessionId) { 9879 try { 9880 mScoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(sessionId); 9881 } catch (RemoteException e) { 9882 throw e.rethrowFromSystemServer(); 9883 } 9884 } 9885 9886 @Override notifyStatusUpdate(int sessionId, boolean isUsable)9887 public void notifyStatusUpdate(int sessionId, boolean isUsable) { 9888 if (!SdkLevel.isAtLeastS()) { 9889 throw new UnsupportedOperationException(); 9890 } 9891 try { 9892 mScoreUpdateObserver.notifyStatusUpdate(sessionId, isUsable); 9893 } catch (RemoteException e) { 9894 throw e.rethrowFromSystemServer(); 9895 } 9896 } 9897 9898 @Override requestNudOperation(int sessionId)9899 public void requestNudOperation(int sessionId) { 9900 if (!SdkLevel.isAtLeastS()) { 9901 throw new UnsupportedOperationException(); 9902 } 9903 try { 9904 mScoreUpdateObserver.requestNudOperation(sessionId); 9905 } catch (RemoteException e) { 9906 throw e.rethrowFromSystemServer(); 9907 } 9908 } 9909 9910 @Override blocklistCurrentBssid(int sessionId)9911 public void blocklistCurrentBssid(int sessionId) { 9912 if (!SdkLevel.isAtLeastS()) { 9913 throw new UnsupportedOperationException(); 9914 } 9915 try { 9916 mScoreUpdateObserver.blocklistCurrentBssid(sessionId); 9917 } catch (RemoteException e) { 9918 throw e.rethrowFromSystemServer(); 9919 } 9920 } 9921 } 9922 9923 /** 9924 * Interface for Wi-Fi connected network scorer. Should be implemented by applications and set 9925 * when calling 9926 * {@link WifiManager#setWifiConnectedNetworkScorer(Executor, WifiConnectedNetworkScorer)}. 9927 * 9928 * @hide 9929 */ 9930 @SystemApi 9931 public interface WifiConnectedNetworkScorer { 9932 /** 9933 * Called by framework to indicate the start of a network connection. 9934 * @param sessionId The ID to indicate current Wi-Fi network connection. 9935 * @deprecated This API is deprecated. Please use 9936 * {@link WifiConnectedNetworkScorer#onStart(WifiConnectedSessionInfo)}. 9937 */ 9938 @Deprecated onStart(int sessionId)9939 default void onStart(int sessionId) {} 9940 9941 /** 9942 * Called by framework to indicate the start of a network connection. 9943 * @param sessionInfo The session information to indicate current Wi-Fi network connection. 9944 * See {@link WifiConnectedSessionInfo}. 9945 */ onStart(@onNull WifiConnectedSessionInfo sessionInfo)9946 default void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) { 9947 onStart(sessionInfo.getSessionId()); 9948 } 9949 9950 /** 9951 * Called by framework to indicate the end of a network connection. 9952 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 9953 * {@link WifiConnectedNetworkScorer#onStart(int)}. 9954 */ onStop(int sessionId)9955 void onStop(int sessionId); 9956 9957 /** 9958 * Framework sets callback for score change events after application sets its scorer. 9959 * @param observerImpl The instance for {@link WifiManager#ScoreUpdateObserver}. Should be 9960 * implemented and instantiated by framework. 9961 */ onSetScoreUpdateObserver(@onNull ScoreUpdateObserver observerImpl)9962 void onSetScoreUpdateObserver(@NonNull ScoreUpdateObserver observerImpl); 9963 9964 /** 9965 * Called by framework to indicate the user accepted a dialog to switch to a new network. 9966 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 9967 * {@link WifiConnectedNetworkScorer#onStart(int)}. 9968 * @param targetNetworkId Network ID of the target network. 9969 * @param targetBssid BSSID of the target network. 9970 */ onNetworkSwitchAccepted( int sessionId, int targetNetworkId, @NonNull String targetBssid)9971 default void onNetworkSwitchAccepted( 9972 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 9973 // No-op. 9974 } 9975 9976 /** 9977 * Called by framework to indicate the user rejected a dialog to switch to new network. 9978 * @param sessionId The ID to indicate current Wi-Fi network connection obtained from 9979 * {@link WifiConnectedNetworkScorer#onStart(int)}. 9980 * @param targetNetworkId Network ID of the target network. 9981 * @param targetBssid BSSID of the target network. 9982 */ onNetworkSwitchRejected( int sessionId, int targetNetworkId, @NonNull String targetBssid)9983 default void onNetworkSwitchRejected( 9984 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 9985 // No-op. 9986 } 9987 } 9988 9989 9990 /** 9991 * Callback registered with {@link WifiManager#setExternalPnoScanRequest(List, int[], Executor, 9992 * PnoScanResultsCallback)}. Returns status and result information on offloaded external PNO 9993 * requests. 9994 * @hide 9995 */ 9996 @SystemApi 9997 public interface PnoScanResultsCallback { 9998 /** 9999 * A status code returned by {@link #onRegisterFailed(int)}. 10000 * Unknown failure. 10001 */ 10002 int REGISTER_PNO_CALLBACK_UNKNOWN = 0; 10003 10004 /** 10005 * A status code returned by {@link #onRegisterFailed(int)}. 10006 * A callback has already been registered by the caller. 10007 */ 10008 int REGISTER_PNO_CALLBACK_ALREADY_REGISTERED = 1; 10009 10010 /** 10011 * A status code returned by {@link #onRegisterFailed(int)}. 10012 * The platform is unable to serve this request because another app has a PNO scan request 10013 * active. 10014 */ 10015 int REGISTER_PNO_CALLBACK_RESOURCE_BUSY = 2; 10016 10017 /** 10018 * A status code returned by {@link #onRegisterFailed(int)}. 10019 * PNO scans are not supported on this device. 10020 */ 10021 int REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED = 3; 10022 10023 /** @hide */ 10024 @IntDef(prefix = { "REGISTER_PNO_CALLBACK_" }, value = { 10025 REGISTER_PNO_CALLBACK_UNKNOWN, 10026 REGISTER_PNO_CALLBACK_ALREADY_REGISTERED, 10027 REGISTER_PNO_CALLBACK_RESOURCE_BUSY, 10028 REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED 10029 }) 10030 @Retention(RetentionPolicy.SOURCE) 10031 public @interface RegisterFailureReason {} 10032 10033 /** 10034 * A status code returned by {@link #onRemoved(int)}. 10035 * Unknown reason. 10036 */ 10037 int REMOVE_PNO_CALLBACK_UNKNOWN = 0; 10038 10039 /** 10040 * A status code returned by {@link #onRemoved(int)}. 10041 * This Callback is automatically removed after results ScanResults are delivered. 10042 */ 10043 int REMOVE_PNO_CALLBACK_RESULTS_DELIVERED = 1; 10044 10045 /** 10046 * A status code returned by {@link #onRemoved(int)}. 10047 * This callback has been unregistered via {@link WifiManager#clearExternalPnoScanRequest()} 10048 */ 10049 int REMOVE_PNO_CALLBACK_UNREGISTERED = 2; 10050 10051 /** @hide */ 10052 @IntDef(prefix = { "REMOVE_PNO_CALLBACK_" }, value = { 10053 REMOVE_PNO_CALLBACK_UNKNOWN, 10054 REMOVE_PNO_CALLBACK_RESULTS_DELIVERED, 10055 REMOVE_PNO_CALLBACK_UNREGISTERED 10056 }) 10057 @Retention(RetentionPolicy.SOURCE) 10058 public @interface RemovalReason {} 10059 10060 /** 10061 * Called when PNO scan finds one of the requested SSIDs. This is a one time callback. 10062 * After results are reported the callback will be automatically unregistered. 10063 */ onScanResultsAvailable(@onNull List<ScanResult> scanResults)10064 void onScanResultsAvailable(@NonNull List<ScanResult> scanResults); 10065 10066 /** 10067 * Called when this callback has been successfully registered. 10068 */ onRegisterSuccess()10069 void onRegisterSuccess(); 10070 10071 /** 10072 * Called when this callback failed to register with the failure reason. 10073 * See {@link RegisterFailureReason} for details. 10074 */ onRegisterFailed(@egisterFailureReason int reason)10075 void onRegisterFailed(@RegisterFailureReason int reason); 10076 10077 /** 10078 * Called when this callback has been unregistered from the Wi-Fi subsystem. 10079 * See {@link RemovalReason} for details. 10080 */ onRemoved(@emovalReason int reason)10081 void onRemoved(@RemovalReason int reason); 10082 } 10083 10084 10085 private class PnoScanResultsCallbackProxy extends IPnoScanResultsCallback.Stub { 10086 private Executor mExecutor; 10087 private PnoScanResultsCallback mCallback; 10088 PnoScanResultsCallbackProxy(@onNull Executor executor, @NonNull PnoScanResultsCallback callback)10089 PnoScanResultsCallbackProxy(@NonNull Executor executor, 10090 @NonNull PnoScanResultsCallback callback) { 10091 mExecutor = executor; 10092 mCallback = callback; 10093 } 10094 10095 @Override onScanResultsAvailable(List<ScanResult> scanResults)10096 public void onScanResultsAvailable(List<ScanResult> scanResults) { 10097 if (mVerboseLoggingEnabled) { 10098 Log.v(TAG, "PnoScanResultsCallback: " + "onScanResultsAvailable"); 10099 } 10100 Binder.clearCallingIdentity(); 10101 mExecutor.execute(() -> mCallback.onScanResultsAvailable(scanResults)); 10102 } 10103 10104 @Override onRegisterSuccess()10105 public void onRegisterSuccess() { 10106 if (mVerboseLoggingEnabled) { 10107 Log.v(TAG, "PnoScanResultsCallback: " + "onRegisterSuccess"); 10108 } 10109 Binder.clearCallingIdentity(); 10110 mExecutor.execute(() -> mCallback.onRegisterSuccess()); 10111 } 10112 10113 @Override onRegisterFailed(int reason)10114 public void onRegisterFailed(int reason) { 10115 if (mVerboseLoggingEnabled) { 10116 Log.v(TAG, "PnoScanResultsCallback: " + "onRegisterFailed " + reason); 10117 } 10118 Binder.clearCallingIdentity(); 10119 mExecutor.execute(() -> mCallback.onRegisterFailed(reason)); 10120 } 10121 10122 @Override onRemoved(int reason)10123 public void onRemoved(int reason) { 10124 if (mVerboseLoggingEnabled) { 10125 Log.v(TAG, "PnoScanResultsCallback: " + "onRemoved"); 10126 } 10127 Binder.clearCallingIdentity(); 10128 mExecutor.execute(() -> mCallback.onRemoved(reason)); 10129 } 10130 } 10131 10132 /** 10133 * Callback proxy for {@link WifiConnectedNetworkScorer} objects. 10134 * 10135 * @hide 10136 */ 10137 private class WifiConnectedNetworkScorerProxy extends IWifiConnectedNetworkScorer.Stub { 10138 private Executor mExecutor; 10139 private WifiConnectedNetworkScorer mScorer; 10140 WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer)10141 WifiConnectedNetworkScorerProxy(Executor executor, WifiConnectedNetworkScorer scorer) { 10142 mExecutor = executor; 10143 mScorer = scorer; 10144 } 10145 10146 @Override onStart(@onNull WifiConnectedSessionInfo sessionInfo)10147 public void onStart(@NonNull WifiConnectedSessionInfo sessionInfo) { 10148 if (mVerboseLoggingEnabled) { 10149 Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStart: sessionInfo=" + sessionInfo); 10150 } 10151 Binder.clearCallingIdentity(); 10152 mExecutor.execute(() -> mScorer.onStart(sessionInfo)); 10153 } 10154 10155 @Override onStop(int sessionId)10156 public void onStop(int sessionId) { 10157 if (mVerboseLoggingEnabled) { 10158 Log.v(TAG, "WifiConnectedNetworkScorer: " + "onStop: sessionId=" + sessionId); 10159 } 10160 Binder.clearCallingIdentity(); 10161 mExecutor.execute(() -> mScorer.onStop(sessionId)); 10162 } 10163 10164 @Override onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl)10165 public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) { 10166 if (mVerboseLoggingEnabled) { 10167 Log.v(TAG, "WifiConnectedNetworkScorer: " 10168 + "onSetScoreUpdateObserver: observerImpl=" + observerImpl); 10169 } 10170 Binder.clearCallingIdentity(); 10171 mExecutor.execute(() -> mScorer.onSetScoreUpdateObserver( 10172 new ScoreUpdateObserverProxy(observerImpl))); 10173 } 10174 10175 @Override onNetworkSwitchAccepted( int sessionId, int targetNetworkId, @NonNull String targetBssid)10176 public void onNetworkSwitchAccepted( 10177 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10178 if (mVerboseLoggingEnabled) { 10179 Log.v(TAG, "WifiConnectedNetworkScorer: onNetworkSwitchAccepted:" 10180 + " sessionId=" + sessionId 10181 + " targetNetworkId=" + targetNetworkId 10182 + " targetBssid=" + targetBssid); 10183 } 10184 Binder.clearCallingIdentity(); 10185 mExecutor.execute(() -> mScorer.onNetworkSwitchAccepted( 10186 sessionId, targetNetworkId, targetBssid)); 10187 } 10188 @Override onNetworkSwitchRejected( int sessionId, int targetNetworkId, @NonNull String targetBssid)10189 public void onNetworkSwitchRejected( 10190 int sessionId, int targetNetworkId, @NonNull String targetBssid) { 10191 if (mVerboseLoggingEnabled) { 10192 Log.v(TAG, "WifiConnectedNetworkScorer: onNetworkSwitchRejected:" 10193 + " sessionId=" + sessionId 10194 + " targetNetworkId=" + targetNetworkId 10195 + " targetBssid=" + targetBssid); 10196 } 10197 Binder.clearCallingIdentity(); 10198 mExecutor.execute(() -> mScorer.onNetworkSwitchRejected( 10199 sessionId, targetNetworkId, targetBssid)); 10200 } 10201 } 10202 10203 /** 10204 * This API allows the caller to program up to 2 SSIDs for PNO scans. PNO scans are offloaded 10205 * to the Wi-Fi chip when the device is inactive (typically screen-off). 10206 * If the screen is currently off when this API is called, then a PNO scan including the 10207 * requested SSIDs will immediately get started. If the screen is on when this API is called, 10208 * the requested SSIDs will get included for PNO scans the next time the screen turns off. 10209 * <p> 10210 * Note, due to PNO being a limited resource, only one external PNO request is supported, and 10211 * calling this API will fail if an external PNO scan request is already registered by another 10212 * caller. If the caller that has already registered a callback calls this API again, the new 10213 * callback will override the previous one. 10214 * <p> 10215 * After this API is called, {@link PnoScanResultsCallback#onRegisterSuccess()} will be invoked 10216 * if the operation is successful, or {@link PnoScanResultsCallback#onRegisterFailed(int)} will 10217 * be invoked if the operation failed. 10218 * <p> 10219 * {@link PnoScanResultsCallback#onRemoved(int)} will be invoked to notify the caller when the 10220 * external PNO scan request is removed, which will happen when one of the following events 10221 * happen: 10222 * </p> 10223 * <ul> 10224 * <li>Upon finding any of the requested SSIDs through either a connectivity scan or PNO scan, 10225 * the matching ScanResults will be returned 10226 * via {@link PnoScanResultsCallback#onScanResultsAvailable(List)}, and the registered PNO 10227 * scan request will get automatically removed.</li> 10228 * <li>The external PNO scan request is removed by a call to 10229 * {@link #clearExternalPnoScanRequest()}</li> 10230 * </ul> 10231 * 10232 * @param ssids The list of SSIDs to request for PNO scan. 10233 * @param frequencies Provide as hint a list of up to 10 frequencies to be used for PNO scan. 10234 * Each frequency should be in MHz. For example 2412 and 5180 are valid 10235 * frequencies. {@link WifiInfo#getFrequency()} is a location where this 10236 * information could be obtained. If a null or empty array is provided, the 10237 * Wi-Fi framework will automatically decide the list of frequencies to scan. 10238 * @param executor The executor on which callback will be invoked. 10239 * @param callback For the calling application to receive results and status updates. 10240 * 10241 * @throws SecurityException if the caller does not have permission. 10242 * @throws IllegalArgumentException if the caller provided invalid inputs. 10243 * @throws UnsupportedOperationException if this API is not supported on this SDK version. 10244 * @hide 10245 */ 10246 @SystemApi 10247 @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, 10248 REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}) 10249 @RequiresApi(Build.VERSION_CODES.TIRAMISU) setExternalPnoScanRequest(@onNull List<WifiSsid> ssids, @Nullable int[] frequencies, @NonNull @CallbackExecutor Executor executor, @NonNull PnoScanResultsCallback callback)10250 public void setExternalPnoScanRequest(@NonNull List<WifiSsid> ssids, 10251 @Nullable int[] frequencies, @NonNull @CallbackExecutor Executor executor, 10252 @NonNull PnoScanResultsCallback callback) { 10253 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 10254 if (callback == null) throw new IllegalArgumentException("callback cannot be null"); 10255 try { 10256 mService.setExternalPnoScanRequest(new Binder(), 10257 new PnoScanResultsCallbackProxy(executor, callback), 10258 ssids, frequencies == null ? new int[0] : frequencies, 10259 mContext.getOpPackageName(), mContext.getAttributionTag()); 10260 } catch (RemoteException e) { 10261 throw e.rethrowFromSystemServer(); 10262 } 10263 } 10264 10265 /** 10266 * Clear the current PNO scan request that's been set by the calling UID. Note, the call will 10267 * be no-op if the current PNO scan request is set by a different UID. 10268 * 10269 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 10270 * @hide 10271 */ 10272 @SystemApi 10273 @RequiresApi(Build.VERSION_CODES.TIRAMISU) clearExternalPnoScanRequest()10274 public void clearExternalPnoScanRequest() { 10275 try { 10276 mService.clearExternalPnoScanRequest(); 10277 } catch (RemoteException e) { 10278 throw e.rethrowFromSystemServer(); 10279 } 10280 } 10281 10282 /** 10283 * Returns information about the last caller of an API. 10284 * 10285 * @param apiType The type of API to request information for the last caller. 10286 * @param executor The executor on which callback will be invoked. 10287 * @param resultsCallback An asynchronous callback that will return 2 arguments. 10288 * {@code String} the name of the package that performed the last API 10289 * call. {@code Boolean} the value associated with the last API call. 10290 * 10291 * @throws SecurityException if the caller does not have permission. 10292 * @throws IllegalArgumentException if the caller provided invalid inputs. 10293 * @hide 10294 */ 10295 @SystemApi 10296 @RequiresPermission(anyOf = { 10297 android.Manifest.permission.NETWORK_SETTINGS, 10298 android.Manifest.permission.NETWORK_STACK, 10299 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) getLastCallerInfoForApi(@piType int apiType, @NonNull @CallbackExecutor Executor executor, @NonNull BiConsumer<String, Boolean> resultsCallback)10300 public void getLastCallerInfoForApi(@ApiType int apiType, 10301 @NonNull @CallbackExecutor Executor executor, 10302 @NonNull BiConsumer<String, Boolean> resultsCallback) { 10303 if (executor == null) { 10304 throw new IllegalArgumentException("executor can't be null"); 10305 } 10306 if (resultsCallback == null) { 10307 throw new IllegalArgumentException("resultsCallback can't be null"); 10308 } 10309 try { 10310 mService.getLastCallerInfoForApi(apiType, 10311 new ILastCallerListener.Stub() { 10312 @Override 10313 public void onResult(String packageName, boolean enabled) { 10314 Binder.clearCallingIdentity(); 10315 executor.execute(() -> { 10316 resultsCallback.accept(packageName, enabled); 10317 }); 10318 } 10319 }); 10320 } catch (RemoteException e) { 10321 throw e.rethrowFromSystemServer(); 10322 } 10323 } 10324 10325 /** 10326 * Set a callback for Wi-Fi connected network scorer. See {@link WifiConnectedNetworkScorer}. 10327 * Only a single scorer can be set. Caller will be invoked periodically by framework to inform 10328 * client about start and stop of Wi-Fi connection. Caller can clear a previously set scorer 10329 * using {@link clearWifiConnectedNetworkScorer()}. 10330 * 10331 * @param executor The executor on which callback will be invoked. 10332 * @param scorer Scorer for Wi-Fi network implemented by application. 10333 * @return true Scorer is set successfully. 10334 * 10335 * @hide 10336 */ 10337 @SystemApi 10338 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) setWifiConnectedNetworkScorer(@onNull @allbackExecutor Executor executor, @NonNull WifiConnectedNetworkScorer scorer)10339 public boolean setWifiConnectedNetworkScorer(@NonNull @CallbackExecutor Executor executor, 10340 @NonNull WifiConnectedNetworkScorer scorer) { 10341 if (executor == null) throw new IllegalArgumentException("executor cannot be null"); 10342 if (scorer == null) throw new IllegalArgumentException("scorer cannot be null"); 10343 if (mVerboseLoggingEnabled) { 10344 Log.v(TAG, "setWifiConnectedNetworkScorer: scorer=" + scorer); 10345 } 10346 try { 10347 return mService.setWifiConnectedNetworkScorer(new Binder(), 10348 new WifiConnectedNetworkScorerProxy(executor, scorer)); 10349 } catch (RemoteException e) { 10350 throw e.rethrowFromSystemServer(); 10351 } 10352 } 10353 10354 /** 10355 * Allow caller to clear a previously set scorer. After calling this method, 10356 * client will no longer receive information about start and stop of Wi-Fi connection. 10357 * 10358 * @hide 10359 */ 10360 @SystemApi 10361 @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) clearWifiConnectedNetworkScorer()10362 public void clearWifiConnectedNetworkScorer() { 10363 if (mVerboseLoggingEnabled) { 10364 Log.v(TAG, "clearWifiConnectedNetworkScorer"); 10365 } 10366 try { 10367 mService.clearWifiConnectedNetworkScorer(); 10368 } catch (RemoteException e) { 10369 throw e.rethrowFromSystemServer(); 10370 } 10371 } 10372 10373 /** 10374 * Enable/disable wifi scan throttling from 3rd party apps. 10375 * 10376 * <p> 10377 * The throttling limits for apps are described in 10378 * <a href="Wi-Fi Scan Throttling"> 10379 * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a> 10380 * </p> 10381 * 10382 * @param enable true to allow scan throttling, false to disallow scan throttling. 10383 * @hide 10384 */ 10385 @SystemApi 10386 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setScanThrottleEnabled(boolean enable)10387 public void setScanThrottleEnabled(boolean enable) { 10388 try { 10389 mService.setScanThrottleEnabled(enable); 10390 } catch (RemoteException e) { 10391 throw e.rethrowFromSystemServer(); 10392 } 10393 } 10394 10395 /** 10396 * Get the persisted Wi-Fi scan throttle state. Defaults to true, unless changed by the user via 10397 * Developer options. 10398 * 10399 * <p> 10400 * The throttling limits for apps are described in 10401 * <a href="Wi-Fi Scan Throttling"> 10402 * https://developer.android.com/guide/topics/connectivity/wifi-scan#wifi-scan-throttling</a> 10403 * </p> 10404 * 10405 * @return true to indicate that scan throttling is enabled, false to indicate that scan 10406 * throttling is disabled. 10407 */ 10408 @RequiresPermission(ACCESS_WIFI_STATE) isScanThrottleEnabled()10409 public boolean isScanThrottleEnabled() { 10410 try { 10411 return mService.isScanThrottleEnabled(); 10412 } catch (RemoteException e) { 10413 throw e.rethrowFromSystemServer(); 10414 } 10415 } 10416 10417 /** 10418 * Enable/disable wifi auto wakeup feature. 10419 * 10420 * <p> 10421 * The feature is described in 10422 * <a href="Wi-Fi Turn on automatically"> 10423 * https://source.android.com/devices/tech/connect/wifi-infrastructure 10424 * #turn_on_wi-fi_automatically 10425 * </a> 10426 * 10427 * @param enable true to enable, false to disable. 10428 * @hide 10429 */ 10430 @SystemApi 10431 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setAutoWakeupEnabled(boolean enable)10432 public void setAutoWakeupEnabled(boolean enable) { 10433 try { 10434 mService.setAutoWakeupEnabled(enable); 10435 } catch (RemoteException e) { 10436 throw e.rethrowFromSystemServer(); 10437 } 10438 } 10439 10440 /** 10441 * Get the persisted Wi-Fi auto wakeup feature state. Defaults to false, unless changed by the 10442 * user via Settings. 10443 * 10444 * <p> 10445 * The feature is described in 10446 * <a href="Wi-Fi Turn on automatically"> 10447 * https://source.android.com/devices/tech/connect/wifi-infrastructure 10448 * #turn_on_wi-fi_automatically 10449 * </a> 10450 * 10451 * @return true to indicate that wakeup feature is enabled, false to indicate that wakeup 10452 * feature is disabled. 10453 */ 10454 @RequiresPermission(ACCESS_WIFI_STATE) isAutoWakeupEnabled()10455 public boolean isAutoWakeupEnabled() { 10456 try { 10457 return mService.isAutoWakeupEnabled(); 10458 } catch (RemoteException e) { 10459 throw e.rethrowFromSystemServer(); 10460 } 10461 } 10462 10463 /** 10464 * Sets the state of carrier offload on merged or unmerged networks for specified subscription. 10465 * 10466 * <p> 10467 * When a subscription's carrier network offload is disabled, all network suggestions related to 10468 * this subscription will not be considered for auto join. 10469 * <p> 10470 * If calling app want disable all carrier network offload from a specified subscription, should 10471 * call this API twice to disable both merged and unmerged carrier network suggestions. 10472 * 10473 * @param subscriptionId See {@link SubscriptionInfo#getSubscriptionId()}. 10474 * @param merged True for carrier merged network, false otherwise. 10475 * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} 10476 * @param enabled True for enable carrier network offload, false otherwise. 10477 * @see #isCarrierNetworkOffloadEnabled(int, boolean) 10478 * @hide 10479 */ 10480 @SystemApi 10481 @RequiresPermission(anyOf = { 10482 android.Manifest.permission.NETWORK_SETTINGS, 10483 android.Manifest.permission.NETWORK_SETUP_WIZARD}) setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, boolean enabled)10484 public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, 10485 boolean enabled) { 10486 try { 10487 mService.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled); 10488 } catch (RemoteException e) { 10489 throw e.rethrowFromSystemServer(); 10490 } 10491 } 10492 10493 /** 10494 * Get the carrier network offload state for merged or unmerged networks for specified 10495 * subscription. 10496 * @param subscriptionId subscription ID see {@link SubscriptionInfo#getSubscriptionId()} 10497 * @param merged True for carrier merged network, false otherwise. 10498 * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} 10499 * @return True to indicate that carrier network offload is enabled, false otherwise. 10500 */ 10501 @RequiresPermission(ACCESS_WIFI_STATE) isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged)10502 public boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged) { 10503 try { 10504 return mService.isCarrierNetworkOffloadEnabled(subscriptionId, merged); 10505 } catch (RemoteException e) { 10506 throw e.rethrowFromSystemServer(); 10507 } 10508 } 10509 10510 /** 10511 * Interface for network suggestion user approval status change listener. 10512 * Should be implemented by applications and registered using 10513 * {@link #addSuggestionUserApprovalStatusListener(Executor, 10514 * SuggestionUserApprovalStatusListener)} ( 10515 */ 10516 public interface SuggestionUserApprovalStatusListener { 10517 10518 /** 10519 * Called when the user approval status of the App has changed. 10520 * @param status The current status code for the user approval. One of the 10521 * {@code STATUS_SUGGESTION_APPROVAL_} values. 10522 */ onUserApprovalStatusChange(@uggestionUserApprovalStatus int status)10523 void onUserApprovalStatusChange(@SuggestionUserApprovalStatus int status); 10524 } 10525 10526 private class SuggestionUserApprovalStatusListenerProxy extends 10527 ISuggestionUserApprovalStatusListener.Stub { 10528 private final Executor mExecutor; 10529 private final SuggestionUserApprovalStatusListener mListener; 10530 SuggestionUserApprovalStatusListenerProxy(@onNull Executor executor, @NonNull SuggestionUserApprovalStatusListener listener)10531 SuggestionUserApprovalStatusListenerProxy(@NonNull Executor executor, 10532 @NonNull SuggestionUserApprovalStatusListener listener) { 10533 mExecutor = executor; 10534 mListener = listener; 10535 } 10536 10537 @Override onUserApprovalStatusChange(int status)10538 public void onUserApprovalStatusChange(int status) { 10539 mExecutor.execute(() -> mListener.onUserApprovalStatusChange(status)); 10540 } 10541 10542 } 10543 10544 /** 10545 * Add a listener for Wi-Fi network suggestion user approval status. 10546 * See {@link SuggestionUserApprovalStatusListener}. 10547 * Caller will receive a callback immediately after adding a listener and when the user approval 10548 * status of the caller has changed. 10549 * Caller can remove a previously registered listener using 10550 * {@link WifiManager#removeSuggestionUserApprovalStatusListener( 10551 * SuggestionUserApprovalStatusListener)} 10552 * A caller can add multiple listeners to monitor the event. 10553 * @param executor The executor to execute the listener of the {@code listener} object. 10554 * @param listener listener for suggestion user approval status changes. 10555 */ 10556 @RequiresPermission(ACCESS_WIFI_STATE) addSuggestionUserApprovalStatusListener( @onNull @allbackExecutor Executor executor, @NonNull SuggestionUserApprovalStatusListener listener)10557 public void addSuggestionUserApprovalStatusListener( 10558 @NonNull @CallbackExecutor Executor executor, 10559 @NonNull SuggestionUserApprovalStatusListener listener) { 10560 if (listener == null) throw new NullPointerException("Listener cannot be null"); 10561 if (executor == null) throw new NullPointerException("Executor cannot be null"); 10562 Log.v(TAG, "addSuggestionUserApprovalStatusListener listener=" + listener 10563 + ", executor=" + executor); 10564 try { 10565 synchronized (sSuggestionUserApprovalStatusListenerMap) { 10566 ISuggestionUserApprovalStatusListener.Stub binderCallback = 10567 new SuggestionUserApprovalStatusListenerProxy(executor, listener); 10568 sSuggestionUserApprovalStatusListenerMap.put(System.identityHashCode(listener), 10569 binderCallback); 10570 mService.addSuggestionUserApprovalStatusListener(binderCallback, 10571 mContext.getOpPackageName()); 10572 } 10573 } catch (RemoteException e) { 10574 throw e.rethrowFromSystemServer(); 10575 } 10576 10577 } 10578 10579 /** 10580 * Allow callers to remove a previously registered listener using 10581 * {@link #addSuggestionUserApprovalStatusListener(Executor, 10582 * SuggestionUserApprovalStatusListener)}. After calling this method, 10583 * applications will no longer receive network suggestion user approval status change through 10584 * that listener. 10585 */ 10586 @RequiresPermission(ACCESS_WIFI_STATE) removeSuggestionUserApprovalStatusListener( @onNull SuggestionUserApprovalStatusListener listener)10587 public void removeSuggestionUserApprovalStatusListener( 10588 @NonNull SuggestionUserApprovalStatusListener listener) { 10589 if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); 10590 Log.v(TAG, "removeSuggestionUserApprovalStatusListener: listener=" + listener); 10591 try { 10592 synchronized (sSuggestionUserApprovalStatusListenerMap) { 10593 int listenerIdentifier = System.identityHashCode(listener); 10594 if (!sSuggestionUserApprovalStatusListenerMap.contains(listenerIdentifier)) { 10595 Log.w(TAG, "Unknown external callback " + listenerIdentifier); 10596 return; 10597 } 10598 mService.removeSuggestionUserApprovalStatusListener( 10599 sSuggestionUserApprovalStatusListenerMap.get(listenerIdentifier), 10600 mContext.getOpPackageName()); 10601 sSuggestionUserApprovalStatusListenerMap.remove(listenerIdentifier); 10602 } 10603 } catch (RemoteException e) { 10604 throw e.rethrowFromSystemServer(); 10605 } 10606 } 10607 10608 /** 10609 * Indicates the start/end of an emergency scan request being processed by {@link WifiScanner}. 10610 * The wifi stack should ensure that the wifi chip remains on for the duration of the scan. 10611 * WifiScanner detects emergency scan requests via 10612 * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag. 10613 * 10614 * If the wifi stack is off (because location & wifi toggles are off) when this indication is 10615 * received, the wifi stack will temporarily move to a scan only mode. Since location toggle 10616 * is off, only scan with 10617 * {@link WifiScanner.ScanSettings#ignoreLocationSettings} flag set will be 10618 * allowed to be processed for this duration. 10619 * 10620 * @hide 10621 */ 10622 @RequiresPermission(android.Manifest.permission.NETWORK_STACK) setEmergencyScanRequestInProgress(boolean inProgress)10623 public void setEmergencyScanRequestInProgress(boolean inProgress) { 10624 try { 10625 mService.setEmergencyScanRequestInProgress(inProgress); 10626 } catch (RemoteException e) { 10627 throw e.rethrowFromSystemServer(); 10628 } 10629 } 10630 10631 /** 10632 * Enable or disable Wi-Fi scoring. Wi-Fi network status is evaluated by Wi-Fi scoring 10633 * {@link WifiScoreReport}. This API enables/disables Wi-Fi scoring to take action on network 10634 * selection. 10635 * 10636 * @param enabled {@code true} to enable, {@code false} to disable. 10637 * @return true The status of Wifi scoring is set successfully. 10638 * @hide 10639 */ 10640 @SystemApi 10641 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) setWifiScoringEnabled(boolean enabled)10642 public boolean setWifiScoringEnabled(boolean enabled) { 10643 if (mVerboseLoggingEnabled) { 10644 Log.v(TAG, "setWifiScoringEnabled: " + enabled); 10645 } 10646 try { 10647 return mService.setWifiScoringEnabled(enabled); 10648 } catch (RemoteException e) { 10649 throw e.rethrowFromSystemServer(); 10650 } 10651 } 10652 10653 /** 10654 * Flush Passpoint ANQP cache, and clear pending ANQP requests. Allows the caller to reset the 10655 * Passpoint ANQP state, if required. 10656 * 10657 * Notes: 10658 * 1. Flushing the ANQP cache may cause delays in discovering and connecting to Passpoint 10659 * networks. 10660 * 2. Intended to be used by Device Owner (DO), Profile Owner (PO), Settings and provisioning 10661 * apps. 10662 */ 10663 @RequiresPermission(anyOf = { 10664 android.Manifest.permission.NETWORK_SETTINGS, 10665 android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, 10666 android.Manifest.permission.NETWORK_CARRIER_PROVISIONING 10667 }, conditional = true) flushPasspointAnqpCache()10668 public void flushPasspointAnqpCache() { 10669 try { 10670 mService.flushPasspointAnqpCache(mContext.getOpPackageName()); 10671 } catch (RemoteException e) { 10672 throw e.rethrowFromSystemServer(); 10673 } 10674 } 10675 10676 /** 10677 * Returns a list of {@link WifiAvailableChannel} for the specified band and operational 10678 * mode(s), that is allowed for the current regulatory domain. An empty list implies that there 10679 * are no available channels for use. 10680 * 10681 * Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*} 10682 * constant is limited to one of the band values specified below. Specifically, if the 5GHz 10683 * band is included then it must include the DFS channels - an exception will be thrown 10684 * otherwise. The caller should not make any assumptions about whether DFS channels are allowed. 10685 * This API will indicate whether DFS channels are allowed for the specified operation mode(s) 10686 * per device policy. 10687 * 10688 * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} 10689 * constants. 10690 * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED}=0 - no band specified; Looks for the 10691 * channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz 10692 * 2. {@code WifiScanner#WIFI_BAND_24_GHZ}=1 10693 * 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}=6 10694 * 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}=7 10695 * 5. {@code WifiScanner#WIFI_BAND_6_GHZ}=8 10696 * 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}=15 10697 * 7. {@code WifiScanner#WIFI_BAND_60_GHZ}=16 10698 * 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}=31 10699 * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants 10700 * e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE} 10701 * @return a list of {@link WifiAvailableChannel} 10702 * 10703 * @throws UnsupportedOperationException - if this API is not supported on this device 10704 * or IllegalArgumentException - if the band specified is not one among the list 10705 * of bands mentioned above. 10706 */ 10707 @RequiresApi(Build.VERSION_CODES.S) 10708 @NonNull 10709 @RequiresPermission(NEARBY_WIFI_DEVICES) getAllowedChannels( int band, @WifiAvailableChannel.OpMode int mode)10710 public List<WifiAvailableChannel> getAllowedChannels( 10711 int band, 10712 @WifiAvailableChannel.OpMode int mode) { 10713 if (!SdkLevel.isAtLeastS()) { 10714 throw new UnsupportedOperationException(); 10715 } 10716 try { 10717 Bundle extras = new Bundle(); 10718 if (SdkLevel.isAtLeastS()) { 10719 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 10720 mContext.getAttributionSource()); 10721 } 10722 return mService.getUsableChannels(band, mode, 10723 WifiAvailableChannel.FILTER_REGULATORY, mContext.getOpPackageName(), extras); 10724 } catch (RemoteException e) { 10725 throw e.rethrowFromSystemServer(); 10726 } 10727 } 10728 10729 /** 10730 * Returns a list of {@link WifiAvailableChannel} for the specified band and operational 10731 * mode(s) per the current regulatory domain and device-specific constraints such as concurrency 10732 * state and interference due to other radios. An empty list implies that there are no available 10733 * channels for use. 10734 * 10735 * Note: the {@code band} parameter which is specified as a {@code WifiScanner#WIFI_BAND_*} 10736 * constant is limited to one of the band values specified below. Specifically, if the 5GHz 10737 * band is included then it must include the DFS channels - an exception will be thrown 10738 * otherwise. The caller should not make any assumptions about whether DFS channels are allowed. 10739 * This API will indicate whether DFS channels are allowed for the specified operation mode(s) 10740 * per device policy. 10741 * 10742 * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*} 10743 * constants. 10744 * 1. {@code WifiScanner#WIFI_BAND_UNSPECIFIED}=0 - no band specified; Looks for the 10745 * channels in all the available bands - 2.4 GHz, 5 GHz, 6 GHz and 60 GHz 10746 * 2. {@code WifiScanner#WIFI_BAND_24_GHZ}=1 10747 * 3. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}=6 10748 * 4. {@code WifiScanner#WIFI_BAND_BOTH_WITH_DFS}=7 10749 * 5. {@code WifiScanner#WIFI_BAND_6_GHZ}=8 10750 * 6. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_GHZ}=15 10751 * 7. {@code WifiScanner#WIFI_BAND_60_GHZ}=16 10752 * 8. {@code WifiScanner#WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}=31 10753 * @param mode Bitwise OR of {@code WifiAvailableChannel#OP_MODE_*} constants 10754 * e.g. {@link WifiAvailableChannel#OP_MODE_WIFI_AWARE} 10755 * @return a list of {@link WifiAvailableChannel} 10756 * 10757 * @throws UnsupportedOperationException - if this API is not supported on this device 10758 * or IllegalArgumentException - if the band specified is not one among the list 10759 * of bands mentioned above. 10760 */ 10761 @RequiresApi(Build.VERSION_CODES.S) 10762 @NonNull 10763 @RequiresPermission(NEARBY_WIFI_DEVICES) getUsableChannels( int band, @WifiAvailableChannel.OpMode int mode)10764 public List<WifiAvailableChannel> getUsableChannels( 10765 int band, 10766 @WifiAvailableChannel.OpMode int mode) { 10767 if (!SdkLevel.isAtLeastS()) { 10768 throw new UnsupportedOperationException(); 10769 } 10770 try { 10771 Bundle extras = new Bundle(); 10772 if (SdkLevel.isAtLeastS()) { 10773 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 10774 mContext.getAttributionSource()); 10775 } 10776 return mService.getUsableChannels(band, mode, 10777 WifiAvailableChannel.getUsableFilter(), mContext.getOpPackageName(), extras); 10778 } catch (RemoteException e) { 10779 throw e.rethrowFromSystemServer(); 10780 } 10781 } 10782 10783 /** 10784 * If the device supports Wi-Fi Passpoint, the user can explicitly enable or disable it. 10785 * That status can be queried using this method. 10786 * @return {@code true} if Wi-Fi Passpoint is enabled 10787 * 10788 */ 10789 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) isWifiPasspointEnabled()10790 public boolean isWifiPasspointEnabled() { 10791 try { 10792 return mService.isWifiPasspointEnabled(); 10793 } catch (RemoteException e) { 10794 throw e.rethrowFromSystemServer(); 10795 } 10796 } 10797 10798 /** 10799 * Explicitly enable or disable Wi-Fi Passpoint as a global switch. 10800 * The global Passpoint enabling/disabling overrides individual configuration 10801 * enabling/disabling. 10802 * Passpoint global status can be queried by {@link WifiManager#isWifiPasspointEnabled }. 10803 * 10804 * @param enabled {@code true} to enable, {@code false} to disable. 10805 * @hide 10806 */ 10807 @SystemApi 10808 @RequiresPermission(anyOf = { 10809 android.Manifest.permission.NETWORK_SETTINGS, 10810 android.Manifest.permission.NETWORK_SETUP_WIZARD 10811 }) setWifiPasspointEnabled(boolean enabled)10812 public void setWifiPasspointEnabled(boolean enabled) { 10813 if (mVerboseLoggingEnabled) { 10814 Log.v(TAG, "setWifiPasspointEnabled: " + enabled); 10815 } 10816 try { 10817 mService.setWifiPasspointEnabled(enabled); 10818 } catch (RemoteException e) { 10819 throw e.rethrowFromSystemServer(); 10820 } 10821 } 10822 10823 /** 10824 * The device may support concurrent connections to multiple internet-providing Wi-Fi 10825 * networks (APs) - that is indicated by 10826 * {@link WifiManager#isStaConcurrencyForMultiInternetSupported()}. 10827 * This method indicates whether or not the feature is currently enabled. 10828 * A value of {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DISABLED} indicates that the feature 10829 * is disabled, a value of {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DBS_AP} or 10830 * {@link WifiManager#WIFI_MULTI_INTERNET_MODE_MULTI_AP} indicates that the feature is enabled. 10831 * 10832 * The app can register to receive the corresponding Wi-Fi networks using the 10833 * {@link ConnectivityManager#registerNetworkCallback(NetworkRequest, NetworkCallback)} API with 10834 * a {@link WifiNetworkSpecifier} configured using the 10835 * {@link WifiNetworkSpecifier.Builder#setBand(int)} method. 10836 */ 10837 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 10838 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) getStaConcurrencyForMultiInternetMode()10839 public @WifiMultiInternetMode int getStaConcurrencyForMultiInternetMode() { 10840 try { 10841 return mService.getStaConcurrencyForMultiInternetMode(); 10842 } catch (RemoteException e) { 10843 throw e.rethrowFromSystemServer(); 10844 } 10845 } 10846 10847 /** 10848 * Check if the currently connected network meets the minimum required Wi-Fi security level set. 10849 * If not, the current network will be disconnected. 10850 * 10851 * @throws SecurityException if the caller does not have permission. 10852 * @hide 10853 */ 10854 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 10855 @SystemApi 10856 @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) notifyMinimumRequiredWifiSecurityLevelChanged(int level)10857 public void notifyMinimumRequiredWifiSecurityLevelChanged(int level) { 10858 if (mVerboseLoggingEnabled) { 10859 Log.v(TAG, "notifyMinimumRequiredWifiSecurityLevelChanged"); 10860 } 10861 try { 10862 mService.notifyMinimumRequiredWifiSecurityLevelChanged(level); 10863 } catch (RemoteException e) { 10864 throw e.rethrowFromSystemServer(); 10865 } 10866 } 10867 10868 /** 10869 * Check if the currently connected network meets the Wi-Fi SSID policy set. 10870 * If not, the current network will be disconnected. 10871 * 10872 * @throws SecurityException if the caller does not have permission. 10873 * @hide 10874 */ 10875 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 10876 @SystemApi 10877 @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) notifyWifiSsidPolicyChanged(@onNull WifiSsidPolicy policy)10878 public void notifyWifiSsidPolicyChanged(@NonNull WifiSsidPolicy policy) { 10879 if (mVerboseLoggingEnabled) { 10880 Log.v(TAG, "notifyWifiSsidPolicyChanged"); 10881 } 10882 try { 10883 if (policy != null) { 10884 mService.notifyWifiSsidPolicyChanged( 10885 policy.getPolicyType(), new ArrayList<>(policy.getSsids())); 10886 } 10887 } catch (RemoteException e) { 10888 throw e.rethrowFromSystemServer(); 10889 } 10890 } 10891 10892 /** 10893 * Configure whether or not concurrent multiple connections to internet-providing Wi-Fi 10894 * networks (AP) is enabled. 10895 * Use {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DISABLED} to disable, and either 10896 * {@link WifiManager#WIFI_MULTI_INTERNET_MODE_DBS_AP} or 10897 * {@link WifiManager#WIFI_MULTI_INTERNET_MODE_MULTI_AP} to enable in different modes. 10898 * The {@link WifiManager#getStaConcurrencyForMultiInternetMode() } can be used to retrieve 10899 * the current mode. 10900 * 10901 * @param mode Multi internet mode. 10902 * @return true when the mode is set successfully, false when failed. 10903 * @hide 10904 */ 10905 @SystemApi 10906 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 10907 @RequiresPermission(anyOf = { 10908 android.Manifest.permission.NETWORK_SETTINGS, 10909 android.Manifest.permission.NETWORK_SETUP_WIZARD 10910 }) setStaConcurrencyForMultiInternetMode(@ifiMultiInternetMode int mode)10911 public boolean setStaConcurrencyForMultiInternetMode(@WifiMultiInternetMode int mode) { 10912 if (mVerboseLoggingEnabled) { 10913 Log.v(TAG, "setStaConcurrencyForMultiInternetMode: " + mode); 10914 } 10915 try { 10916 return mService.setStaConcurrencyForMultiInternetMode(mode); 10917 } catch (RemoteException e) { 10918 throw e.rethrowFromSystemServer(); 10919 } 10920 } 10921 10922 /** 10923 * Intent action to launch a dialog from the WifiDialog app. 10924 * Must include EXTRA_DIALOG_ID, EXTRA_DIALOG_TYPE, and appropriate extras for the dialog type. 10925 * @hide 10926 */ 10927 public static final String ACTION_LAUNCH_DIALOG = 10928 "android.net.wifi.action.LAUNCH_DIALOG"; 10929 10930 /** 10931 * Intent action to dismiss an existing dialog from the WifiDialog app. 10932 * Must include EXTRA_DIALOG_ID. 10933 * @hide 10934 */ 10935 public static final String ACTION_DISMISS_DIALOG = 10936 "android.net.wifi.action.DISMISS_DIALOG"; 10937 10938 /** 10939 * Unknown DialogType. 10940 * @hide 10941 */ 10942 public static final int DIALOG_TYPE_UNKNOWN = 0; 10943 10944 /** 10945 * DialogType for a simple dialog. 10946 * @see {@link com.android.server.wifi.WifiDialogManager#createSimpleDialog} 10947 * @hide 10948 */ 10949 public static final int DIALOG_TYPE_SIMPLE = 1; 10950 10951 /** 10952 * DialogType for a P2P Invitation Sent dialog. 10953 * @see {@link com.android.server.wifi.WifiDialogManager#createP2pInvitationSentDialog} 10954 * @hide 10955 */ 10956 public static final int DIALOG_TYPE_P2P_INVITATION_SENT = 2; 10957 10958 /** 10959 * DialogType for a P2P Invitation Received dialog. 10960 * @see {@link com.android.server.wifi.WifiDialogManager#createP2pInvitationReceivedDialog} 10961 * @hide 10962 */ 10963 public static final int DIALOG_TYPE_P2P_INVITATION_RECEIVED = 3; 10964 10965 /** @hide */ 10966 @IntDef(prefix = { "DIALOG_TYPE_" }, value = { 10967 DIALOG_TYPE_UNKNOWN, 10968 DIALOG_TYPE_SIMPLE, 10969 DIALOG_TYPE_P2P_INVITATION_SENT, 10970 DIALOG_TYPE_P2P_INVITATION_RECEIVED, 10971 }) 10972 @Retention(RetentionPolicy.SOURCE) 10973 public @interface DialogType {} 10974 10975 /** 10976 * Dialog positive button was clicked. 10977 * @hide 10978 */ 10979 public static final int DIALOG_REPLY_POSITIVE = 0; 10980 10981 /** 10982 * Dialog negative button was clicked. 10983 * @hide 10984 */ 10985 public static final int DIALOG_REPLY_NEGATIVE = 1; 10986 10987 /** 10988 * Dialog neutral button was clicked. 10989 * @hide 10990 */ 10991 public static final int DIALOG_REPLY_NEUTRAL = 2; 10992 10993 /** 10994 * Dialog was cancelled. 10995 * @hide 10996 */ 10997 public static final int DIALOG_REPLY_CANCELLED = 3; 10998 10999 /** 11000 * Indication of a reply to a dialog. 11001 * See {@link WifiManager#replyToSimpleDialog(int, int)} 11002 * @hide 11003 */ 11004 @IntDef(prefix = { "DIALOG_TYPE_" }, value = { 11005 DIALOG_REPLY_POSITIVE, 11006 DIALOG_REPLY_NEGATIVE, 11007 DIALOG_REPLY_NEUTRAL, 11008 DIALOG_REPLY_CANCELLED, 11009 }) 11010 @Retention(RetentionPolicy.SOURCE) 11011 public @interface DialogReply {} 11012 11013 /** 11014 * Invalid dialog id for dialogs that are not currently active. 11015 * @hide 11016 */ 11017 public static final int INVALID_DIALOG_ID = -1; 11018 11019 /** 11020 * Extra int indicating the type of dialog to display. 11021 * @hide 11022 */ 11023 public static final String EXTRA_DIALOG_TYPE = "android.net.wifi.extra.DIALOG_TYPE"; 11024 11025 /** 11026 * Extra int indicating the ID of a dialog. The value must not be {@link #INVALID_DIALOG_ID}. 11027 * @hide 11028 */ 11029 public static final String EXTRA_DIALOG_ID = "android.net.wifi.extra.DIALOG_ID"; 11030 11031 /** 11032 * Extra String indicating the title of a simple dialog. 11033 * @hide 11034 */ 11035 public static final String EXTRA_DIALOG_TITLE = "android.net.wifi.extra.DIALOG_TITLE"; 11036 11037 /** 11038 * Extra String indicating the message of a simple dialog. 11039 * @hide 11040 */ 11041 public static final String EXTRA_DIALOG_MESSAGE = "android.net.wifi.extra.DIALOG_MESSAGE"; 11042 11043 /** 11044 * Extra String indicating the message URL of a simple dialog. 11045 * @hide 11046 */ 11047 public static final String EXTRA_DIALOG_MESSAGE_URL = 11048 "android.net.wifi.extra.DIALOG_MESSAGE_URL"; 11049 11050 /** 11051 * Extra String indicating the start index of a message URL span of a simple dialog. 11052 * @hide 11053 */ 11054 public static final String EXTRA_DIALOG_MESSAGE_URL_START = 11055 "android.net.wifi.extra.DIALOG_MESSAGE_URL_START"; 11056 11057 /** 11058 * Extra String indicating the end index of a message URL span of a simple dialog. 11059 * @hide 11060 */ 11061 public static final String EXTRA_DIALOG_MESSAGE_URL_END = 11062 "android.net.wifi.extra.DIALOG_MESSAGE_URL_END"; 11063 11064 /** 11065 * Extra String indicating the positive button text of a simple dialog. 11066 * @hide 11067 */ 11068 public static final String EXTRA_DIALOG_POSITIVE_BUTTON_TEXT = 11069 "android.net.wifi.extra.DIALOG_POSITIVE_BUTTON_TEXT"; 11070 11071 /** 11072 * Extra String indicating the negative button text of a simple dialog. 11073 * @hide 11074 */ 11075 public static final String EXTRA_DIALOG_NEGATIVE_BUTTON_TEXT = 11076 "android.net.wifi.extra.DIALOG_NEGATIVE_BUTTON_TEXT"; 11077 11078 /** 11079 * Extra String indicating the neutral button text of a simple dialog. 11080 * @hide 11081 */ 11082 public static final String EXTRA_DIALOG_NEUTRAL_BUTTON_TEXT = 11083 "android.net.wifi.extra.DIALOG_NEUTRAL_BUTTON_TEXT"; 11084 11085 /** 11086 * Extra long indicating the timeout in milliseconds of a dialog. 11087 * @hide 11088 */ 11089 public static final String EXTRA_DIALOG_TIMEOUT_MS = "android.net.wifi.extra.DIALOG_TIMEOUT_MS"; 11090 11091 /** 11092 * Extra String indicating a P2P device name for a P2P Invitation Sent/Received dialog. 11093 * @hide 11094 */ 11095 public static final String EXTRA_P2P_DEVICE_NAME = "android.net.wifi.extra.P2P_DEVICE_NAME"; 11096 11097 /** 11098 * Extra boolean indicating that a PIN is requested for a P2P Invitation Received dialog. 11099 * @hide 11100 */ 11101 public static final String EXTRA_P2P_PIN_REQUESTED = "android.net.wifi.extra.P2P_PIN_REQUESTED"; 11102 11103 /** 11104 * Extra String indicating the PIN to be displayed for a P2P Invitation Sent/Received dialog. 11105 * @hide 11106 */ 11107 public static final String EXTRA_P2P_DISPLAY_PIN = "android.net.wifi.extra.P2P_DISPLAY_PIN"; 11108 11109 /** 11110 * Extra boolean indicating ACTION_CLOSE_SYSTEM_DIALOGS should not close the Wi-Fi dialogs. 11111 * @hide 11112 */ 11113 public static final String EXTRA_CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI = 11114 "android.net.wifi.extra.CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI"; 11115 11116 /** 11117 * Returns a set of packages that aren't DO or PO but should be able to manage WiFi networks. 11118 * @hide 11119 */ 11120 @SystemApi 11121 @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) 11122 @NonNull getOemPrivilegedWifiAdminPackages()11123 public Set<String> getOemPrivilegedWifiAdminPackages() { 11124 try { 11125 return new ArraySet<>(mService.getOemPrivilegedWifiAdminPackages()); 11126 } catch (RemoteException e) { 11127 throw e.rethrowFromSystemServer(); 11128 } 11129 } 11130 11131 /** 11132 * Method for WifiDialog to notify the framework of a reply to a simple dialog. 11133 * @param dialogId id of the replying dialog. 11134 * @param reply reply of the dialog. 11135 * @hide 11136 */ replyToSimpleDialog(int dialogId, @DialogReply int reply)11137 public void replyToSimpleDialog(int dialogId, @DialogReply int reply) { 11138 if (mVerboseLoggingEnabled) { 11139 Log.v(TAG, "replyToWifiEnableRequestDialog: dialogId=" + dialogId 11140 + " reply=" + reply); 11141 } 11142 try { 11143 mService.replyToSimpleDialog(dialogId, reply); 11144 } catch (RemoteException e) { 11145 throw e.rethrowFromSystemServer(); 11146 } 11147 } 11148 11149 /** 11150 * Method for WifiDialog to notify the framework of a reply to a P2P Invitation Received dialog. 11151 * @param dialogId id of the replying dialog. 11152 * @param accepted Whether the invitation was accepted. 11153 * @param optionalPin PIN of the reply, or {@code null} if none was supplied. 11154 * @hide 11155 */ replyToP2pInvitationReceivedDialog( int dialogId, boolean accepted, @Nullable String optionalPin)11156 public void replyToP2pInvitationReceivedDialog( 11157 int dialogId, boolean accepted, @Nullable String optionalPin) { 11158 if (mVerboseLoggingEnabled) { 11159 Log.v(TAG, "replyToP2pInvitationReceivedDialog: " 11160 + "dialogId=" + dialogId 11161 + ", accepted=" + accepted 11162 + ", pin=" + optionalPin); 11163 } 11164 try { 11165 mService.replyToP2pInvitationReceivedDialog(dialogId, accepted, optionalPin); 11166 } catch (RemoteException e) { 11167 throw e.rethrowFromSystemServer(); 11168 } 11169 } 11170 11171 /** 11172 * Specify a list of DHCP options to use for any network whose SSID is specified and which 11173 * transmits vendor-specific information elements (VSIEs) using the specified Organizationally 11174 * Unique Identifier (OUI). If the AP transmits VSIEs for multiple specified OUIs then all 11175 * matching DHCP options will be used. The allowlist for DHCP options in 11176 * {@link android.net.ip.IpClient} gates whether the DHCP options will actually be used. 11177 * When DHCP options are used: if the option value {@link android.net.DhcpOption#getValue()} 11178 * is null, the option type {@link android.net.DhcpOption#getType()} will be put in the 11179 * Parameter Request List in the DHCP packets; otherwise, the option will be included in the 11180 * options section in the DHCP packets. Use {@link #removeCustomDhcpOptions(Object, Object)} 11181 * to remove the specified DHCP options. 11182 * 11183 * @param ssid the network SSID. 11184 * @param oui the 3-byte OUI. 11185 * @param options the list of {@link android.net.DhcpOption}. 11186 * 11187 * @hide 11188 */ 11189 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 11190 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11191 @RequiresPermission(anyOf = { 11192 android.Manifest.permission.NETWORK_SETTINGS, 11193 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 11194 }) addCustomDhcpOptions(@onNull WifiSsid ssid, @NonNull byte[] oui, @NonNull List<DhcpOption> options)11195 public void addCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui, 11196 @NonNull List<DhcpOption> options) { 11197 if (mVerboseLoggingEnabled) { 11198 Log.v(TAG, "addCustomDhcpOptions: ssid=" 11199 + ssid + ", oui=" + Arrays.toString(oui) + ", options=" + options); 11200 } 11201 try { 11202 mService.addCustomDhcpOptions(ssid, oui, options); 11203 } catch (RemoteException e) { 11204 throw e.rethrowFromSystemServer(); 11205 } 11206 } 11207 11208 /** 11209 * Remove custom DHCP options specified by {@link #addCustomDhcpOptions(Object, Object, List)}. 11210 * 11211 * @param ssid the network SSID. 11212 * @param oui the 3-byte OUI. 11213 * 11214 * @hide 11215 */ 11216 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 11217 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11218 @RequiresPermission(anyOf = { 11219 android.Manifest.permission.NETWORK_SETTINGS, 11220 android.Manifest.permission.OVERRIDE_WIFI_CONFIG 11221 }) removeCustomDhcpOptions(@onNull WifiSsid ssid, @NonNull byte[] oui)11222 public void removeCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui) { 11223 if (mVerboseLoggingEnabled) { 11224 Log.v(TAG, "removeCustomDhcpOptions: ssid=" + ssid + ", oui=" + Arrays.toString(oui)); 11225 } 11226 try { 11227 mService.removeCustomDhcpOptions(ssid, oui); 11228 } catch (RemoteException e) { 11229 throw e.rethrowFromSystemServer(); 11230 } 11231 } 11232 11233 /** 11234 * Wi-Fi interface of type STA (station/client Wi-Fi infrastructure device). 11235 */ 11236 public static final int WIFI_INTERFACE_TYPE_STA = 0; 11237 11238 /** 11239 * Wi-Fi interface of type AP (access point Wi-Fi infrastructure device). 11240 */ 11241 public static final int WIFI_INTERFACE_TYPE_AP = 1; 11242 11243 /** 11244 * Wi-Fi interface of type Wi-Fi Aware (aka NAN). 11245 */ 11246 public static final int WIFI_INTERFACE_TYPE_AWARE = 2; 11247 11248 /** 11249 * Wi-Fi interface of type Wi-Fi Direct (aka P2P). 11250 */ 11251 public static final int WIFI_INTERFACE_TYPE_DIRECT = 3; 11252 11253 /** @hide */ 11254 @IntDef(prefix = { "WIFI_INTERFACE_TYPE_" }, value = { 11255 WIFI_INTERFACE_TYPE_STA, 11256 WIFI_INTERFACE_TYPE_AP, 11257 WIFI_INTERFACE_TYPE_AWARE, 11258 WIFI_INTERFACE_TYPE_DIRECT, 11259 }) 11260 @Retention(RetentionPolicy.SOURCE) 11261 public @interface WifiInterfaceType {} 11262 11263 /** 11264 * Class describing an impact of interface creation - returned by 11265 * {@link #reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}. Due to Wi-Fi 11266 * concurrency limitations certain interfaces may have to be torn down. Each of these 11267 * interfaces was requested by a set of applications who could potentially be impacted. 11268 * 11269 * This class contain the information for a single interface: the interface type with 11270 * {@link InterfaceCreationImpact#getInterfaceType()} and the set of impacted packages 11271 * with {@link InterfaceCreationImpact#getPackages()}. 11272 */ 11273 public static class InterfaceCreationImpact { 11274 private final int mInterfaceType; 11275 private final Set<String> mPackages; 11276 InterfaceCreationImpact(@ifiInterfaceType int interfaceType, @NonNull Set<String> packages)11277 public InterfaceCreationImpact(@WifiInterfaceType int interfaceType, 11278 @NonNull Set<String> packages) { 11279 mInterfaceType = interfaceType; 11280 mPackages = packages; 11281 } 11282 11283 /** 11284 * @return The interface type which will be torn down to make room for the interface 11285 * requested in {@link #reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}. 11286 */ getInterfaceType()11287 public @WifiInterfaceType int getInterfaceType() { 11288 return mInterfaceType; 11289 } 11290 11291 /** 11292 * @return The list of potentially impacted packages due to tearing down the interface 11293 * specified in {@link #getInterfaceType()}. 11294 */ getPackages()11295 public @NonNull Set<String> getPackages() { 11296 return mPackages; 11297 } 11298 11299 @Override hashCode()11300 public int hashCode() { 11301 return Objects.hash(mInterfaceType, mPackages); 11302 } 11303 11304 @Override equals(Object that)11305 public boolean equals(Object that) { 11306 if (this == that) return true; 11307 if (!(that instanceof InterfaceCreationImpact)) return false; 11308 InterfaceCreationImpact thatInterfaceCreationImpact = (InterfaceCreationImpact) that; 11309 11310 return this.mInterfaceType == thatInterfaceCreationImpact.mInterfaceType 11311 && Objects.equals(this.mPackages, thatInterfaceCreationImpact.mPackages); 11312 } 11313 } 11314 11315 /** 11316 * Queries the framework to determine whether the specified interface can be created, and if 11317 * so - what other interfaces would be torn down by the framework to allow this creation if 11318 * it were requested. The result is returned via the specified {@link BiConsumer} callback 11319 * which returns two arguments: 11320 * <li>First argument: a {@code boolean} - indicating whether or not the interface can be 11321 * created.</li> 11322 * <li>Second argument: a {@code Set<InterfaceCreationImpact>} - if the interface can be 11323 * created (first argument is {@code true} then this is the set of interface types which 11324 * will be removed and the packages which requested them. Possibly an empty set. If the 11325 * first argument is {@code false}, then an empty set will be returned here.</li> 11326 * <p> 11327 * Interfaces, input and output, are specified using the {@code WIFI_INTERFACE_*} constants: 11328 * {@link #WIFI_INTERFACE_TYPE_STA}, {@link #WIFI_INTERFACE_TYPE_AP}, 11329 * {@link #WIFI_INTERFACE_TYPE_AWARE}, or {@link #WIFI_INTERFACE_TYPE_DIRECT}. 11330 * <p> 11331 * This method does not actually create the interface. That operation is handled by the 11332 * framework when a particular service method is called. E.g. a Wi-Fi Direct interface may be 11333 * created when various methods of {@link android.net.wifi.p2p.WifiP2pManager} are called, 11334 * similarly for Wi-Fi Aware and {@link android.net.wifi.aware.WifiAwareManager}. 11335 * <p> 11336 * Note: the information returned via this method is the current snapshot of the system. It may 11337 * change due to actions of the framework or other apps. 11338 * 11339 * @param interfaceType The interface type whose possible creation is being queried. 11340 * @param requireNewInterface Indicates that the query is for a new interface of the specified 11341 * type - an existing interface won't meet the query. Some 11342 * operations (such as Wi-Fi Direct and Wi-Fi Aware are a shared 11343 * resource and so may not need a new interface). 11344 * @param executor An {@link Executor} on which to return the result. 11345 * @param resultCallback The asynchronous callback which will return two argument: a 11346 * {@code boolean} (whether the interface can be created), and a 11347 * {@code Set<InterfaceCreationImpact>} (a set of {@link InterfaceCreationImpact}: 11348 * interfaces which will be destroyed when the interface is created 11349 * and the packages which requested them and thus may be impacted). 11350 */ 11351 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11352 @RequiresPermission(allOf = {android.Manifest.permission.MANAGE_WIFI_INTERFACES, 11353 ACCESS_WIFI_STATE}) reportCreateInterfaceImpact(@ifiInterfaceType int interfaceType, boolean requireNewInterface, @NonNull @CallbackExecutor Executor executor, @NonNull BiConsumer<Boolean, Set<InterfaceCreationImpact>> resultCallback)11354 public void reportCreateInterfaceImpact(@WifiInterfaceType int interfaceType, 11355 boolean requireNewInterface, 11356 @NonNull @CallbackExecutor Executor executor, 11357 @NonNull BiConsumer<Boolean, Set<InterfaceCreationImpact>> resultCallback) { 11358 Objects.requireNonNull(executor, "Non-null executor required"); 11359 Objects.requireNonNull(resultCallback, "Non-null resultCallback required"); 11360 try { 11361 mService.reportCreateInterfaceImpact(mContext.getOpPackageName(), interfaceType, 11362 requireNewInterface, new IInterfaceCreationInfoCallback.Stub() { 11363 @Override 11364 public void onResults(boolean canCreate, int[] interfacesToDelete, 11365 String[] packagesForInterfaces) { 11366 Binder.clearCallingIdentity(); 11367 if ((interfacesToDelete == null && packagesForInterfaces != null) 11368 || (interfacesToDelete != null 11369 && packagesForInterfaces == null) || (canCreate && ( 11370 interfacesToDelete == null || interfacesToDelete.length 11371 != packagesForInterfaces.length))) { 11372 Log.e(TAG, 11373 "reportImpactToCreateIfaceRequest: Invalid callback " 11374 + "parameters - canCreate=" 11375 + canCreate + ", interfacesToDelete=" 11376 + Arrays.toString(interfacesToDelete) 11377 + ", worksourcesForInterfaces=" 11378 + Arrays.toString(packagesForInterfaces)); 11379 return; 11380 } 11381 11382 final Set<InterfaceCreationImpact> finalSet = 11383 (canCreate && interfacesToDelete.length > 0) ? new ArraySet<>() 11384 : Collections.emptySet(); 11385 if (canCreate) { 11386 for (int i = 0; i < interfacesToDelete.length; ++i) { 11387 finalSet.add( 11388 new InterfaceCreationImpact(interfacesToDelete[i], 11389 packagesForInterfaces[i] == null 11390 ? Collections.emptySet() 11391 : new ArraySet<>( 11392 packagesForInterfaces[i] 11393 .split(",")))); 11394 } 11395 } 11396 executor.execute(() -> resultCallback.accept(canCreate, finalSet)); 11397 } 11398 }); 11399 } catch (RemoteException e) { 11400 throw e.rethrowFromSystemServer(); 11401 } 11402 } 11403 11404 /** 11405 * Returns the max number of channels that is allowed to be set on a 11406 * {@link WifiNetworkSpecifier}. 11407 * @see WifiNetworkSpecifier.Builder#setPreferredChannelsFrequenciesMhz(int[]) 11408 * 11409 * @return The max number of channels can be set on a request. 11410 */ 11411 getMaxNumberOfChannelsPerNetworkSpecifierRequest()11412 public int getMaxNumberOfChannelsPerNetworkSpecifierRequest() { 11413 try { 11414 return mService.getMaxNumberOfChannelsPerRequest(); 11415 } catch (RemoteException e) { 11416 throw e.rethrowFromSystemServer(); 11417 } 11418 } 11419 11420 /** 11421 * Add a list of new application-initiated QoS policies. 11422 * 11423 * Note: Policies are managed using a policy ID, which can be retrieved using 11424 * {@link QosPolicyParams#getPolicyId()}. This ID can be used when removing a policy via 11425 * {@link #removeQosPolicies(int[])}. The caller is in charge of assigning and managing 11426 * the policy IDs for any requested policies. 11427 * 11428 * Note: Policies with duplicate IDs are not allowed. To update an existing policy, first 11429 * remove it using {@link #removeQosPolicies(int[])}, and then re-add it using this API. 11430 * 11431 * Note: All policies in a single request must have the same {@link QosPolicyParams.Direction}. 11432 * 11433 * Note: Currently, only the {@link QosPolicyParams#DIRECTION_DOWNLINK} direction is supported. 11434 * 11435 * @param policyParamsList List of {@link QosPolicyParams} objects describing the requested 11436 * policies. Must have a maximum length of 11437 * {@link #getMaxNumberOfPoliciesPerQosRequest()}. 11438 * @param executor The executor on which callback will be invoked. 11439 * @param resultsCallback An asynchronous callback that will return a list of integer status 11440 * codes from {@link QosRequestStatus}. Result list will be the same 11441 * length as the input list, and each status code will correspond to 11442 * the policy at that index in the input list. 11443 * 11444 * @throws SecurityException if caller does not have the required permissions. 11445 * @throws NullPointerException if the caller provided a null input. 11446 * @throws UnsupportedOperationException if the feature is not enabled. 11447 * @throws IllegalArgumentException if the input list is invalid. 11448 * @hide 11449 */ 11450 @SystemApi 11451 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11452 @RequiresPermission(anyOf = { 11453 android.Manifest.permission.NETWORK_SETTINGS, 11454 MANAGE_WIFI_NETWORK_SELECTION 11455 }) addQosPolicies(@onNull List<QosPolicyParams> policyParamsList, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<List<Integer>> resultsCallback)11456 public void addQosPolicies(@NonNull List<QosPolicyParams> policyParamsList, 11457 @NonNull @CallbackExecutor Executor executor, 11458 @NonNull Consumer<List<Integer>> resultsCallback) { 11459 Objects.requireNonNull(policyParamsList, "policyParamsList cannot be null"); 11460 Objects.requireNonNull(executor, "executor cannot be null"); 11461 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 11462 try { 11463 mService.addQosPolicies(policyParamsList, new Binder(), mContext.getOpPackageName(), 11464 new IListListener.Stub() { 11465 @Override 11466 public void onResult(List value) { 11467 Binder.clearCallingIdentity(); 11468 executor.execute(() -> { 11469 resultsCallback.accept(value); 11470 }); 11471 } 11472 }); 11473 } catch (RemoteException e) { 11474 throw e.rethrowFromSystemServer(); 11475 } 11476 } 11477 11478 /** 11479 * Remove a list of existing application-initiated QoS policies, previously added via 11480 * {@link #addQosPolicies(List, Executor, Consumer)}. 11481 * 11482 * Note: Policies are identified by their policy IDs, which are assigned by the caller. The ID 11483 * for a given policy can be retrieved using {@link QosPolicyParams#getPolicyId()}. 11484 * 11485 * @param policyIdList List of policy IDs corresponding to the policies to remove. Must have 11486 * a maximum length of {@link #getMaxNumberOfPoliciesPerQosRequest()}. 11487 * @throws SecurityException if caller does not have the required permissions. 11488 * @throws NullPointerException if the caller provided a null input. 11489 * @throws IllegalArgumentException if the input list is invalid. 11490 * @hide 11491 */ 11492 @SystemApi 11493 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11494 @RequiresPermission(anyOf = { 11495 android.Manifest.permission.NETWORK_SETTINGS, 11496 MANAGE_WIFI_NETWORK_SELECTION 11497 }) removeQosPolicies(@onNull int[] policyIdList)11498 public void removeQosPolicies(@NonNull int[] policyIdList) { 11499 Objects.requireNonNull(policyIdList, "policyIdList cannot be null"); 11500 try { 11501 mService.removeQosPolicies(policyIdList, mContext.getOpPackageName()); 11502 } catch (RemoteException e) { 11503 throw e.rethrowFromSystemServer(); 11504 } 11505 } 11506 11507 /** 11508 * Remove all application-initiated QoS policies requested by this caller, 11509 * previously added via {@link #addQosPolicies(List, Executor, Consumer)}. 11510 * 11511 * @throws SecurityException if caller does not have the required permissions. 11512 * @hide 11513 */ 11514 @SystemApi 11515 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11516 @RequiresPermission(anyOf = { 11517 android.Manifest.permission.NETWORK_SETTINGS, 11518 MANAGE_WIFI_NETWORK_SELECTION 11519 }) removeAllQosPolicies()11520 public void removeAllQosPolicies() { 11521 try { 11522 mService.removeAllQosPolicies(mContext.getOpPackageName()); 11523 } catch (RemoteException e) { 11524 throw e.rethrowFromSystemServer(); 11525 } 11526 } 11527 11528 /** 11529 * Set the link layer stats polling interval, in milliseconds. 11530 * 11531 * @param intervalMs a non-negative integer, for the link layer stats polling interval 11532 * in milliseconds. 11533 * To set a fixed interval, use a positive value. 11534 * For automatic handling of the interval, use value 0 11535 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 11536 * @throws SecurityException if the caller does not have permission. 11537 * @throws IllegalArgumentException if input is invalid. 11538 * @hide 11539 */ 11540 @SystemApi 11541 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11542 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) setLinkLayerStatsPollingInterval(@ntRange from = 0) int intervalMs)11543 public void setLinkLayerStatsPollingInterval(@IntRange (from = 0) int intervalMs) { 11544 try { 11545 mService.setLinkLayerStatsPollingInterval(intervalMs); 11546 } catch (RemoteException e) { 11547 throw e.rethrowFromSystemServer(); 11548 } 11549 } 11550 11551 /** 11552 * Get the link layer stats polling interval, in milliseconds. 11553 * 11554 * @param executor The executor on which callback will be invoked. 11555 * @param resultsCallback An asynchronous callback that will return current 11556 * link layer stats polling interval in milliseconds. 11557 * 11558 * @throws UnsupportedOperationException if the API is not supported on this SDK version. 11559 * @throws SecurityException if the caller does not have permission. 11560 * @throws NullPointerException if the caller provided invalid inputs. 11561 * @hide 11562 */ 11563 @SystemApi 11564 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 11565 @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) getLinkLayerStatsPollingInterval(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)11566 public void getLinkLayerStatsPollingInterval(@NonNull @CallbackExecutor Executor executor, 11567 @NonNull Consumer<Integer> resultsCallback) { 11568 Objects.requireNonNull(executor, "executor cannot be null"); 11569 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 11570 try { 11571 mService.getLinkLayerStatsPollingInterval( 11572 new IIntegerListener.Stub() { 11573 @Override 11574 public void onResult(int value) { 11575 Binder.clearCallingIdentity(); 11576 executor.execute(() -> { 11577 resultsCallback.accept(value); 11578 }); 11579 } 11580 }); 11581 } catch (RemoteException e) { 11582 throw e.rethrowFromSystemServer(); 11583 } 11584 } 11585 11586 /** 11587 * This API allows a privileged application to set Multi-Link Operation mode. 11588 * 11589 * Multi-link operation (MLO) will allow Wi-Fi devices to operate on multiple links at the same 11590 * time through a single connection, aiming to support applications that require lower latency, 11591 * and higher capacity. Chip vendors have algorithms that run on the chip to use available links 11592 * based on incoming traffic and various inputs. This API allows system application to give a 11593 * suggestion to such algorithms on its preference using {@link MloMode}. 11594 * 11595 * 11596 * @param mode Refer {@link MloMode} for supported modes. 11597 * @param executor The executor on which callback will be invoked. 11598 * @param resultsCallback An asynchronous callback that will return {@code Boolean} indicating 11599 * whether the MLO mode is successfully set or not. 11600 * @throws IllegalArgumentException if mode value is not in {@link MloMode}. 11601 * @throws NullPointerException if the caller provided a null input. 11602 * @throws SecurityException if caller does not have the required permissions. 11603 * @throws UnsupportedOperationException if the set operation is not supported on this SDK. 11604 * @hide 11605 */ 11606 @SystemApi 11607 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11608 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) setMloMode(@loMode int mode, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> resultsCallback)11609 public void setMloMode(@MloMode int mode, @NonNull @CallbackExecutor Executor executor, 11610 @NonNull Consumer<Boolean> resultsCallback) { 11611 11612 if (mode < MLO_MODE_DEFAULT || mode > MLO_MODE_LOW_POWER) { 11613 throw new IllegalArgumentException("invalid mode: " + mode); 11614 } 11615 Objects.requireNonNull(executor, "executor cannot be null"); 11616 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 11617 try { 11618 mService.setMloMode(mode, new IBooleanListener.Stub() { 11619 @Override 11620 public void onResult(boolean value) { 11621 Binder.clearCallingIdentity(); 11622 executor.execute(() -> { 11623 resultsCallback.accept(value); 11624 }); 11625 } 11626 }); 11627 } catch (RemoteException e) { 11628 throw e.rethrowFromSystemServer(); 11629 } 11630 } 11631 11632 /** 11633 * This API allows a privileged application to get Multi-Link Operation mode. Refer 11634 * {@link WifiManager#setMloMode(int, Executor, Consumer)} for more details. 11635 * 11636 * @param executor The executor on which callback will be invoked. 11637 * @param resultsCallback An asynchronous callback that will return current MLO mode. Returns 11638 * {@link MloMode#MLO_MODE_DEFAULT} if information is not available, 11639 * e.g. if the driver/firmware doesn't provide this information. 11640 * @throws NullPointerException if the caller provided a null input. 11641 * @throws SecurityException if caller does not have the required permissions. 11642 * @throws UnsupportedOperationException if the get operation is not supported on this SDK. 11643 * @hide 11644 */ 11645 @SystemApi 11646 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11647 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getMloMode(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)11648 public void getMloMode(@NonNull @CallbackExecutor Executor executor, 11649 @NonNull Consumer<Integer> resultsCallback) { 11650 Objects.requireNonNull(executor, "executor cannot be null"); 11651 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 11652 try { 11653 mService.getMloMode(new IIntegerListener.Stub() { 11654 @Override 11655 public void onResult(int value) { 11656 Binder.clearCallingIdentity(); 11657 executor.execute(() -> { 11658 resultsCallback.accept(value); 11659 }); 11660 } 11661 }); 11662 } catch (RemoteException e) { 11663 throw e.rethrowFromSystemServer(); 11664 } 11665 } 11666 11667 /** 11668 * Get the maximum number of links supported by the chip for MLO association. e.g. if the Wi-Fi 11669 * chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous Transmit and 11670 * Receive) with following capabilities, 11671 * - Max MLO assoc link count = 3. 11672 * - Max MLO STR link count = 2. See 11673 * {@link WifiManager#getMaxMloStrLinkCount(Executor, Consumer)} 11674 * One of the possible configuration is - STR (2.4 GHz , eMLSR(5 GHz, 6 GHz)), provided the 11675 * radio combination of the chip supports it. 11676 * 11677 * @param executor The executor on which callback will be invoked. 11678 * @param resultsCallback An asynchronous callback that will return maximum MLO association link 11679 * count supported by the chip or -1 if error or not available. 11680 * @throws NullPointerException if the caller provided a null input. 11681 * @throws SecurityException if caller does not have the required permissions. 11682 * @throws UnsupportedOperationException if the get operation is not supported on this SDK. 11683 * @hide 11684 */ 11685 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11686 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getMaxMloAssociationLinkCount(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)11687 public void getMaxMloAssociationLinkCount(@NonNull @CallbackExecutor Executor executor, 11688 @NonNull Consumer<Integer> resultsCallback) { 11689 Objects.requireNonNull(executor, "executor cannot be null"); 11690 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 11691 try { 11692 Bundle extras = new Bundle(); 11693 if (SdkLevel.isAtLeastS()) { 11694 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 11695 mContext.getAttributionSource()); 11696 } 11697 mService.getMaxMloAssociationLinkCount(new IIntegerListener.Stub() { 11698 @Override 11699 public void onResult(int value) { 11700 Binder.clearCallingIdentity(); 11701 executor.execute(() -> { 11702 resultsCallback.accept(value); 11703 }); 11704 } 11705 }, extras); 11706 } catch (RemoteException e) { 11707 throw e.rethrowFromSystemServer(); 11708 } 11709 } 11710 11711 /** 11712 * Get the maximum number of STR links used in Multi-Link Operation. The maximum number of STR 11713 * links used for MLO can be different from the number of radios supported by the chip. e.g. if 11714 * the Wi-Fi chip supports eMLSR (Enhanced Multi-Link Single Radio) and STR (Simultaneous 11715 * Transmit and Receive) with following capabilities, 11716 * - Max MLO assoc link count = 3. See 11717 * {@link WifiManager#getMaxMloAssociationLinkCount(Executor, Consumer)}. 11718 * - Max MLO STR link count = 2. 11719 * One of the possible configuration is - STR (2.4 GHz, eMLSR(5 GHz, 6 GHz)), provided the radio 11720 * combination of the chip supports it. 11721 * 11722 * @param executor The executor on which callback will be invoked. 11723 * @param resultsCallback An asynchronous callback that will return maximum STR link count 11724 * supported by the chip in MLO mode or -1 if error or not available. 11725 * @throws NullPointerException if the caller provided a null input. 11726 * @throws SecurityException if caller does not have the required permissions. 11727 * @throws UnsupportedOperationException if the get operation is not supported on this SDK 11728 * @hide 11729 */ 11730 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11731 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getMaxMloStrLinkCount(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Integer> resultsCallback)11732 public void getMaxMloStrLinkCount(@NonNull @CallbackExecutor Executor executor, 11733 @NonNull Consumer<Integer> resultsCallback) { 11734 Objects.requireNonNull(executor, "executor cannot be null"); 11735 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 11736 try { 11737 Bundle extras = new Bundle(); 11738 if (SdkLevel.isAtLeastS()) { 11739 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 11740 mContext.getAttributionSource()); 11741 } 11742 mService.getMaxMloStrLinkCount(new IIntegerListener.Stub() { 11743 @Override 11744 public void onResult(int value) { 11745 Binder.clearCallingIdentity(); 11746 executor.execute(() -> { 11747 resultsCallback.accept(value); 11748 }); 11749 } 11750 }, extras); 11751 } catch (RemoteException e) { 11752 throw e.rethrowFromSystemServer(); 11753 } 11754 } 11755 11756 /** 11757 * Get the set of band combinations supported simultaneously by the Wi-Fi Chip. 11758 * 11759 * Note: This method returns simultaneous band operation combination and not multichannel 11760 * concurrent operation (MCC) combination. 11761 * 11762 * @param executor The executor on which callback will be invoked. 11763 * @param resultsCallback An asynchronous callback that will return a list of possible 11764 * simultaneous band combinations supported by the chip or empty list if 11765 * not available. Band value is defined in {@link WifiScanner.WifiBand}. 11766 * @throws NullPointerException if the caller provided a null input. 11767 * @throws SecurityException if caller does not have the required permissions. 11768 * @throws UnsupportedOperationException if the get operation is not supported on this SDK. 11769 * @hide 11770 */ 11771 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 11772 @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION) getSupportedSimultaneousBandCombinations( @onNull @allbackExecutor Executor executor, @NonNull Consumer<List<int[]>> resultsCallback)11773 public void getSupportedSimultaneousBandCombinations( 11774 @NonNull @CallbackExecutor Executor executor, 11775 @NonNull Consumer<List<int[]>> resultsCallback) { 11776 Objects.requireNonNull(executor, "executor cannot be null"); 11777 Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); 11778 try { 11779 Bundle extras = new Bundle(); 11780 if (SdkLevel.isAtLeastS()) { 11781 extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, 11782 mContext.getAttributionSource()); 11783 } 11784 mService.getSupportedSimultaneousBandCombinations(new IWifiBandsListener.Stub() { 11785 @Override 11786 public void onResult(WifiBands[] supportedBands) { 11787 Binder.clearCallingIdentity(); 11788 List<int[]> bandCombinations = new ArrayList<>(); 11789 for (WifiBands wifiBands : supportedBands) { 11790 bandCombinations.add(wifiBands.bands); 11791 } 11792 executor.execute(() -> { 11793 resultsCallback.accept(bandCombinations); 11794 }); 11795 } 11796 }, extras); 11797 } catch (RemoteException e) { 11798 throw e.rethrowFromSystemServer(); 11799 } 11800 } 11801 }