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